[WIP] Port to EdwardsPoint and hash_point_to_point

TODO: Use keccak instead of sha512 when hashing scalars.
This commit is contained in:
Lucas Soriano del Pino 2021-04-20 17:42:57 +10:00
parent ff68a1c1b5
commit bc6a7fb6ff
No known key found for this signature in database
GPG Key ID: EE611E973A1530E7

View File

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