This commit is contained in:
jonesmarvin8 2026-05-20 16:36:24 -04:00
parent 8253002739
commit 8492f995df
33 changed files with 57 additions and 37 deletions

26
Cargo.lock generated
View File

@ -674,9 +674,9 @@ checksum = "4858a9d740c5007a9069007c3b4e91152d0506f13c1b31dd49051fd537656156"
[[package]]
name = "astral-tokio-tar"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ce73b17c62717c4b6a9af10b43e87c578b0cac27e00666d48304d3b7d2c0693"
checksum = "cb50a7aae84a03bf55b067832bc376f4961b790c97e64d3eacee97d389b90277"
dependencies = [
"filetime",
"futures-core",
@ -1972,7 +1972,6 @@ dependencies = [
"anyhow",
"key_protocol",
"nssa_core",
"rand 0.8.5",
"serde",
"serde_json",
]
@ -2134,7 +2133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de"
dependencies = [
"data-encoding",
"syn 2.0.117",
"syn 1.0.109",
]
[[package]]
@ -2318,7 +2317,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -2649,7 +2648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -3629,7 +3628,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.3",
"socket2 0.5.10",
"tokio",
"tower-service",
"tracing",
@ -6479,7 +6478,6 @@ dependencies = [
"bytemuck",
"bytesize",
"chacha20",
"k256",
"ml-kem",
"risc0-zkvm",
"serde",
@ -6494,7 +6492,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -7358,7 +7356,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.6.3",
"socket2 0.5.10",
"thiserror 2.0.18",
"tokio",
"tracing",
@ -7395,7 +7393,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.6.3",
"socket2 0.5.10",
"tracing",
"windows-sys 0.59.0",
]
@ -8292,7 +8290,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -9283,7 +9281,7 @@ dependencies = [
"getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -10586,7 +10584,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -107,10 +107,9 @@ async fn group_invite_join_key_agreement() -> Result<()> {
.key_chain()
.sealing_secret_key()
.context("Sealing key not found")?;
let sealing_pk =
key_protocol::key_management::group_key_holder::SealingPublicKey::from_bytes(
nssa_core::encryption::ViewingPublicKey::from_seed(&sealing_sk.d, &sealing_sk.r).0,
);
let sealing_pk = key_protocol::key_management::group_key_holder::SealingPublicKey::from_bytes(
nssa_core::encryption::ViewingPublicKey::from_seed(&sealing_sk.d, &sealing_sk.r).0,
);
let holder = ctx
.wallet()

View File

@ -16,7 +16,6 @@ thiserror.workspace = true
bytemuck.workspace = true
bytesize.workspace = true
base58.workspace = true
k256 = { workspace = true, optional = true }
ml-kem = { workspace = true, optional = true, features = ["getrandom"] }
chacha20 = { version = "0.10" }
@ -25,4 +24,4 @@ serde_json.workspace = true
[features]
default = []
host = ["dep:k256", "dep:ml-kem"]
host = ["dep:ml-kem"]

View File

@ -156,7 +156,7 @@ mod tests {
}
/// Verifies the full account-note pipeline: ML-KEM-768 encapsulation/decapsulation
/// feeds the correct shared secret into the SHA-256 KDF and ChaCha20 round-trip.
/// feeds the correct shared secret into the SHA-256 KDF and `ChaCha20` round-trip.
#[cfg(feature = "host")]
#[test]
fn kem_to_chacha20_round_trip() {

View File

@ -10,7 +10,18 @@ use crate::SharedSecretKey;
pub struct EphemeralPublicKey(pub Vec<u8>);
/// ML-KEM-768 encapsulation key bytes (1184 bytes, opaque to this crate).
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, BorshSerialize, BorshDeserialize)]
#[derive(
Serialize,
Deserialize,
Clone,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
BorshSerialize,
BorshDeserialize,
)]
pub struct ViewingPublicKey(pub Vec<u8>);
impl ViewingPublicKey {
@ -73,8 +84,8 @@ impl SharedSecretKey {
input.extend_from_slice(message_hash);
input.extend_from_slice(&output_index.to_le_bytes());
let hash = Impl::hash_bytes(&input);
let m: ml_kem::B32 = ml_kem::array::Array::try_from(hash.as_bytes())
.expect("SHA-256 output is 32 bytes");
let m: ml_kem::B32 =
ml_kem::array::Array::try_from(hash.as_bytes()).expect("SHA-256 output is 32 bytes");
let ek_bytes: ml_kem::kem::Key<ml_kem::EncapsulationKey768> = vpk
.0

View File

@ -2,11 +2,10 @@ use common::PINATA_BASE58;
use key_protocol::key_management::{
KeyChain,
key_tree::chain_index::ChainIndex,
secret_holders::{PrivateKeyHolder, SecretSpendingKey},
secret_holders::{PrivateKeyHolder, SecretSpendingKey, ViewingSecretKey},
};
use nssa::{Account, AccountId, Data, PrivateKey, PublicKey, V03State};
use nssa_core::{NullifierPublicKey, encryption::ViewingPublicKey};
use key_protocol::key_management::secret_holders::ViewingSecretKey;
use serde::{Deserialize, Serialize};
const PRIVATE_KEY_PUB_ACC_A: [u8; 32] = [
@ -49,8 +48,6 @@ const VSK_PRIV_ACC_B: [u8; 32] = [
154, 161, 34, 208, 74, 27, 1, 119, 13, 88, 128,
];
const NPK_PRIV_ACC_A: [u8; 32] = [
167, 108, 50, 153, 74, 47, 151, 188, 140, 79, 195, 31, 181, 9, 40, 167, 201, 32, 175, 129, 45,
245, 223, 193, 210, 170, 247, 128, 167, 140, 155, 129,
@ -129,7 +126,10 @@ pub fn initial_priv_accounts_private_keys() -> Vec<PrivateAccountPrivateInitialD
secret_spending_key: SecretSpendingKey(SSK_PRIV_ACC_A),
private_key_holder: PrivateKeyHolder {
nullifier_secret_key: NSK_PRIV_ACC_A,
viewing_secret_key: ViewingSecretKey { d: VSK_PRIV_ACC_A, r: [0_u8; 32] },
viewing_secret_key: ViewingSecretKey {
d: VSK_PRIV_ACC_A,
r: [0_u8; 32],
},
},
nullifier_public_key: NullifierPublicKey(NPK_PRIV_ACC_A),
viewing_public_key: ViewingPublicKey::from_seed(&VSK_PRIV_ACC_A, &[0_u8; 32]),
@ -139,7 +139,10 @@ pub fn initial_priv_accounts_private_keys() -> Vec<PrivateAccountPrivateInitialD
secret_spending_key: SecretSpendingKey(SSK_PRIV_ACC_B),
private_key_holder: PrivateKeyHolder {
nullifier_secret_key: NSK_PRIV_ACC_B,
viewing_secret_key: ViewingSecretKey { d: VSK_PRIV_ACC_B, r: [0_u8; 32] },
viewing_secret_key: ViewingSecretKey {
d: VSK_PRIV_ACC_B,
r: [0_u8; 32],
},
},
nullifier_public_key: NullifierPublicKey(NPK_PRIV_ACC_B),
viewing_public_key: ViewingPublicKey::from_seed(&VSK_PRIV_ACC_B, &[0_u8; 32]),

View File

@ -15,4 +15,3 @@ nssa_core = { workspace = true, features = ["host"] }
anyhow.workspace = true
serde.workspace = true
serde_json.workspace = true
rand = { workspace = true }

View File

@ -86,9 +86,13 @@ fn main() -> Result<()> {
// ML-KEM-768 encapsulation (replaces the old ECDH scalar multiplication).
let recipient_kc = KeyChain::new_os_random();
let vpk = recipient_kc.viewing_public_key;
results.push(time("SharedSecretKey::encapsulate (sender KEM)", ITERS, || {
let (_ssk, _epk) = SharedSecretKey::encapsulate(&vpk);
}));
results.push(time(
"SharedSecretKey::encapsulate (sender KEM)",
ITERS,
|| {
let (_ssk, _epk) = SharedSecretKey::encapsulate(&vpk);
},
));
// EncryptionScheme::encrypt / decrypt over a small Account note.
let account = Account::default();

View File

@ -1,6 +1,9 @@
use anyhow::{Context as _, Result};
use clap::Subcommand;
use key_protocol::key_management::{group_key_holder::{GroupKeyHolder, SealingPublicKey}, secret_holders::ViewingSecretKey};
use key_protocol::key_management::{
group_key_holder::{GroupKeyHolder, SealingPublicKey},
secret_holders::ViewingSecretKey,
};
use crate::{
WalletCore,

View File

@ -266,7 +266,10 @@ impl WalletCore {
}
/// Set the wallet's dedicated sealing secret key.
pub const fn set_sealing_secret_key(&mut self, key: key_protocol::key_management::secret_holders::ViewingSecretKey) {
pub const fn set_sealing_secret_key(
&mut self,
key: key_protocol::key_management::secret_holders::ViewingSecretKey,
) {
self.storage.key_chain_mut().set_sealing_secret_key(key);
}
@ -766,7 +769,8 @@ impl WalletCore {
continue;
}
let shared_secret = SharedSecretKey::decapsulate(&encrypted_data.epk, &vsk.d, &vsk.r);
let shared_secret =
SharedSecretKey::decapsulate(&encrypted_data.epk, &vsk.d, &vsk.r);
let commitment = &tx.message.new_commitments[ciph_id];
if let Some((_kind, new_acc)) = nssa_core::EncryptionScheme::decrypt(