Merge branch 'Pravdyvy/key-protocol-update-private' into Pravdyvy/wallet-privacy-preserving-transactions

This commit is contained in:
Oleksandr Pravdyvyi 2025-09-16 08:49:10 +03:00
commit ae70baf5c4
No known key found for this signature in database
GPG Key ID: 9F8955C63C443871
12 changed files with 142 additions and 321 deletions

1
Cargo.lock generated
View File

@ -2623,6 +2623,7 @@ dependencies = [
"borsh",
"hex",
"hex-literal 1.0.0",
"k256",
"nssa-core",
"program-methods",
"rand 0.8.5",

View File

@ -1,24 +1,30 @@
use elliptic_curve::PrimeField;
use k256::{AffinePoint, Scalar};
use k256::Scalar;
use log::info;
use nssa_core::{
NullifierPublicKey, SharedSecretKey,
encryption::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey},
};
use sha2::Digest;
use crate::key_management::secret_holders::OutgoingViewingSecretKey;
#[derive(Debug)]
///Ephemeral secret key holder. Non-clonable as intended for one-time use. Produces ephemeral public keys. Can produce shared secret for sender.
pub struct EphemeralKeyHolder {
ephemeral_secret_key: Scalar,
ephemeral_secret_key: EphemeralSecretKey,
}
impl EphemeralKeyHolder {
pub fn new(
receiver_nullifier_public_key: [u8; 32],
sender_outgoing_viewing_secret_key: Scalar,
receiver_nullifier_public_key: NullifierPublicKey,
sender_outgoing_viewing_secret_key: OutgoingViewingSecretKey,
nonce: u64,
) -> Self {
let mut hasher = sha2::Sha256::new();
hasher.update(receiver_nullifier_public_key);
hasher.update(nonce.to_le_bytes());
hasher.update([0; 192]);
hasher.update([0; 24]);
let hash_recepient = hasher.finalize();
@ -31,15 +37,18 @@ impl EphemeralKeyHolder {
}
}
pub fn generate_ephemeral_public_key(&self) -> AffinePoint {
(AffinePoint::GENERATOR * self.ephemeral_secret_key).into()
pub fn generate_ephemeral_public_key(&self) -> EphemeralPublicKey {
EphemeralPublicKey::from_scalar(self.ephemeral_secret_key)
}
pub fn calculate_shared_secret_sender(
&self,
receiver_incoming_viewing_public_key: AffinePoint,
) -> AffinePoint {
(receiver_incoming_viewing_public_key * self.ephemeral_secret_key).into()
receiver_incoming_viewing_public_key: IncomingViewingPublicKey,
) -> SharedSecretKey {
SharedSecretKey::new(
&self.ephemeral_secret_key,
&receiver_incoming_viewing_public_key,
)
}
pub fn log(&self) {

View File

@ -4,25 +4,26 @@ use elliptic_curve::group::GroupEncoding;
use elliptic_curve::point::AffineCoordinates;
use k256::AffinePoint;
use log::info;
use secret_holders::{PrivateKeyHolder, SeedHolder, TopSecretKeyHolder};
use nssa_core::{
NullifierPublicKey, SharedSecretKey,
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
};
use secret_holders::{PrivateKeyHolder, SecretSpendingKey, SeedHolder};
use serde::{Deserialize, Serialize};
use sha2::{Digest, digest::FixedOutput};
use types::{CipherText, Nonce};
use crate::key_protocol_core::PublicKey;
pub type PublicAccountSigningKey = [u8; 32];
pub mod ephemeral_key_holder;
pub mod secret_holders;
pub mod types;
#[derive(Serialize, Deserialize, Clone, Debug)]
///Entrypoint to key management
pub struct KeyChain {
top_secret_key_holder: TopSecretKeyHolder,
secret_spending_key: SecretSpendingKey,
pub private_key_holder: PrivateKeyHolder,
pub nullifer_public_key: [u8; 32],
pub incoming_viewing_public_key: PublicKey,
pub nullifer_public_key: NullifierPublicKey,
pub incoming_viewing_public_key: IncomingViewingPublicKey,
}
impl KeyChain {
@ -30,15 +31,15 @@ impl KeyChain {
//Currently dropping SeedHolder at the end of initialization.
//Now entirely sure if we need it in the future.
let seed_holder = SeedHolder::new_os_random();
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
let secret_spending_key = seed_holder.produce_top_secret_key_holder();
let private_key_holder = top_secret_key_holder.produce_private_key_holder();
let private_key_holder = secret_spending_key.produce_private_key_holder();
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
let incoming_viewing_public_key = private_key_holder.generate_incoming_viewing_public_key();
Self {
top_secret_key_holder,
secret_spending_key,
private_key_holder,
nullifer_public_key,
incoming_viewing_public_key,
@ -48,7 +49,7 @@ impl KeyChain {
pub fn produce_user_address(&self) -> [u8; 32] {
let mut hasher = sha2::Sha256::new();
hasher.update(self.nullifer_public_key);
hasher.update(&self.nullifer_public_key);
hasher.update(self.incoming_viewing_public_key.to_bytes());
<TreeHashType>::from(hasher.finalize_fixed())
@ -56,33 +57,20 @@ impl KeyChain {
pub fn calculate_shared_secret_receiver(
&self,
ephemeral_public_key_sender: AffinePoint,
) -> AffinePoint {
(ephemeral_public_key_sender
* self
.top_secret_key_holder
.generate_incloming_viewing_secret_key())
.into()
}
pub fn decrypt_data(
&self,
ephemeral_public_key_sender: AffinePoint,
ciphertext: CipherText,
nonce: Nonce,
) -> Result<Vec<u8>, aes_gcm::Error> {
let shared_secret = self.calculate_shared_secret_receiver(ephemeral_public_key_sender);
let cipher = Aes256Gcm::new(&shared_secret.x());
cipher.decrypt(&nonce, ciphertext.as_slice())
ephemeral_public_key_sender: EphemeralPublicKey,
) -> SharedSecretKey {
SharedSecretKey::new(
&self
.secret_spending_key
.generate_incoming_viewing_secret_key(),
&ephemeral_public_key_sender,
)
}
pub fn log(&self) {
info!(
"Secret spending key is {:?}",
hex::encode(
serde_json::to_vec(&self.top_secret_key_holder.secret_spending_key).unwrap()
),
hex::encode(serde_json::to_vec(&self.secret_spending_key).unwrap()),
);
info!(
"Nulifier secret key is {:?}",
@ -113,17 +101,9 @@ impl KeyChain {
#[cfg(test)]
mod tests {
use aes_gcm::{
Aes256Gcm,
aead::{Aead, KeyInit, OsRng},
};
use aes_gcm::aead::OsRng;
use elliptic_curve::ff::Field;
use elliptic_curve::group::prime::PrimeCurveAffine;
use elliptic_curve::point::AffineCoordinates;
use k256::{AffinePoint, ProjectivePoint, Scalar};
use types::{CipherText, Nonce};
use crate::key_management::ephemeral_key_holder::EphemeralKeyHolder;
use k256::{AffinePoint, Scalar};
use super::*;
@ -133,10 +113,7 @@ mod tests {
let address_key_holder = KeyChain::new_os_random();
// Check that key holder fields are initialized with expected types
assert_ne!(address_key_holder.nullifer_public_key, [0u8; 32]);
assert!(!Into::<bool>::into(
address_key_holder.incoming_viewing_public_key.is_identity()
));
assert_ne!(address_key_holder.nullifer_public_key.as_ref(), &[0u8; 32]);
}
#[test]
@ -145,171 +122,11 @@ mod tests {
// Generate a random ephemeral public key sender
let scalar = Scalar::random(&mut OsRng);
let ephemeral_public_key_sender = (ProjectivePoint::GENERATOR * scalar).to_affine();
let ephemeral_public_key_sender = EphemeralPublicKey::from_scalar(scalar);
// Calculate shared secret
let 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::<bool>::into(shared_secret.is_identity()));
}
#[test]
fn test_decrypt_data() {
let address_key_holder = KeyChain::new_os_random();
let test_receiver_nullifier_public_key = [42; 32];
let sender_outgoing_viewing_key = address_key_holder
.top_secret_key_holder
.generate_outgoing_viewing_secret_key();
let nonce = 0;
// Generate an ephemeral key and shared secret
let ephemeral_public_key_sender = EphemeralKeyHolder::new(
test_receiver_nullifier_public_key,
sender_outgoing_viewing_key,
nonce,
)
.generate_ephemeral_public_key();
let shared_secret =
address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender);
// Encrypt sample data
let cipher = Aes256Gcm::new(&shared_secret.x());
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<u8> = address_key_holder
.decrypt_data(
ephemeral_public_key_sender,
CipherText::from(ciphertext),
*nonce,
)
.unwrap();
// Verify decryption is successful and matches original plaintext
assert_eq!(decrypted_data, plaintext);
}
#[test]
fn test_calculate_shared_secret_with_identity_point() {
let address_key_holder = KeyChain::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::<bool>::into(shared_secret.is_identity()));
}
#[test]
#[should_panic]
fn test_decrypt_data_with_incorrect_nonce() {
let address_key_holder = KeyChain::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);
// Encrypt sample data with a specific nonce
let cipher = Aes256Gcm::new(&shared_secret.x());
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,
)
.unwrap();
// The decryption should fail or produce incorrect output due to nonce mismatch
assert_ne!(decrypted_data, plaintext);
}
#[test]
#[should_panic]
fn test_decrypt_data_with_incorrect_ciphertext() {
let address_key_holder = KeyChain::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);
// Encrypt sample data
let cipher = Aes256Gcm::new(&shared_secret.x());
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,
)
.unwrap();
// The decryption should fail or produce incorrect output due to tampered ciphertext
assert_ne!(result, plaintext);
}
#[test]
fn test_encryption_decryption_round_trip() {
let address_key_holder = KeyChain::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);
let cipher = Aes256Gcm::new(&shared_secret.x());
let ciphertext = cipher
.encrypt(nonce, plaintext.as_ref())
.expect("encryption failure");
// Decrypt the data using the `KeyChain` instance
let decrypted_data = address_key_holder
.decrypt_data(
ephemeral_public_key_sender,
CipherText::from(ciphertext),
*nonce,
)
.unwrap();
// Verify the decrypted data matches the original plaintext
assert_eq!(decrypted_data, plaintext);
}
#[test]

View File

@ -1,7 +1,8 @@
use bip39::Mnemonic;
use common::TreeHashType;
use elliptic_curve::PrimeField;
use k256::{AffinePoint, Scalar};
use k256::Scalar;
use nssa_core::{NullifierPublicKey, NullifierSecretKey, encryption::IncomingViewingPublicKey};
use rand::{RngCore, rngs::OsRng};
use serde::{Deserialize, Serialize};
use sha2::{Digest, digest::FixedOutput};
@ -15,17 +16,18 @@ pub struct SeedHolder {
}
#[derive(Serialize, Deserialize, Debug, Clone)]
///Secret spending key holder. Produces `PrivateKeyHolder` objects.
pub struct TopSecretKeyHolder {
pub(crate) secret_spending_key: [u8; 32],
}
///Secret spending key object. Can produce `PrivateKeyHolder` objects.
pub struct SecretSpendingKey(pub(crate) [u8; 32]);
pub type IncomingViewingSecretKey = Scalar;
pub type OutgoingViewingSecretKey = Scalar;
#[derive(Serialize, Deserialize, Debug, Clone)]
///Private key holder. Produces public keys. Can produce address. Can produce shared secret for recepient.
pub struct PrivateKeyHolder {
pub nullifier_secret_key: [u8; 32],
pub(crate) incoming_viewing_secret_key: Scalar,
pub outgoing_viewing_secret_key: Scalar,
pub(crate) nullifier_secret_key: NullifierSecretKey,
pub(crate) incoming_viewing_secret_key: IncomingViewingSecretKey,
pub(crate) outgoing_viewing_secret_key: OutgoingViewingSecretKey,
}
impl SeedHolder {
@ -52,74 +54,65 @@ impl SeedHolder {
*hash.first_chunk::<32>().unwrap()
}
pub fn produce_top_secret_key_holder(&self) -> TopSecretKeyHolder {
TopSecretKeyHolder {
secret_spending_key: self.generate_secret_spending_key_hash(),
}
pub fn produce_top_secret_key_holder(&self) -> SecretSpendingKey {
SecretSpendingKey(self.generate_secret_spending_key_hash())
}
}
impl TopSecretKeyHolder {
pub fn generate_nullifier_secret_key(&self) -> [u8; 32] {
impl SecretSpendingKey {
pub fn generate_nullifier_secret_key(&self) -> NullifierSecretKey {
let mut hasher = sha2::Sha256::new();
hasher.update("NSSA_keys");
hasher.update(self.secret_spending_key);
hasher.update(self.0);
hasher.update([1u8]);
hasher.update([0u8; 176]);
hasher.update([0u8; 22]);
<TreeHashType>::from(hasher.finalize_fixed())
<NullifierSecretKey>::from(hasher.finalize_fixed())
}
pub fn generate_incloming_viewing_secret_key(&self) -> Scalar {
pub fn generate_incoming_viewing_secret_key(&self) -> IncomingViewingSecretKey {
let mut hasher = sha2::Sha256::new();
hasher.update("NSSA_keys");
hasher.update(self.secret_spending_key);
hasher.update(self.0);
hasher.update([2u8]);
hasher.update([0u8; 176]);
hasher.update([0u8; 22]);
let hash = <TreeHashType>::from(hasher.finalize_fixed());
Scalar::from_repr(hash.into()).unwrap()
IncomingViewingSecretKey::from_repr(hash.into()).unwrap()
}
pub fn generate_outgoing_viewing_secret_key(&self) -> Scalar {
pub fn generate_outgoing_viewing_secret_key(&self) -> OutgoingViewingSecretKey {
let mut hasher = sha2::Sha256::new();
hasher.update("NSSA_keys");
hasher.update(self.secret_spending_key);
hasher.update(self.0);
hasher.update([3u8]);
hasher.update([0u8; 176]);
hasher.update([0u8; 22]);
let hash = <TreeHashType>::from(hasher.finalize_fixed());
Scalar::from_repr(hash.into()).unwrap()
OutgoingViewingSecretKey::from_repr(hash.into()).unwrap()
}
pub fn produce_private_key_holder(&self) -> PrivateKeyHolder {
PrivateKeyHolder {
nullifier_secret_key: self.generate_nullifier_secret_key(),
incoming_viewing_secret_key: self.generate_incloming_viewing_secret_key(),
incoming_viewing_secret_key: self.generate_incoming_viewing_secret_key(),
outgoing_viewing_secret_key: self.generate_outgoing_viewing_secret_key(),
}
}
}
impl PrivateKeyHolder {
pub fn generate_nullifier_public_key(&self) -> [u8; 32] {
let mut hasher = sha2::Sha256::new();
hasher.update("NSSA_keys");
hasher.update(self.nullifier_secret_key);
hasher.update([7u8]);
hasher.update([0u8; 176]);
<TreeHashType>::from(hasher.finalize_fixed())
pub fn generate_nullifier_public_key(&self) -> NullifierPublicKey {
(&self.nullifier_secret_key).into()
}
pub fn generate_incoming_viewing_public_key(&self) -> AffinePoint {
(AffinePoint::GENERATOR * self.incoming_viewing_secret_key).into()
pub fn generate_incoming_viewing_public_key(&self) -> IncomingViewingPublicKey {
IncomingViewingPublicKey::from_scalar(self.incoming_viewing_secret_key)
}
}
@ -151,7 +144,7 @@ mod tests {
let top_secret_key_holder = seed_holder.produce_top_secret_key_holder();
let _ = top_secret_key_holder.generate_incloming_viewing_secret_key();
let _ = top_secret_key_holder.generate_incoming_viewing_secret_key();
}
#[test]

View File

@ -1,8 +0,0 @@
use elliptic_curve::{
consts::{B0, B1},
generic_array::GenericArray,
};
use sha2::digest::typenum::{UInt, UTerm};
pub type CipherText = Vec<u8>;
pub type Nonce = GenericArray<u8, UInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>, B0>>;

View File

@ -14,6 +14,7 @@ secp256k1 = "0.31.1"
rand = "0.8"
borsh = "1.5.7"
hex = "0.4.3"
k256 = "0.13.3"
[dev-dependencies]
test-program-methods = { path = "test_program_methods" }

View File

@ -14,7 +14,7 @@ use crate::SharedSecretKey;
pub struct Secp256k1Point(pub Vec<u8>);
impl Secp256k1Point {
pub fn from_scalar(value: [u8; 32]) -> Secp256k1Point {
pub fn from_scalar(value: Scalar) -> Secp256k1Point {
let x_bytes: FieldBytes = value.into();
let x = Scalar::from_repr(x_bytes).unwrap();
@ -26,7 +26,7 @@ impl Secp256k1Point {
}
}
pub type EphemeralSecretKey = [u8; 32];
pub type EphemeralSecretKey = Scalar;
pub type EphemeralPublicKey = Secp256k1Point;
pub type IncomingViewingPublicKey = Secp256k1Point;
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
@ -36,8 +36,7 @@ impl From<&EphemeralSecretKey> for EphemeralPublicKey {
}
impl SharedSecretKey {
pub fn new(scalar: &[u8; 32], point: &Secp256k1Point) -> Self {
let scalar = Scalar::from_repr((*scalar).into()).unwrap();
pub fn new(scalar: &Scalar, point: &Secp256k1Point) -> Self {
let point: [u8; 33] = point.0.clone().try_into().unwrap();
let encoded = EncodedPoint::from_bytes(point).unwrap();

View File

@ -7,6 +7,12 @@ use crate::Commitment;
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, Hash))]
pub struct NullifierPublicKey(pub [u8; 32]);
impl AsRef<[u8]> for NullifierPublicKey {
fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}
impl From<&NullifierSecretKey> for NullifierPublicKey {
fn from(value: &NullifierSecretKey) -> Self {
let mut bytes = Vec::new();

View File

@ -224,3 +224,34 @@ impl PrivacyPreservingTransaction {
Ok(PrivacyPreservingTransaction::new(message, witness_set))
}
}
impl Proof {
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
let proof_len = self.0.len() as u32;
bytes.extend_from_slice(&proof_len.to_le_bytes());
bytes.extend_from_slice(&self.0);
bytes
}
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
let proof_len = u32_from_cursor(cursor) as usize;
let mut proof = Vec::with_capacity(proof_len);
for _ in 0..proof_len {
let mut one_byte_buf = [0u8];
cursor.read_exact(&mut one_byte_buf)?;
proof.push(one_byte_buf[0]);
}
Ok(Self(proof))
}
}
// TODO: Improve error handling. Remove unwraps.
pub fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> u32 {
let mut word_buf = [0u8; 4];
cursor.read_exact(&mut word_buf).unwrap();
u32::from_le_bytes(word_buf)
}

View File

@ -1,5 +1,3 @@
use std::io::{Cursor, Read};
use nssa_core::{
MembershipProof, NullifierPublicKey, NullifierSecretKey, PrivacyPreservingCircuitInput,
PrivacyPreservingCircuitOutput, SharedSecretKey,
@ -14,44 +12,7 @@ use program_methods::{PRIVACY_PRESERVING_CIRCUIT_ELF, PRIVACY_PRESERVING_CIRCUIT
/// Proof of the privacy preserving execution circuit
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Proof(pub(super) Vec<u8>);
impl Proof {
pub(crate) fn is_valid_for(&self, circuit_output: &PrivacyPreservingCircuitOutput) -> bool {
let inner: InnerReceipt = borsh::from_slice(&self.0).unwrap();
let receipt = Receipt::new(inner, circuit_output.to_bytes());
receipt.verify(PRIVACY_PRESERVING_CIRCUIT_ID).is_ok()
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
let proof_len = self.0.len() as u32;
bytes.extend_from_slice(&proof_len.to_le_bytes());
bytes.extend_from_slice(&self.0);
bytes
}
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
let proof_len = u32_from_cursor(cursor) as usize;
let mut proof = Vec::with_capacity(proof_len);
for _ in 0..proof_len {
let mut one_byte_buf = [0u8];
cursor.read_exact(&mut one_byte_buf)?;
proof.push(one_byte_buf[0]);
}
Ok(Self(proof))
}
}
// TODO: Improve error handling. Remove unwraps.
pub fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> u32 {
let mut word_buf = [0u8; 4];
cursor.read_exact(&mut word_buf).unwrap();
u32::from_le_bytes(word_buf)
}
pub struct Proof(pub(crate) Vec<u8>);
/// Generates a proof of the execution of a NSSA program inside the privacy preserving execution
/// circuit
@ -117,8 +78,17 @@ fn execute_and_prove_program(
.receipt)
}
impl Proof {
pub(crate) fn is_valid_for(&self, circuit_output: &PrivacyPreservingCircuitOutput) -> bool {
let inner: InnerReceipt = borsh::from_slice(&self.0).unwrap();
let receipt = Receipt::new(inner, circuit_output.to_bytes());
receipt.verify(PRIVACY_PRESERVING_CIRCUIT_ID).is_ok()
}
}
#[cfg(test)]
mod tests {
use k256::{Scalar, elliptic_curve::PrimeField};
use nssa_core::{
Commitment, EncryptionScheme, Nullifier,
account::{Account, AccountWithMetadata},
@ -170,7 +140,7 @@ mod tests {
let expected_sender_pre = sender.clone();
let recipient_keys = test_private_account_keys_1();
let esk = [3; 32];
let esk = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
let (output, proof) = execute_and_prove(
@ -251,10 +221,10 @@ mod tests {
Commitment::new(&recipient_keys.npk(), &expected_private_account_2),
];
let esk_1 = [3; 32];
let esk_1 = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
let esk_2 = [5; 32];
let esk_2 = Scalar::from_repr([5; 32].into()).unwrap();
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
let (output, proof) = execute_and_prove(

View File

@ -90,6 +90,7 @@ impl Message {
#[cfg(test)]
pub mod tests {
use k256::{Scalar, elliptic_curve::PrimeField};
use std::io::Cursor;
use nssa_core::{
@ -151,10 +152,10 @@ pub mod tests {
#[test]
fn test_encrypted_account_data_constructor() {
let npk = NullifierPublicKey::from(&[1; 32]);
let ivk = IncomingViewingPublicKey::from(&[2; 32]);
let ivk = IncomingViewingPublicKey::from(&Scalar::from_repr([2; 32].into()).unwrap());
let account = Account::default();
let commitment = Commitment::new(&npk, &account);
let esk = [3; 32];
let esk = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret = SharedSecretKey::new(&esk, &ivk);
let epk = EphemeralPublicKey::from_scalar(esk);
let ciphertext = EncryptionScheme::encrypt(&account, &shared_secret, &commitment, 2);

View File

@ -227,6 +227,7 @@ pub mod tests {
signature::PrivateKey,
};
use k256::{Scalar, elliptic_curve::PrimeField};
use nssa_core::{
Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::{Account, AccountWithMetadata, Nonce},
@ -743,7 +744,7 @@ pub mod tests {
pub struct TestPrivateKeys {
pub nsk: NullifierSecretKey,
pub isk: [u8; 32],
pub isk: Scalar,
}
impl TestPrivateKeys {
@ -759,14 +760,14 @@ pub mod tests {
pub fn test_private_account_keys_1() -> TestPrivateKeys {
TestPrivateKeys {
nsk: [13; 32],
isk: [31; 32],
isk: Scalar::from_repr([31; 32].into()).unwrap(),
}
}
pub fn test_private_account_keys_2() -> TestPrivateKeys {
TestPrivateKeys {
nsk: [38; 32],
isk: [83; 32],
isk: Scalar::from_repr([83; 32].into()).unwrap(),
}
}
@ -788,7 +789,7 @@ pub mod tests {
is_authorized: false,
};
let esk = [3; 32];
let esk = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
let epk = EphemeralPublicKey::from_scalar(esk);
@ -834,11 +835,11 @@ pub mod tests {
is_authorized: false,
};
let esk_1 = [3; 32];
let esk_1 = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
let esk_2 = [3; 32];
let esk_2 = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
@ -894,7 +895,7 @@ pub mod tests {
is_authorized: false,
};
let esk = [3; 32];
let esk = Scalar::from_repr([3; 32].into()).unwrap();
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.ivk());
let epk = EphemeralPublicKey::from_scalar(esk);