arkworks_setups/
keypair.rs

1use ark_crypto_primitives::Error;
2use ark_ff::PrimeField;
3use ark_std::{error::Error as ArkError, marker::PhantomData, string::ToString};
4use arkworks_native_gadgets::poseidon::FieldHasher;
5
6#[derive(Debug)]
7pub enum KeypairError {
8	EncryptionFailed,
9	DecryptionFailed,
10	SecretKeyParseFailed,
11	DecodeFailed,
12	EncodeFailed,
13}
14
15impl core::fmt::Display for KeypairError {
16	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17		let msg = match self {
18			KeypairError::EncryptionFailed => "Data encryption failed".to_string(),
19			KeypairError::DecryptionFailed => "Data decryption failed".to_string(),
20			KeypairError::SecretKeyParseFailed => "Failed to parse secret key".to_string(),
21			KeypairError::DecodeFailed => "Failed to decode encrypted data".to_string(),
22			KeypairError::EncodeFailed => "Failed to encode encrypted data".to_string(),
23		};
24		write!(f, "{}", msg)
25	}
26}
27
28impl ArkError for KeypairError {}
29
30#[derive(Default, Debug, Copy)]
31pub struct Keypair<F: PrimeField, H: FieldHasher<F>> {
32	pub secret_key: Option<F>,
33	pub public_key: F,
34	_h: PhantomData<H>,
35}
36
37impl<F: PrimeField, H: FieldHasher<F>> Keypair<F, H> {
38	pub fn new(secret_key: F, hasher: &H) -> Self {
39		let pubkey = hasher.hash(&[secret_key]).unwrap();
40
41		Self {
42			public_key: pubkey,
43			secret_key: Some(secret_key),
44			_h: PhantomData,
45		}
46	}
47
48	pub fn new_from_keys(public_key: F, secret_key: Option<F>) -> Self {
49		Self {
50			public_key,
51			secret_key,
52			_h: PhantomData,
53		}
54	}
55
56	pub fn new_from_public_key(public_key: F) -> Self {
57		Self {
58			public_key,
59			secret_key: None,
60			_h: PhantomData,
61		}
62	}
63
64	// Computes the signature = hash(secret_key, commitment, pathIndices)
65	// If the secret_key is not configured on this Keypair, return an error
66	pub fn signature(&self, commitment: &F, index: &F, hasher4: &H) -> Result<F, Error> {
67		let res = hasher4.hash(&[self.secret_key.unwrap(), commitment.clone(), index.clone()])?;
68		Ok(res)
69	}
70}
71
72impl<F: PrimeField, H: FieldHasher<F>> Clone for Keypair<F, H> {
73	fn clone(&self) -> Self {
74		match self.secret_key {
75			Some(secret) => Self::new_from_keys(self.public_key.clone(), Some(secret)),
76			None => Self::new_from_public_key(self.public_key.clone()),
77		}
78	}
79}
80
81#[cfg(test)]
82mod test {
83	use crate::common::setup_params;
84	use ark_bn254::Fq;
85	use ark_std::{test_rng, UniformRand, Zero};
86	use arkworks_native_gadgets::poseidon::{FieldHasher, Poseidon};
87	use arkworks_utils::Curve;
88
89	use super::Keypair;
90
91	#[test]
92	fn should_create_new_public_key() {
93		let rng = &mut test_rng();
94		let curve = Curve::Bn254;
95
96		let params = setup_params(curve, 5, 2);
97		let hasher = Poseidon::<Fq>::new(params.clone());
98		let private_key = Fq::rand(rng);
99
100		let pubkey = hasher.hash(&[private_key]).unwrap();
101
102		let keypair = Keypair::<Fq, Poseidon<Fq>>::new(private_key.clone(), &hasher);
103		let new_pubkey = keypair.public_key;
104
105		assert_eq!(new_pubkey, pubkey)
106	}
107	#[test]
108	fn should_create_new_signature() {
109		let rng = &mut test_rng();
110		let index = Fq::zero();
111		let private_key = Fq::rand(rng);
112		let curve = Curve::Bn254;
113		// create the hasher which is used for deriving the public key from the private
114		// key
115		let params2 = setup_params(curve, 5, 2);
116		let hasher2 = Poseidon::<Fq>::new(params2.clone());
117
118		// create the hasher which is used for generating a signature.
119		let params4 = setup_params(curve, 5, 4);
120		let hasher4 = Poseidon::<Fq>::new(params4.clone());
121		let commitment = Fq::rand(rng);
122
123		let keypair = Keypair::<Fq, Poseidon<Fq>>::new(private_key.clone(), &hasher2);
124
125		// Since signature = hash(privKey, commitment, pathIndices)
126		let ev_res = hasher4.hash(&[private_key, commitment, index]).unwrap();
127		let signature = keypair.signature(&commitment, &index, &hasher4).unwrap();
128		assert_eq!(ev_res, signature);
129	}
130}