From 72063ae8ed72ba5f478ade6b75f4d15b07067874 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:34:04 +0100 Subject: [PATCH 01/10] add test_new_os_random --- accounts/src/key_management/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 42988a2..20342f3 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -77,9 +77,24 @@ impl AddressKeyHolder { mod tests { use constants_types::{NULLIFIER_SECRET_CONST, VIEVING_SECRET_CONST}; use elliptic_curve::group::GroupEncoding; + use aes_gcm::{Aes256Gcm, aead::{Aead, KeyInit, OsRng}}; + use k256::{AffinePoint, ProjectivePoint, Scalar}; + use constants_types::{CipherText, Nonce}; + use elliptic_curve::group::prime::PrimeCurveAffine; + use elliptic_curve::ff::Field; use super::*; + #[test] + fn test_new_os_random() { + // Ensure that a new AddressKeyHolder instance can be created without errors. + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Check that key holder fields are initialized with expected types + assert!(!Into::::into(address_key_holder.nullifer_public_key.is_identity())); + assert!(!Into::::into(address_key_holder.viewing_public_key.is_identity())); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From 210da1c672f0ec6038597645b1e4deeb2c0ba999 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:34:34 +0100 Subject: [PATCH 02/10] add test_calculate_shared_secret_receiver --- accounts/src/key_management/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 20342f3..f8d1bc9 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -95,6 +95,21 @@ mod tests { assert!(!Into::::into(address_key_holder.viewing_public_key.is_identity())); } + #[test] + fn test_calculate_shared_secret_receiver() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Generate a random ephemeral public key sender + let scalar = Scalar::random(&mut OsRng); + let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); + + // Calculate shared secret + let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + + // Ensure the shared secret is not an identity point (suggesting non-zero output) + assert!(!Into::::into(shared_secret.is_identity())); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From 5a76f51fe5cb118027a614b940acbccd81298e27 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:35:00 +0100 Subject: [PATCH 03/10] add test_decrypt_data --- accounts/src/key_management/mod.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index f8d1bc9..87112b8 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -110,6 +110,35 @@ mod tests { assert!(!Into::::into(shared_secret.is_identity())); } + #[test] + fn test_decrypt_data() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Generate an ephemeral key and shared secret + let scalar = Scalar::random(OsRng); + let ephemeral_public_key_sender = address_key_holder.produce_ephemeral_key_holder().generate_ephemeral_public_key(); + let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + + // Prepare the encryption key from shared secret + let key_raw = shared_secret.to_bytes(); + let key_raw_adjust_pre = &key_raw.as_slice()[..32]; + let key_raw_adjust: [u8; 32] = key_raw_adjust_pre.try_into().unwrap(); + let key: Key = key_raw_adjust.into(); + + let cipher = Aes256Gcm::new(&key); + + // Encrypt sample data + let nonce = Nonce::from_slice(b"unique nonce"); + let plaintext = b"Sensitive data"; + let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + + // Attempt decryption + let decrypted_data: Vec = address_key_holder.decrypt_data(ephemeral_public_key_sender, CipherText::from(ciphertext), nonce.clone()); + + // Verify decryption is successful and matches original plaintext + assert_eq!(decrypted_data, plaintext); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From 5dba3856bf515aa8efbbda6455af6af21f2bf460 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:35:42 +0100 Subject: [PATCH 04/10] bug fix --- accounts/src/key_management/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 87112b8..331ba71 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -62,13 +62,14 @@ impl AddressKeyHolder { nonce: Nonce, ) -> Vec { let key_point = self.calculate_shared_secret_receiver(ephemeral_public_key_sender); - let key_raw = key_point.to_bytes(); - let key_raw_adjust: [u8; 32] = key_raw.as_slice().try_into().unwrap(); - + let binding = key_point.to_bytes(); + let key_raw = &binding.as_slice()[..32]; + let key_raw_adjust: [u8; 32] = key_raw.try_into().unwrap(); + let key: Key = key_raw_adjust.into(); - + let cipher = Aes256Gcm::new(&key); - + cipher.decrypt(&nonce, ciphertext.as_slice()).unwrap() } } From 7d0ff2df300ace45032f889cf0b1fb396fcebab8 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:36:10 +0100 Subject: [PATCH 05/10] add test_new_os_random_initialization --- accounts/src/key_management/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 331ba71..4a27a58 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -140,6 +140,17 @@ mod tests { assert_eq!(decrypted_data, plaintext); } + #[test] + fn test_new_os_random_initialization() { + // Ensure that AddressKeyHolder is initialized correctly + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Check that key holder fields are initialized with expected types and values + assert!(!Into::::into(address_key_holder.nullifer_public_key.is_identity())); + assert!(!Into::::into(address_key_holder.viewing_public_key.is_identity())); + assert!(address_key_holder.address.as_slice().len() > 0); // Assume TreeHashType has non-zero length for a valid address + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From 31762ed4ebbb845b3a825cede677b0d0da812c41 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:36:36 +0100 Subject: [PATCH 06/10] add test_calculate_shared_secret_with_identity_point --- accounts/src/key_management/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 4a27a58..43a1c93 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -151,6 +151,20 @@ mod tests { assert!(address_key_holder.address.as_slice().len() > 0); // Assume TreeHashType has non-zero length for a valid address } + #[test] + fn test_calculate_shared_secret_with_identity_point() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Use identity point as ephemeral public key + let identity_point = AffinePoint::identity(); + + // Calculate shared secret + let shared_secret = address_key_holder.calculate_shared_secret_receiver(identity_point); + + // The shared secret with the identity point should also result in the identity point + assert!(Into::::into(shared_secret.is_identity())); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From ef29a16f67abc02aa769027078633c78279beae9 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:37:15 +0100 Subject: [PATCH 07/10] add test_decrypt_data_with_incorrect_nonce --- accounts/src/key_management/mod.rs | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 43a1c93..eb377ba 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -165,6 +165,41 @@ mod tests { assert!(Into::::into(shared_secret.is_identity())); } + #[test] + #[should_panic] + fn test_decrypt_data_with_incorrect_nonce() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Generate ephemeral public key and shared secret + let scalar = Scalar::random(OsRng); + let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); + let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + + // Prepare the encryption key from shared secret + let key_raw = shared_secret.to_bytes(); + let key_raw_adjust_pre = &key_raw.as_slice()[..32]; + let key_raw_adjust: [u8; 32] = key_raw_adjust_pre.try_into().unwrap(); + let key: Key = key_raw_adjust.into(); + + let cipher = Aes256Gcm::new(&key); + + // Encrypt sample data with a specific nonce + let nonce = Nonce::from_slice(b"unique nonce"); + let plaintext = b"Sensitive data"; + let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + + // Attempt decryption with an incorrect nonce + let incorrect_nonce = Nonce::from_slice(b"wrong nonce"); + let decrypted_data = address_key_holder.decrypt_data( + ephemeral_public_key_sender, + CipherText::from(ciphertext.clone()), + incorrect_nonce.clone(), + ); + + // The decryption should fail or produce incorrect output due to nonce mismatch + assert_ne!(decrypted_data, plaintext); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From b24ad55f31d8f5c41726fe5484310b8996fb09ac Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:37:49 +0100 Subject: [PATCH 08/10] add test_decrypt_data_with_incorrect_ciphertext --- accounts/src/key_management/mod.rs | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index eb377ba..517250f 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -200,6 +200,44 @@ mod tests { assert_ne!(decrypted_data, plaintext); } + #[test] + #[should_panic] + fn test_decrypt_data_with_incorrect_ciphertext() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Generate ephemeral public key and shared secret + let scalar = Scalar::random(OsRng); + let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); + let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + + // Prepare the encryption key from shared secret + let key_raw = shared_secret.to_bytes(); + let key_raw_adjust_pre = &key_raw.as_slice()[..32]; + let key_raw_adjust: [u8; 32] = key_raw_adjust_pre.try_into().unwrap(); + let key: Key = key_raw_adjust.into(); + + let cipher = Aes256Gcm::new(&key); + + // Encrypt sample data + let nonce = Nonce::from_slice(b"unique nonce"); + let plaintext = b"Sensitive data"; + let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + + // Tamper with the ciphertext to simulate corruption + let mut corrupted_ciphertext = ciphertext.clone(); + corrupted_ciphertext[0] ^= 1; // Flip a bit in the ciphertext + + // Attempt decryption + let result = address_key_holder.decrypt_data( + ephemeral_public_key_sender, + CipherText::from(corrupted_ciphertext), + nonce.clone(), + ); + + // The decryption should fail or produce incorrect output due to tampered ciphertext + assert_ne!(result, plaintext); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From f48541444fb88cf56558e62616d0b6780ae19a63 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:38:15 +0100 Subject: [PATCH 09/10] add test_encryption_decryption_round_trip --- accounts/src/key_management/mod.rs | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 517250f..0fab650 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -238,6 +238,39 @@ mod tests { assert_ne!(result, plaintext); } + #[test] + fn test_encryption_decryption_round_trip() { + let address_key_holder = AddressKeyHolder::new_os_random(); + + // Generate ephemeral key and shared secret + let scalar = Scalar::random(OsRng); + let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); + + // Encrypt sample data + let plaintext = b"Round-trip test data"; + let nonce = Nonce::from_slice(b"unique nonce"); + + let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + // Prepare the encryption key from shared secret + let key_raw = shared_secret.to_bytes(); + let key_raw_adjust_pre = &key_raw.as_slice()[..32]; + let key_raw_adjust: [u8; 32] = key_raw_adjust_pre.try_into().unwrap(); + let key: Key = key_raw_adjust.into(); + let cipher = Aes256Gcm::new(&key); + + let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + + // Decrypt the data using the `AddressKeyHolder` instance + let decrypted_data = address_key_holder.decrypt_data( + ephemeral_public_key_sender, + CipherText::from(ciphertext), + nonce.clone(), + ); + + // Verify the decrypted data matches the original plaintext + assert_eq!(decrypted_data, plaintext); + } + #[test] fn key_generation_test() { let seed_holder = SeedHolder::new_os_random(); From 051c563b7debc2934929aa3ef15e795cc13c0419 Mon Sep 17 00:00:00 2001 From: Rostyslav Tyshko Date: Sat, 2 Nov 2024 01:40:44 +0100 Subject: [PATCH 10/10] fmt --- accounts/src/key_management/mod.rs | 96 ++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/accounts/src/key_management/mod.rs b/accounts/src/key_management/mod.rs index 0fab650..fcfcedd 100644 --- a/accounts/src/key_management/mod.rs +++ b/accounts/src/key_management/mod.rs @@ -65,24 +65,27 @@ impl AddressKeyHolder { let binding = key_point.to_bytes(); let key_raw = &binding.as_slice()[..32]; let key_raw_adjust: [u8; 32] = key_raw.try_into().unwrap(); - + let key: Key = key_raw_adjust.into(); - + let cipher = Aes256Gcm::new(&key); - + cipher.decrypt(&nonce, ciphertext.as_slice()).unwrap() } } #[cfg(test)] mod tests { - use constants_types::{NULLIFIER_SECRET_CONST, VIEVING_SECRET_CONST}; - use elliptic_curve::group::GroupEncoding; - use aes_gcm::{Aes256Gcm, aead::{Aead, KeyInit, OsRng}}; - use k256::{AffinePoint, ProjectivePoint, Scalar}; + use aes_gcm::{ + aead::{Aead, KeyInit, OsRng}, + Aes256Gcm, + }; use constants_types::{CipherText, Nonce}; - use elliptic_curve::group::prime::PrimeCurveAffine; + use constants_types::{NULLIFIER_SECRET_CONST, VIEVING_SECRET_CONST}; use elliptic_curve::ff::Field; + use elliptic_curve::group::prime::PrimeCurveAffine; + use elliptic_curve::group::GroupEncoding; + use k256::{AffinePoint, ProjectivePoint, Scalar}; use super::*; @@ -90,10 +93,14 @@ mod tests { fn test_new_os_random() { // Ensure that a new AddressKeyHolder instance can be created without errors. let address_key_holder = AddressKeyHolder::new_os_random(); - + // Check that key holder fields are initialized with expected types - assert!(!Into::::into(address_key_holder.nullifer_public_key.is_identity())); - assert!(!Into::::into(address_key_holder.viewing_public_key.is_identity())); + assert!(!Into::::into( + address_key_holder.nullifer_public_key.is_identity() + )); + assert!(!Into::::into( + address_key_holder.viewing_public_key.is_identity() + )); } #[test] @@ -105,7 +112,8 @@ mod tests { let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); // Calculate shared secret - let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let shared_secret = + address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); // Ensure the shared secret is not an identity point (suggesting non-zero output) assert!(!Into::::into(shared_secret.is_identity())); @@ -117,8 +125,11 @@ mod tests { // Generate an ephemeral key and shared secret let scalar = Scalar::random(OsRng); - let ephemeral_public_key_sender = address_key_holder.produce_ephemeral_key_holder().generate_ephemeral_public_key(); - let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let ephemeral_public_key_sender = address_key_holder + .produce_ephemeral_key_holder() + .generate_ephemeral_public_key(); + let shared_secret = + address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); // Prepare the encryption key from shared secret let key_raw = shared_secret.to_bytes(); @@ -131,10 +142,16 @@ mod tests { // Encrypt sample data let nonce = Nonce::from_slice(b"unique nonce"); let plaintext = b"Sensitive data"; - let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + let ciphertext = cipher + .encrypt(nonce, plaintext.as_ref()) + .expect("encryption failure"); // Attempt decryption - let decrypted_data: Vec = address_key_holder.decrypt_data(ephemeral_public_key_sender, CipherText::from(ciphertext), nonce.clone()); + let decrypted_data: Vec = address_key_holder.decrypt_data( + ephemeral_public_key_sender, + CipherText::from(ciphertext), + nonce.clone(), + ); // Verify decryption is successful and matches original plaintext assert_eq!(decrypted_data, plaintext); @@ -146,8 +163,12 @@ mod tests { let address_key_holder = AddressKeyHolder::new_os_random(); // Check that key holder fields are initialized with expected types and values - assert!(!Into::::into(address_key_holder.nullifer_public_key.is_identity())); - assert!(!Into::::into(address_key_holder.viewing_public_key.is_identity())); + assert!(!Into::::into( + address_key_holder.nullifer_public_key.is_identity() + )); + assert!(!Into::::into( + address_key_holder.viewing_public_key.is_identity() + )); assert!(address_key_holder.address.as_slice().len() > 0); // Assume TreeHashType has non-zero length for a valid address } @@ -173,7 +194,8 @@ mod tests { // Generate ephemeral public key and shared secret let scalar = Scalar::random(OsRng); let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); - let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let shared_secret = + address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); // Prepare the encryption key from shared secret let key_raw = shared_secret.to_bytes(); @@ -186,14 +208,16 @@ mod tests { // Encrypt sample data with a specific nonce let nonce = Nonce::from_slice(b"unique nonce"); let plaintext = b"Sensitive data"; - let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + let ciphertext = cipher + .encrypt(nonce, plaintext.as_ref()) + .expect("encryption failure"); // Attempt decryption with an incorrect nonce let incorrect_nonce = Nonce::from_slice(b"wrong nonce"); let decrypted_data = address_key_holder.decrypt_data( - ephemeral_public_key_sender, - CipherText::from(ciphertext.clone()), - incorrect_nonce.clone(), + ephemeral_public_key_sender, + CipherText::from(ciphertext.clone()), + incorrect_nonce.clone(), ); // The decryption should fail or produce incorrect output due to nonce mismatch @@ -208,7 +232,8 @@ mod tests { // Generate ephemeral public key and shared secret let scalar = Scalar::random(OsRng); let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine(); - let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let shared_secret = + address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); // Prepare the encryption key from shared secret let key_raw = shared_secret.to_bytes(); @@ -221,7 +246,9 @@ mod tests { // Encrypt sample data let nonce = Nonce::from_slice(b"unique nonce"); let plaintext = b"Sensitive data"; - let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + let ciphertext = cipher + .encrypt(nonce, plaintext.as_ref()) + .expect("encryption failure"); // Tamper with the ciphertext to simulate corruption let mut corrupted_ciphertext = ciphertext.clone(); @@ -229,9 +256,9 @@ mod tests { // Attempt decryption let result = address_key_holder.decrypt_data( - ephemeral_public_key_sender, - CipherText::from(corrupted_ciphertext), - nonce.clone(), + ephemeral_public_key_sender, + CipherText::from(corrupted_ciphertext), + nonce.clone(), ); // The decryption should fail or produce incorrect output due to tampered ciphertext @@ -250,7 +277,8 @@ mod tests { let plaintext = b"Round-trip test data"; let nonce = Nonce::from_slice(b"unique nonce"); - let shared_secret = address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); + let shared_secret = + address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender); // Prepare the encryption key from shared secret let key_raw = shared_secret.to_bytes(); let key_raw_adjust_pre = &key_raw.as_slice()[..32]; @@ -258,13 +286,15 @@ mod tests { let key: Key = key_raw_adjust.into(); let cipher = Aes256Gcm::new(&key); - let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).expect("encryption failure"); + let ciphertext = cipher + .encrypt(nonce, plaintext.as_ref()) + .expect("encryption failure"); // Decrypt the data using the `AddressKeyHolder` instance let decrypted_data = address_key_holder.decrypt_data( - ephemeral_public_key_sender, - CipherText::from(ciphertext), - nonce.clone(), + ephemeral_public_key_sender, + CipherText::from(ciphertext), + nonce.clone(), ); // Verify the decrypted data matches the original plaintext