[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 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<EdwardsPoint> {
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<Scalar> {
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<Scalar> {
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<bool> {
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<Self> {
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<Alice1> {
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<Self> {
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());
}
}