Post-quantum crypto and better useragent security #80

Merged
Skipper merged 4 commits from push-xrxykvkuxpsv into main 2026-04-07 19:26:55 +00:00
19 changed files with 68 additions and 84 deletions
Showing only changes of commit a9f9fc2a9d - Show all commits

View File

@@ -1,3 +1,4 @@
use arbiter_crypto::authn::{CLIENT_CONTEXT, SigningKey, format_challenge};
use arbiter_proto::{
ClientMetadata,
proto::{
@@ -14,7 +15,6 @@ use arbiter_proto::{
shared::ClientInfo as ProtoClientInfo,
},
};
use arbiter_crypto::authn::{CLIENT_CONTEXT, PublicKey, Signature, SigningKey, format_challenge};
use crate::{
storage::StorageError,

View File

@@ -1,7 +1,5 @@
#[cfg(feature = "authn")]
pub mod authn;
#[cfg(feature = "safecell")]
pub mod safecell;
pub mod safecell;

View File

@@ -107,7 +107,7 @@ fn abort_memory_breach(action: &str, err: &memsafe::error::MemoryError) -> ! {
eprintln!("fatal {action}: {err}");
// SAFETY: Intentionally cause a segmentation fault to prevent further execution in a compromised state.
unsafe {
let unsafe_pointer = 0x0 as *mut u8;
let unsafe_pointer = std::ptr::null_mut::<u8>();
std::ptr::write_volatile(unsafe_pointer, 0);
}
std::process::abort();

View File

@@ -1,8 +1,6 @@
pub mod transport;
pub mod url;
use base64::{Engine, prelude::BASE64_STANDARD};
pub mod proto {
tonic::include_proto!("arbiter");

View File

@@ -7,11 +7,11 @@ use kameo::{Actor, actor::ActorRef, messages};
use rand::{SeedableRng, rng, rngs::StdRng};
use crate::{
actors::keyholder::{CreateNew, Decrypt, GetState, KeyHolder, KeyHolderState},
actors::keyholder::{CreateNew, Decrypt, KeyHolder},
crypto::integrity,
db::{
DatabaseError, DatabasePool,
models::{self, SqliteTimestamp},
models::{self},
schema,
},
evm::{
@@ -21,7 +21,6 @@ use crate::{
ether_transfer::EtherTransfer, token_transfers::TokenTransfer,
},
},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
@@ -159,7 +158,7 @@ impl EvmActor {
}
#[message]
pub async fn useragent_delete_grant(&mut self, grant_id: i32) -> Result<(), Error> {
pub async fn useragent_delete_grant(&mut self, _grant_id: i32) -> Result<(), Error> {
// let mut conn = self.db.get().await.map_err(DatabaseError::from)?;
// let keyholder = self.keyholder.clone();

View File

@@ -9,19 +9,15 @@ use kameo::{Actor, Reply, messages};
use strum::{EnumDiscriminants, IntoDiscriminant};
use tracing::{error, info};
use crate::{
crypto::{
KeyCell, derive_key,
encryption::v1::{self, Nonce},
integrity::v1::HmacSha256,
},
use crate::crypto::{
KeyCell, derive_key,
encryption::v1::{self, Nonce},
integrity::v1::HmacSha256,
};
use crate::{
db::{
self,
models::{self, RootKeyHistory},
schema::{self},
},
use crate::db::{
self,
models::{self, RootKeyHistory},
schema::{self},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
@@ -399,9 +395,7 @@ mod tests {
use diesel_async::RunQueryDsl;
use crate::{
db::{self},
};
use crate::db::{self};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use super::*;

View File

@@ -1,5 +1,5 @@
use arbiter_crypto::authn::{self, USERAGENT_CONTEXT};
use arbiter_proto::{transport::Bi};
use arbiter_proto::transport::Bi;
use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl, update};
use diesel_async::{AsyncConnection, RunQueryDsl};
use kameo::actor::ActorRef;
@@ -183,7 +183,7 @@ async fn register_key(
nonce: NONCE_START,
};
integrity::sign_entity(conn, &keyholder, &entity, id)
integrity::sign_entity(conn, keyholder, &entity, id)
.await
.map_err(|e| {
error!(error = ?e, "Failed to sign integrity tag for new user-agent key");

View File

@@ -5,7 +5,6 @@ use crate::{
};
use arbiter_crypto::authn;
#[derive(Debug)]
pub struct UserAgentCredentials {
pub pubkey: authn::PublicKey,

View File

@@ -1,7 +1,10 @@
use std::sync::Mutex;
use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature};
use arbiter_crypto::{authn, safecell::{SafeCell, SafeCellHandle as _}};
use arbiter_crypto::{
authn,
safecell::{SafeCell, SafeCellHandle as _},
};
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper};
use diesel_async::{AsyncConnection, RunQueryDsl};
@@ -14,23 +17,21 @@ use x25519_dalek::{EphemeralSecret, PublicKey};
use crate::actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer;
use crate::actors::keyholder::KeyHolderState;
use crate::actors::user_agent::session::Error;
use crate::actors::{
evm::{
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
UseragentCreateGrant, UseragentListGrants,
},
keyholder::{self, Bootstrap, TryUnseal},
user_agent::session::{
UserAgentSession,
state::{UnsealContext, UserAgentEvents, UserAgentStates},
},
};
use crate::db::models::{
EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata,
};
use crate::evm::policies::{Grant, SpecificGrant};
use crate::{
actors::{
evm::{
ClientSignTransaction, Generate, ListWallets, SignTransactionError as EvmSignError,
UseragentCreateGrant, UseragentDeleteGrant, UseragentListGrants,
},
keyholder::{self, Bootstrap, TryUnseal},
user_agent::session::{
UserAgentSession,
state::{UnsealContext, UserAgentEvents, UserAgentStates},
},
},
};
impl UserAgentSession {
fn take_unseal_secret(&mut self) -> Result<(EphemeralSecret, PublicKey), Error> {
@@ -360,19 +361,21 @@ impl UserAgentSession {
&mut self,
grant_id: i32,
) -> Result<(), GrantMutationError> {
match self
.props
.actors
.evm
.ask(UseragentDeleteGrant { grant_id })
.await
{
Ok(()) => Ok(()),
Err(err) => {
error!(?err, "EVM grant delete failed");
Err(GrantMutationError::Internal)
}
}
// match self
// .props
// .actors
// .evm
// .ask(UseragentDeleteGrant { grant_id })
// .await
// {
// Ok(()) => Ok(()),
// Err(err) => {
// error!(?err, "EVM grant delete failed");
// Err(GrantMutationError::Internal)
// }
// }
let _ = grant_id;
todo!()
}
#[message]

View File

@@ -59,9 +59,7 @@ mod tests {
use std::ops::Deref as _;
use super::*;
use crate::{
crypto::derive_key
};
use crate::crypto::derive_key;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
#[test]

View File

@@ -1,7 +1,5 @@
use crate::{
actors::keyholder, crypto::integrity::hashing::Hashable
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use crate::{actors::keyholder, crypto::integrity::hashing::Hashable};
use arbiter_crypto::safecell::SafeCellHandle as _;
use hmac::{Hmac, Mac as _};
use sha2::Sha256;
@@ -128,7 +126,7 @@ pub async fn sign_entity<E: Integrable>(
insert_into(integrity_envelope::table)
.values(NewIntegrityEnvelope {
entity_kind: E::KIND.to_owned(),
entity_id: entity_id,
entity_id,
payload_version: E::VERSION,
key_version,
mac: mac.to_vec(),
@@ -205,20 +203,19 @@ mod tests {
use diesel::{ExpressionMethods as _, QueryDsl};
use diesel_async::RunQueryDsl;
use kameo::{actor::ActorRef, prelude::Spawn};
use rand::seq::SliceRandom;
use sha2::Digest;
use proptest::prelude::*;
use crate::{
actors::keyholder::{Bootstrap, KeyHolder},
db::{self, schema},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use super::{Error, Integrable, sign_entity, verify_entity};
use super::{hashing::Hashable, payload_hash};
use super::hashing::Hashable;
#[derive(Clone)]
struct DummyEntity {

View File

@@ -62,10 +62,10 @@ impl<T: Hashable> Hashable for Option<T> {
fn hash<H: Digest>(&self, hasher: &mut H) {
match self {
Some(value) => {
hasher.update(&[1]);
hasher.update([1]);
value.hash(hasher);
}
None => hasher.update(&[0]),
None => hasher.update([0]),
}
}
}
@@ -96,12 +96,12 @@ impl Hashable for alloy::primitives::U256 {
impl Hashable for chrono::Duration {
fn hash<H: Digest>(&self, hasher: &mut H) {
hasher.update(&self.num_seconds().to_be_bytes());
hasher.update(self.num_seconds().to_be_bytes());
}
}
impl Hashable for chrono::DateTime<chrono::Utc> {
fn hash<H: Digest>(&self, hasher: &mut H) {
hasher.update(&self.timestamp_millis().to_be_bytes());
hasher.update(self.timestamp_millis().to_be_bytes());
}
}

View File

@@ -1,12 +1,12 @@
use std::sync::Mutex;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use alloy::{
consensus::SignableTransaction,
network::{TxSigner, TxSignerSync},
primitives::{Address, B256, ChainId, Signature},
signers::{Error, Result, Signer, SignerSync, utils::secret_key_to_address},
};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use async_trait::async_trait;
use k256::ecdsa::{self, RecoveryId, SigningKey, signature::hazmat::PrehashSigner};

View File

@@ -1,9 +1,9 @@
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_proto::transport::{Bi, Error, Receiver, Sender};
use arbiter_server::{
actors::keyholder::KeyHolder,
db::{self, schema},
};
use arbiter_crypto::{authn::{self, format_challenge, CLIENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use async_trait::async_trait;
use diesel::QueryDsl;

View File

@@ -1,11 +1,10 @@
use std::collections::{HashMap, HashSet};
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{
actors::keyholder::{CreateNew, Error, KeyHolder},
db::{self, models, schema},
};
use arbiter_crypto::{authn::{self, format_challenge, CLIENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::sql_query};
use diesel_async::RunQueryDsl;

View File

@@ -1,9 +1,9 @@
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{
actors::keyholder::{Error, KeyHolder},
crypto::encryption::v1::{Nonce, ROOT_KEY_TAG},
db::{self, models, schema},
};
use arbiter_crypto::{authn::{self, format_challenge, CLIENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use diesel::{QueryDsl, SelectableHelper};
use diesel_async::RunQueryDsl;

View File

@@ -1,12 +1,11 @@
use std::collections::HashSet;
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{
actors::keyholder::Error,
crypto::encryption::v1::Nonce,
db::{self, models, schema},
};
use arbiter_crypto::{authn::{self, format_challenge, CLIENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::update};
use diesel_async::RunQueryDsl;

View File

@@ -1,4 +1,7 @@
use arbiter_crypto::{authn::{self, format_challenge, USERAGENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use arbiter_crypto::{
authn::{self, USERAGENT_CONTEXT, format_challenge},
safecell::{SafeCell, SafeCellHandle as _},
};
use arbiter_proto::transport::{Receiver, Sender};
use arbiter_server::{

View File

@@ -1,3 +1,4 @@
use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _};
use arbiter_server::{
actors::{
GlobalActors,
@@ -8,13 +9,9 @@ use arbiter_server::{
},
},
db,
};
use arbiter_crypto::{authn::{self, format_challenge, CLIENT_CONTEXT}, safecell::{SafeCell, SafeCellHandle as _}};
use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit};
use diesel::{ExpressionMethods as _, QueryDsl as _, insert_into};
use diesel_async::RunQueryDsl;
use kameo::actor::Spawn as _;
use x25519_dalek::{EphemeralSecret, PublicKey};