mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-13 07:38:49 -05:00
ONLY PARTIALLY WORKING: Allow signing algorithm to be given signing key index
At the moment this works only if the index is 0.
This commit is contained in:
parent
3d9aee932c
commit
58074fc083
4 changed files with 159 additions and 48 deletions
|
|
@ -12,6 +12,7 @@ tiny-keccak = { version = "2", features = ["keccak"] }
|
||||||
hash_edwards_to_edwards = { git = "https://github.com/comit-network/hash_edwards_to_edwards" }
|
hash_edwards_to_edwards = { git = "https://github.com/comit-network/hash_edwards_to_edwards" }
|
||||||
monero = "0.12"
|
monero = "0.12"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
|
itertools = "0.10"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||||
use curve25519_dalek::edwards::EdwardsPoint;
|
use curve25519_dalek::edwards::EdwardsPoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
use hash_edwards_to_edwards::hash_point_to_point;
|
use hash_edwards_to_edwards::hash_point_to_point;
|
||||||
|
use std::iter::{Cycle, Skip, Take};
|
||||||
|
|
||||||
pub const RING_SIZE: usize = 11;
|
pub const RING_SIZE: usize = 11;
|
||||||
|
|
||||||
|
|
@ -12,16 +13,16 @@ const INV_EIGHT: Scalar = Scalar::from_bits([
|
||||||
|
|
||||||
pub fn sign(
|
pub fn sign(
|
||||||
msg: &[u8; 32],
|
msg: &[u8; 32],
|
||||||
signing_key: Scalar,
|
|
||||||
H_p_pk: EdwardsPoint,
|
H_p_pk: EdwardsPoint,
|
||||||
alpha: Scalar,
|
alpha: Scalar,
|
||||||
ring: &[EdwardsPoint; RING_SIZE],
|
ring: &[EdwardsPoint; RING_SIZE],
|
||||||
commitment_ring: &[EdwardsPoint; RING_SIZE],
|
commitment_ring: &[EdwardsPoint; RING_SIZE],
|
||||||
fake_responses: [Scalar; RING_SIZE - 1],
|
mut responses: [Scalar; RING_SIZE],
|
||||||
|
signing_key_index: usize,
|
||||||
z: Scalar,
|
z: Scalar,
|
||||||
pseudo_output_commitment: EdwardsPoint,
|
pseudo_output_commitment: EdwardsPoint,
|
||||||
L_0: EdwardsPoint,
|
L: EdwardsPoint,
|
||||||
R_0: EdwardsPoint,
|
R: EdwardsPoint,
|
||||||
I: EdwardsPoint,
|
I: EdwardsPoint,
|
||||||
) -> Signature {
|
) -> Signature {
|
||||||
let D = z * H_p_pk;
|
let D = z * H_p_pk;
|
||||||
|
|
@ -45,28 +46,19 @@ pub fn sign(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let h_1 = compute_ring_element(L_0, R_0); // if our real key is on index 0, the first hash is index 1
|
let h = compute_ring_element(L, R);
|
||||||
|
|
||||||
dbg!(hex::encode(L_0.compress().as_bytes()));
|
dbg!(hex::encode(L.compress().as_bytes()));
|
||||||
dbg!(hex::encode(R_0.compress().as_bytes()));
|
dbg!(hex::encode(R.compress().as_bytes()));
|
||||||
dbg!(hex::encode(h_1.as_bytes()));
|
dbg!(hex::encode(h.as_bytes()));
|
||||||
|
|
||||||
// if we start at h_1, the final element is h_0
|
let element_after_signing_key = signing_key_index + 1;
|
||||||
let h_0 = fake_responses
|
let h_0 = itertools::izip!(responses, ring, adjusted_commitment_ring)
|
||||||
.iter()
|
.shift_by(element_after_signing_key)
|
||||||
.enumerate()
|
.take(RING_SIZE - 1)
|
||||||
.fold(h_1, |h_prev, (i, s_i)| {
|
.fold(h, |h_prev, (s, P, C)| {
|
||||||
let pk_i = ring[i + 1];
|
let L_i = compute_L(h_prev, mu_P, mu_C, s, *P, C);
|
||||||
|
let R_i = compute_R(h_prev, mu_P, mu_C, s, *P, I, D);
|
||||||
let L_i = compute_L(
|
|
||||||
h_prev,
|
|
||||||
mu_P,
|
|
||||||
mu_C,
|
|
||||||
*s_i,
|
|
||||||
pk_i,
|
|
||||||
adjusted_commitment_ring[i + 1],
|
|
||||||
);
|
|
||||||
let R_i = compute_R(h_prev, mu_P, mu_C, *s_i, pk_i, I, D);
|
|
||||||
|
|
||||||
dbg!(hex::encode(L_i.compress().as_bytes()));
|
dbg!(hex::encode(L_i.compress().as_bytes()));
|
||||||
dbg!(hex::encode(R_i.compress().as_bytes()));
|
dbg!(hex::encode(R_i.compress().as_bytes()));
|
||||||
|
|
@ -77,23 +69,11 @@ pub fn sign(
|
||||||
h
|
h
|
||||||
});
|
});
|
||||||
|
|
||||||
// h_0 gives us s_0
|
responses[signing_key_index] =
|
||||||
let s_0 = alpha - h_0 * ((mu_P * signing_key) + (mu_C * z));
|
alpha - h_0 * ((mu_P * responses[signing_key_index]) + (mu_C * z));
|
||||||
|
|
||||||
Signature {
|
Signature {
|
||||||
responses: [
|
responses,
|
||||||
s_0,
|
|
||||||
fake_responses[0],
|
|
||||||
fake_responses[1],
|
|
||||||
fake_responses[2],
|
|
||||||
fake_responses[3],
|
|
||||||
fake_responses[4],
|
|
||||||
fake_responses[5],
|
|
||||||
fake_responses[6],
|
|
||||||
fake_responses[7],
|
|
||||||
fake_responses[8],
|
|
||||||
fake_responses[9],
|
|
||||||
],
|
|
||||||
h_0,
|
h_0,
|
||||||
I,
|
I,
|
||||||
D: D_inv_8,
|
D: D_inv_8,
|
||||||
|
|
@ -220,11 +200,56 @@ impl From<Signature> for monero::util::ringct::Clsag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait IteratorExt {
|
||||||
|
fn shift_by(self, num: usize) -> ShiftBy<Self>
|
||||||
|
where
|
||||||
|
Self: ExactSizeIterator + Sized + Clone,
|
||||||
|
{
|
||||||
|
let length = self.len();
|
||||||
|
|
||||||
|
ShiftBy::new(self, num, length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ShiftBy<I> {
|
||||||
|
inner: Take<Skip<Cycle<I>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Iterator + Clone> ShiftBy<I> {
|
||||||
|
fn new(iter: I, num: usize, length: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: iter.cycle().skip(num).take(length),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> IteratorExt for I where I: ExactSizeIterator {}
|
||||||
|
|
||||||
|
impl<I> Iterator for ShiftBy<I>
|
||||||
|
where
|
||||||
|
I: Iterator + Clone,
|
||||||
|
{
|
||||||
|
type Item = I::Item;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.inner.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shift_by() {
|
||||||
|
let array = ["a", "b", "c", "d", "e"];
|
||||||
|
|
||||||
|
let shifted = array.iter().copied().shift_by(2).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(shifted, vec!["c", "d", "e", "a", "b"])
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn const_is_inv_eight() {
|
fn const_is_inv_eight() {
|
||||||
let inv_eight = Scalar::from(8u8).invert();
|
let inv_eight = Scalar::from(8u8).invert();
|
||||||
|
|
@ -307,14 +332,17 @@ mod tests {
|
||||||
// TODO: document
|
// TODO: document
|
||||||
let pseudo_output_commitment = commitment_ring[0];
|
let pseudo_output_commitment = commitment_ring[0];
|
||||||
|
|
||||||
|
let mut responses = random_array(|| Scalar::random(&mut rng));
|
||||||
|
responses[0] = signing_key;
|
||||||
|
|
||||||
let signature = sign(
|
let signature = sign(
|
||||||
msg_to_sign,
|
msg_to_sign,
|
||||||
signing_key,
|
|
||||||
H_p_pk,
|
H_p_pk,
|
||||||
alpha,
|
alpha,
|
||||||
&ring,
|
&ring,
|
||||||
&commitment_ring,
|
&commitment_ring,
|
||||||
random_array(|| Scalar::random(&mut rng)),
|
responses,
|
||||||
|
0,
|
||||||
Scalar::zero(),
|
Scalar::zero(),
|
||||||
pseudo_output_commitment,
|
pseudo_output_commitment,
|
||||||
alpha * ED25519_BASEPOINT_POINT,
|
alpha * ED25519_BASEPOINT_POINT,
|
||||||
|
|
@ -360,6 +388,57 @@ mod tests {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sign_and_verify_non_zero_signing_index() {
|
||||||
|
// TODO: FIX THIS TEST
|
||||||
|
let mut rng = rand::rngs::StdRng::from_seed([0u8; 32]);
|
||||||
|
|
||||||
|
let msg_to_sign = b"hello world, monero is amazing!!";
|
||||||
|
|
||||||
|
let signing_key = Scalar::random(&mut rng);
|
||||||
|
let signing_pk = signing_key * ED25519_BASEPOINT_POINT;
|
||||||
|
let H_p_pk = hash_point_to_point(signing_pk);
|
||||||
|
|
||||||
|
let alpha = Scalar::random(&mut rng);
|
||||||
|
|
||||||
|
let mut ring = random_array(|| Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT);
|
||||||
|
ring[0] = signing_pk;
|
||||||
|
|
||||||
|
let real_commitment_blinding = Scalar::random(&mut rng);
|
||||||
|
let mut commitment_ring =
|
||||||
|
random_array(|| Scalar::random(&mut rng) * ED25519_BASEPOINT_POINT);
|
||||||
|
commitment_ring[0] = real_commitment_blinding * ED25519_BASEPOINT_POINT; // + 0 * H
|
||||||
|
|
||||||
|
// TODO: document
|
||||||
|
let pseudo_output_commitment = commitment_ring[0];
|
||||||
|
|
||||||
|
let mut responses = random_array(|| Scalar::random(&mut rng));
|
||||||
|
responses[3] = signing_key;
|
||||||
|
|
||||||
|
let signature = sign(
|
||||||
|
msg_to_sign,
|
||||||
|
H_p_pk,
|
||||||
|
alpha,
|
||||||
|
&ring,
|
||||||
|
&commitment_ring,
|
||||||
|
responses,
|
||||||
|
3,
|
||||||
|
Scalar::zero(),
|
||||||
|
pseudo_output_commitment,
|
||||||
|
alpha * ED25519_BASEPOINT_POINT,
|
||||||
|
alpha * H_p_pk,
|
||||||
|
signing_key * H_p_pk,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(verify(
|
||||||
|
&signature,
|
||||||
|
msg_to_sign,
|
||||||
|
&ring,
|
||||||
|
&commitment_ring,
|
||||||
|
pseudo_output_commitment
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn random_array<T: Default + Copy, const N: usize>(rng: impl FnMut() -> T) -> [T; N] {
|
fn random_array<T: Default + Copy, const N: usize>(rng: impl FnMut() -> T) -> [T; N] {
|
||||||
let mut ring = [T::default(); N];
|
let mut ring = [T::default(); N];
|
||||||
ring[..].fill_with(rng);
|
ring[..].fill_with(rng);
|
||||||
|
|
|
||||||
|
|
@ -155,14 +155,28 @@ impl Alice0 {
|
||||||
msg.pi_b
|
msg.pi_b
|
||||||
.verify(ED25519_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 responses = [
|
||||||
|
self.s_prime_a,
|
||||||
|
self.fake_responses[0],
|
||||||
|
self.fake_responses[1],
|
||||||
|
self.fake_responses[2],
|
||||||
|
self.fake_responses[3],
|
||||||
|
self.fake_responses[4],
|
||||||
|
self.fake_responses[5],
|
||||||
|
self.fake_responses[6],
|
||||||
|
self.fake_responses[7],
|
||||||
|
self.fake_responses[8],
|
||||||
|
self.fake_responses[9],
|
||||||
|
];
|
||||||
|
|
||||||
let sig = clsag::sign(
|
let sig = clsag::sign(
|
||||||
&self.msg,
|
&self.msg,
|
||||||
self.s_prime_a,
|
|
||||||
self.H_p_pk,
|
self.H_p_pk,
|
||||||
self.alpha_a,
|
self.alpha_a,
|
||||||
&self.ring,
|
&self.ring,
|
||||||
&self.commitment_ring,
|
&self.commitment_ring,
|
||||||
self.fake_responses,
|
responses,
|
||||||
|
0,
|
||||||
z,
|
z,
|
||||||
self.pseudo_output_commitment,
|
self.pseudo_output_commitment,
|
||||||
self.T_a + msg.T_b + self.R_a,
|
self.T_a + msg.T_b + self.R_a,
|
||||||
|
|
@ -327,15 +341,29 @@ impl Bob1 {
|
||||||
self.pi_a
|
self.pi_a
|
||||||
.verify(ED25519_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 responses = [
|
||||||
|
self.s_b,
|
||||||
|
fake_responses[0],
|
||||||
|
fake_responses[1],
|
||||||
|
fake_responses[2],
|
||||||
|
fake_responses[3],
|
||||||
|
fake_responses[4],
|
||||||
|
fake_responses[5],
|
||||||
|
fake_responses[6],
|
||||||
|
fake_responses[7],
|
||||||
|
fake_responses[8],
|
||||||
|
fake_responses[9],
|
||||||
|
];
|
||||||
|
|
||||||
let I = I_a + self.I_b;
|
let I = I_a + self.I_b;
|
||||||
let sig = clsag::sign(
|
let sig = clsag::sign(
|
||||||
&self.msg,
|
&self.msg,
|
||||||
self.s_b,
|
|
||||||
self.H_p_pk,
|
self.H_p_pk,
|
||||||
self.alpha_b,
|
self.alpha_b,
|
||||||
&self.ring,
|
&self.ring,
|
||||||
&self.commitment_ring,
|
&self.commitment_ring,
|
||||||
fake_responses,
|
responses,
|
||||||
|
0,
|
||||||
z,
|
z,
|
||||||
self.pseudo_output_commitment,
|
self.pseudo_output_commitment,
|
||||||
T_a + self.T_b + self.R_a,
|
T_a + self.T_b + self.R_a,
|
||||||
|
|
@ -623,7 +651,7 @@ mod tests {
|
||||||
msg_to_sign,
|
msg_to_sign,
|
||||||
&ring,
|
&ring,
|
||||||
&commitment_ring,
|
&commitment_ring,
|
||||||
pseudo_output_commitment
|
pseudo_output_commitment,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,14 +233,17 @@ async fn monerod_integration_test() {
|
||||||
let H_p_pk = hash_point_to_point(signing_key * ED25519_BASEPOINT_POINT);
|
let H_p_pk = hash_point_to_point(signing_key * ED25519_BASEPOINT_POINT);
|
||||||
let alpha = Scalar::random(&mut rng);
|
let alpha = Scalar::random(&mut rng);
|
||||||
|
|
||||||
|
let mut responses = random_array(|| Scalar::random(&mut rng));
|
||||||
|
responses[0] = signing_key;
|
||||||
|
|
||||||
let sig = monero_adaptor::clsag::sign(
|
let sig = monero_adaptor::clsag::sign(
|
||||||
&prefix.hash().to_bytes(),
|
&prefix.hash().to_bytes(),
|
||||||
signing_key,
|
|
||||||
H_p_pk,
|
H_p_pk,
|
||||||
alpha,
|
alpha,
|
||||||
&ring,
|
&ring,
|
||||||
&commitment_ring,
|
&commitment_ring,
|
||||||
random_array(|| Scalar::random(&mut rng)),
|
responses,
|
||||||
|
0,
|
||||||
real_commitment_blinder - (out_blinding_0 + out_blinding_1), // * Scalar::from(MONERO_MUL_FACTOR), TODO DOESN'T VERIFY WITH THIS
|
real_commitment_blinder - (out_blinding_0 + out_blinding_1), // * Scalar::from(MONERO_MUL_FACTOR), TODO DOESN'T VERIFY WITH THIS
|
||||||
pseudo_out,
|
pseudo_out,
|
||||||
alpha * ED25519_BASEPOINT_POINT,
|
alpha * ED25519_BASEPOINT_POINT,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue