diff --git a/monero-adaptor/src/lib.rs b/monero-adaptor/src/lib.rs index c639a1f4..9fdaed46 100644 --- a/monero-adaptor/src/lib.rs +++ b/monero-adaptor/src/lib.rs @@ -9,10 +9,9 @@ extern "C" { } use anyhow::{bail, Context, Result}; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; +use curve25519_dalek::constants::ED25519_BASEPOINT_POINT; use curve25519_dalek::digest::Digest; use curve25519_dalek::edwards::{CompressedEdwardsY, EdwardsPoint}; -use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use rand::rngs::OsRng; use sha2::Sha512; @@ -55,19 +54,14 @@ pub fn hash_point_to_point(point: EdwardsPoint) -> Result { fn challenge( s_i: Scalar, - pk_i: RistrettoPoint, + pk_i: EdwardsPoint, h_prev: Scalar, - I: RistrettoPoint, + I: EdwardsPoint, prefix: Sha512, -) -> Scalar { - let L_i = s_i * RISTRETTO_BASEPOINT_POINT + h_prev * pk_i; +) -> Result { + let L_i = s_i * ED25519_BASEPOINT_POINT + h_prev * pk_i; - let H_p_pk_i = { - let H_p = Sha512::new() - .chain(KEY_TAG.to_string()) - .chain(pk_i.compress().as_bytes()); - RistrettoPoint::from_hash(H_p) - }; + let H_p_pk_i = hash_point_to_point(pk_i)?; let R_i = s_i * H_p_pk_i + h_prev * I; @@ -76,22 +70,23 @@ fn challenge( bytes.append(&mut R_i.compress().as_bytes().to_vec()); let hasher = prefix.chain(bytes); - Scalar::from_hash(hasher) + + Ok(Scalar::from_hash(hasher)) } fn foo( fake_responses: [Scalar; RING_SIZE - 1], - ring: [RistrettoPoint; RING_SIZE], - T_a: RistrettoPoint, - T_b: RistrettoPoint, - R_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - I_hat_b: RistrettoPoint, - R_prime_a: RistrettoPoint, - I_a: RistrettoPoint, - I_b: RistrettoPoint, + ring: [EdwardsPoint; RING_SIZE], + T_a: EdwardsPoint, + T_b: EdwardsPoint, + R_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + I_hat_b: EdwardsPoint, + R_prime_a: EdwardsPoint, + I_a: EdwardsPoint, + I_b: EdwardsPoint, msg: [u8; 32], -) -> (Scalar, Scalar) { +) -> Result<(Scalar, Scalar)> { let h_0 = { let ring = ring .iter() @@ -109,22 +104,22 @@ fn foo( // ring size is 11 let h_last = final_challenge( fake_responses, - <[RistrettoPoint; 11]>::try_from(ring).unwrap(), + <[EdwardsPoint; 11]>::try_from(ring).unwrap(), h_0, I_a + I_b, msg, - ); + )?; - (h_last, h_0) + Ok((h_last, h_0)) } fn final_challenge( fake_responses: [Scalar; RING_SIZE - 1], - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], h_0: Scalar, - I: RistrettoPoint, + I: EdwardsPoint, msg: [u8; 32], -) -> Scalar { +) -> Result { let mut ring_concat = ring .iter() .flat_map(|pk| pk.compress().as_bytes().to_vec()) @@ -142,10 +137,10 @@ fn final_challenge( for (i, s_i) in fake_responses.iter().enumerate() { let pk_i = ring[i + 1]; - h = challenge(*s_i, pk_i, h, I, prefix.clone()); + h = challenge(*s_i, pk_i, h, I, prefix.clone())?; } - h + Ok(h) } pub struct AdaptorSignature { @@ -154,7 +149,7 @@ pub struct AdaptorSignature { fake_responses: [Scalar; RING_SIZE - 1], h_0: Scalar, /// Key image of the real key in the ring. - I: RistrettoPoint, + I: EdwardsPoint, } impl AdaptorSignature { @@ -182,23 +177,11 @@ pub struct Signature { pub responses: [Scalar; RING_SIZE], pub h_0: Scalar, /// Key image of the real key in the ring. - pub I: RistrettoPoint, + pub I: EdwardsPoint, } impl Signature { - #[cfg(test)] - pub fn to_nazgul_signature(&self, ring: &[RistrettoPoint; RING_SIZE]) -> nazgul::clsag::CLSAG { - let ring = ring.iter().map(|pk| vec![*pk]).collect(); - - nazgul::clsag::CLSAG { - challenge: self.h_0, - responses: self.responses.to_vec(), - ring, - key_images: vec![self.I], - } - } - - fn verify(&self, ring: [RistrettoPoint; RING_SIZE], msg: &[u8; 32]) -> bool { + fn verify(&self, ring: [EdwardsPoint; RING_SIZE], msg: &[u8; 32]) -> Result { let mut ring_concat = ring .iter() .flat_map(|pk| pk.compress().as_bytes().to_vec()) @@ -216,59 +199,54 @@ impl Signature { for (i, s_i) in self.responses.iter().enumerate() { let pk_i = ring[(i + 1) % RING_SIZE]; - h = challenge(*s_i, pk_i, h, self.I, prefix.clone()); + h = challenge(*s_i, pk_i, h, self.I, prefix.clone())?; } - h == self.h_0 + Ok(h == self.h_0) } } pub struct Alice0 { // secret index is always 0 - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], fake_responses: [Scalar; RING_SIZE - 1], msg: [u8; 32], // encryption key - R_a: RistrettoPoint, + R_a: EdwardsPoint, // R'a = r_a*H_p(p_k) where p_k is the signing public key - R_prime_a: RistrettoPoint, + R_prime_a: EdwardsPoint, // this is not s_a cos of something to with one-time-address?? s_prime_a: Scalar, // secret value: alpha_a: Scalar, - H_p_pk: RistrettoPoint, - I_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - T_a: RistrettoPoint, + H_p_pk: EdwardsPoint, + I_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + T_a: EdwardsPoint, } impl Alice0 { pub fn new( - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], msg: [u8; 32], - R_a: RistrettoPoint, - R_prime_a: RistrettoPoint, + R_a: EdwardsPoint, + R_prime_a: EdwardsPoint, s_prime_a: Scalar, - ) -> Self { + ) -> Result { let mut fake_responses = [Scalar::zero(); RING_SIZE - 1]; for response in fake_responses.iter_mut().take(RING_SIZE - 1) { *response = Scalar::random(&mut OsRng); } let alpha_a = Scalar::random(&mut OsRng); - let p_k = ring[0].compress(); - let H_p_pk = { - let H_p = Sha512::new() - .chain(KEY_TAG.to_string()) - .chain(p_k.as_bytes()); - RistrettoPoint::from_hash(H_p) - }; + let p_k = ring[0]; + let H_p_pk = hash_point_to_point(p_k)?; let I_a = s_prime_a * H_p_pk; let I_hat_a = alpha_a * H_p_pk; - let T_a = alpha_a * RISTRETTO_BASEPOINT_POINT; + let T_a = alpha_a * ED25519_BASEPOINT_POINT; - Alice0 { + Ok(Alice0 { ring, fake_responses, msg, @@ -280,13 +258,13 @@ impl Alice0 { I_a, I_hat_a, T_a, - } + }) } pub fn next_message(&self) -> Message0 { Message0 { pi_a: DleqProof::new( - RISTRETTO_BASEPOINT_POINT, + ED25519_BASEPOINT_POINT, self.T_a, self.H_p_pk, self.I_hat_a, @@ -298,7 +276,7 @@ impl Alice0 { pub fn receive(self, msg: Message1) -> Result { msg.pi_b - .verify(RISTRETTO_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?; + .verify(ED25519_BASEPOINT_POINT, msg.T_b, self.H_p_pk, msg.I_hat_b)?; let (h_last, h_0) = foo( self.fake_responses, @@ -312,7 +290,7 @@ impl Alice0 { self.I_a, msg.I_b, self.msg, - ); + )?; let s_0_a = self.alpha_a - h_last * self.s_prime_a; @@ -330,11 +308,11 @@ impl Alice0 { pub struct Alice1 { fake_responses: [Scalar; RING_SIZE - 1], - I_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - T_a: RistrettoPoint, + I_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + T_a: EdwardsPoint, h_0: Scalar, - I_b: RistrettoPoint, + I_b: EdwardsPoint, s_0_a: Scalar, } @@ -365,44 +343,39 @@ pub struct Alice2 { pub struct Bob0 { // secret index is always 0 - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], msg: [u8; 32], // encryption key - R_a: RistrettoPoint, + R_a: EdwardsPoint, // R'a = r_a*H_p(p_k) where p_k is the signing public key - R_prime_a: RistrettoPoint, + R_prime_a: EdwardsPoint, s_b: Scalar, // secret value: alpha_b: Scalar, - H_p_pk: RistrettoPoint, - I_b: RistrettoPoint, - I_hat_b: RistrettoPoint, - T_b: RistrettoPoint, + H_p_pk: EdwardsPoint, + I_b: EdwardsPoint, + I_hat_b: EdwardsPoint, + T_b: EdwardsPoint, } impl Bob0 { pub fn new( - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], msg: [u8; 32], - R_a: RistrettoPoint, - R_prime_a: RistrettoPoint, + R_a: EdwardsPoint, + R_prime_a: EdwardsPoint, s_b: Scalar, - ) -> Self { + ) -> Result { let alpha_b = Scalar::random(&mut OsRng); - let p_k = ring.first().unwrap().compress(); - let H_p_pk = { - let H_p = Sha512::new() - .chain(KEY_TAG.to_string()) - .chain(p_k.as_bytes()); - RistrettoPoint::from_hash(H_p) - }; + let p_k = ring.first().unwrap(); + let H_p_pk = hash_point_to_point(*p_k)?; let I_b = s_b * H_p_pk; let I_hat_b = alpha_b * H_p_pk; - let T_b = alpha_b * RISTRETTO_BASEPOINT_POINT; + let T_b = alpha_b * ED25519_BASEPOINT_POINT; - Bob0 { + Ok(Bob0 { ring, msg, R_a, @@ -413,7 +386,7 @@ impl Bob0 { I_b, I_hat_b, T_b, - } + }) } pub fn receive(self, msg: Message0) -> Bob1 { @@ -436,19 +409,19 @@ impl Bob0 { pub struct Bob1 { // secret index is always 0 - ring: [RistrettoPoint; RING_SIZE], + ring: [EdwardsPoint; RING_SIZE], msg: [u8; 32], // encryption key - R_a: RistrettoPoint, + R_a: EdwardsPoint, // R'a = r_a*H_p(p_k) where p_k is the signing public key - R_prime_a: RistrettoPoint, + R_prime_a: EdwardsPoint, s_b: Scalar, // secret value: alpha_b: Scalar, - H_p_pk: RistrettoPoint, - I_b: RistrettoPoint, - I_hat_b: RistrettoPoint, - T_b: RistrettoPoint, + H_p_pk: EdwardsPoint, + I_b: EdwardsPoint, + I_hat_b: EdwardsPoint, + T_b: EdwardsPoint, pi_a: DleqProof, c_a: Commitment, } @@ -460,7 +433,7 @@ impl Bob1 { T_b: self.T_b, I_hat_b: self.I_hat_b, pi_b: DleqProof::new( - RISTRETTO_BASEPOINT_POINT, + ED25519_BASEPOINT_POINT, self.T_b, self.H_p_pk, self.I_hat_b, @@ -473,7 +446,7 @@ impl Bob1 { let (fake_responses, I_a, I_hat_a, T_a) = msg.d_a.open(self.c_a)?; self.pi_a - .verify(RISTRETTO_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?; + .verify(ED25519_BASEPOINT_POINT, T_a, self.H_p_pk, I_hat_a)?; let (h_last, h_0) = foo( fake_responses, @@ -487,7 +460,7 @@ impl Bob1 { I_a, self.I_b, self.msg, - ); + )?; let s_0_b = self.alpha_b - h_last * self.s_b; @@ -521,10 +494,10 @@ struct DleqProof { impl DleqProof { fn new( - G: RistrettoPoint, - xG: RistrettoPoint, - H: RistrettoPoint, - xH: RistrettoPoint, + G: EdwardsPoint, + xG: EdwardsPoint, + H: EdwardsPoint, + xH: EdwardsPoint, x: Scalar, ) -> Self { let r = Scalar::random(&mut OsRng); @@ -547,10 +520,10 @@ impl DleqProof { fn verify( &self, - G: RistrettoPoint, - xG: RistrettoPoint, - H: RistrettoPoint, - xH: RistrettoPoint, + G: EdwardsPoint, + xG: EdwardsPoint, + H: EdwardsPoint, + xH: EdwardsPoint, ) -> Result<()> { let s = self.s; let c = self.c; @@ -581,9 +554,9 @@ struct Commitment([u8; 64]); impl Commitment { fn new( fake_responses: [Scalar; RING_SIZE - 1], - I_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - T_a: RistrettoPoint, + I_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + T_a: EdwardsPoint, ) -> Self { let fake_responses = fake_responses .iter() @@ -606,17 +579,17 @@ impl Commitment { struct Opening { fake_responses: [Scalar; RING_SIZE - 1], - I_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - T_a: RistrettoPoint, + I_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + T_a: EdwardsPoint, } impl Opening { fn new( fake_responses: [Scalar; RING_SIZE - 1], - I_a: RistrettoPoint, - I_hat_a: RistrettoPoint, - T_a: RistrettoPoint, + I_a: EdwardsPoint, + I_hat_a: EdwardsPoint, + T_a: EdwardsPoint, ) -> Self { Self { fake_responses, @@ -631,9 +604,9 @@ impl Opening { commitment: Commitment, ) -> Result<( [Scalar; RING_SIZE - 1], - RistrettoPoint, - RistrettoPoint, - RistrettoPoint, + EdwardsPoint, + EdwardsPoint, + EdwardsPoint, )> { let self_commitment = Commitment::new(self.fake_responses, self.I_a, self.I_hat_a, self.T_a); @@ -654,9 +627,9 @@ pub struct Message0 { // Bob sends this to ALice pub struct Message1 { - I_b: RistrettoPoint, - T_b: RistrettoPoint, - I_hat_b: RistrettoPoint, + I_b: EdwardsPoint, + T_b: EdwardsPoint, + I_hat_b: EdwardsPoint, pi_b: DleqProof, } @@ -683,31 +656,30 @@ mod tests { let s_prime_a = Scalar::random(&mut OsRng); let s_b = Scalar::random(&mut OsRng); - let pk = (s_prime_a + s_b) * RISTRETTO_BASEPOINT_POINT; + let pk = (s_prime_a + s_b) * ED25519_BASEPOINT_POINT; let (r_a, R_a, R_prime_a) = { let r_a = Scalar::random(&mut OsRng); - let R_a = r_a * RISTRETTO_BASEPOINT_POINT; + let R_a = r_a * ED25519_BASEPOINT_POINT; - let pk_hashed_to_point = { - let H_p = Sha512::new() - .chain(KEY_TAG.to_string()) - .chain(pk.compress().as_bytes()); - RistrettoPoint::from_hash(H_p) - }; + let pk_hashed_to_point = hash_point_to_point(pk).unwrap(); let R_prime_a = r_a * pk_hashed_to_point; (r_a, R_a, R_prime_a) }; - let mut ring = [RistrettoPoint::default(); RING_SIZE]; + let mut ring = [EdwardsPoint::default(); RING_SIZE]; ring[0] = pk; - ring[1..].fill_with(|| RistrettoPoint::random(&mut OsRng)); + ring[1..].fill_with(|| { + let x = Scalar::random(&mut OsRng); - let alice = Alice0::new(ring, *msg_to_sign, R_a, R_prime_a, s_prime_a); - let bob = Bob0::new(ring, *msg_to_sign, R_a, R_prime_a, s_b); + x * ED25519_BASEPOINT_POINT + }); + + let alice = Alice0::new(ring, *msg_to_sign, R_a, R_prime_a, s_prime_a).unwrap(); + let bob = Bob0::new(ring, *msg_to_sign, R_a, R_prime_a, s_b).unwrap(); let msg = alice.next_message(); let bob = bob.receive(msg); @@ -723,7 +695,7 @@ mod tests { let sig = alice.adaptor_sig.adapt(r_a); - assert!(sig.verify(ring, msg_to_sign)); + assert!(sig.verify(ring, msg_to_sign).unwrap()); } }