ring-signatures-rs/src/lib.rs
src/lib.rsRaw
1extern crate ark_ed_on_bn254;
2use ark_ec::{AffineCurve, ProjectiveCurve, TEModelParameters};
3use ark_ed_on_bn254::{EdwardsAffine, EdwardsParameters, EdwardsProjective, FqParameters, Fr};
4use ark_ff::{bytes::FromBytes, fields::PrimeField, BigInteger, Fp256};
5use ark_std::{rand, UniformRand, Zero};
6use sha2::{Digest, Sha256};
7
8const GX: Fp256<FqParameters> = <EdwardsParameters as TEModelParameters>::AFFINE_GENERATOR_COEFFS.0;
9const GY: Fp256<FqParameters> = <EdwardsParameters as TEModelParameters>::AFFINE_GENERATOR_COEFFS.1;
10
11#[macro_use]
12extern crate lazy_static;
13
14lazy_static! {
15 static ref G_AFFINE: EdwardsAffine = EdwardsAffine::new(GX, GY);
16 pub static ref G: EdwardsProjective = G_AFFINE.into_projective();
17}
18
19pub type PublicKey = EdwardsProjective;
20pub type Signature = (Fr, Vec<Fr>);
21
22#[derive(Debug, PartialEq)]
23pub struct KeyPair {
24 sk: Fr,
25 pub pk: PublicKey,
26}
27
28pub fn new_key() -> KeyPair {
29 let mut rng = ark_std::rand::thread_rng();
30 let sk: Fr = Fr::rand(&mut rng);
31 // let sk: Fr = UniformRand::rand(&mut rng);
32
33 let pk = G.mul(sk.into_repr());
34 KeyPair { sk, pk }
35}
36
37impl KeyPair {
38 pub fn key_image(&self) -> EdwardsProjective {
39 hash_to_point(self.pk).mul(self.sk.into_repr())
40 }
41
42 pub fn sign(&self, ring: Vec<PublicKey>, m: Vec<u8>) -> Signature {
43 let ring_size = ring.len();
44 // determine pi (the position of signer's public key in R
45 let mut pi = 0;
46 let mut found = false;
47 for i in 0..ring_size {
48 if self.pk == ring[i] {
49 pi = i;
50 found = true;
51 break;
52 }
53 }
54 if !found {
55 // error
56 println!("key not found in the ring");
57 }
58
59 let mut rng = ark_std::rand::thread_rng();
60 let a: Fr = Fr::rand(&mut rng);
61 let mut r: Vec<Fr> = vec![Fr::zero(); ring_size];
62
63 // for i \in {1, 2, ..., n} \ {i=pi}
64 for i in 0..ring_size {
65 if i == pi {
66 continue;
67 }
68 r[i] = Fr::rand(&mut rng);
69 }
70
71 let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
72 // c_{pi+1}
73 let pi1 = (pi + 1) % ring_size;
74 c[pi1] = hash(
75 &ring,
76 &m,
77 G.mul(a.into_repr()),
78 hash_to_point(ring[pi]).mul(a.into_repr()),
79 );
80
81 let key_image = self.key_image();
82 // do c_{i+1} from i=pi+1 to pi-1:
83 for j in 0..(ring_size - 1) {
84 let i = (pi1 + j) % ring_size;
85 let i1 = (pi1 + j + 1) % ring_size;
86 c[i1] = hash(
87 &ring,
88 &m,
89 G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
90 hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
91 );
92 println!("i {:?}, {:?}", i, c[i1]);
93 }
94
95 // compute r_pi
96 r[pi] = a - c[pi] * self.sk;
97 (c[0], r)
98 }
99}
100
101fn hash_to_point(a: EdwardsProjective) -> EdwardsProjective {
102 // TODO use a proper hash_to_point method
103 let mut v: Vec<u8> = Vec::new();
104 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
105 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
106 let mut hasher = Sha256::new();
107 hasher.update(v);
108 let h = hasher.finalize();
109 let v = Fr::from_le_bytes_mod_order(&h[..]);
110
111 G.mul(v.into_repr())
112}
113
114fn hash(ring: &Vec<PublicKey>, m: &Vec<u8>, a: EdwardsProjective, b: EdwardsProjective) -> Fr {
115 let mut v: Vec<u8> = Vec::new();
116
117 for i in 0..ring.len() {
118 v.append(&mut ring[i].into_affine().x.into_repr().to_bytes_le());
119 v.append(&mut ring[i].into_affine().y.into_repr().to_bytes_le());
120 }
121 v.append(&mut m.clone());
122 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
123 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
124 v.append(&mut b.into_affine().x.into_repr().to_bytes_le());
125 v.append(&mut b.into_affine().y.into_repr().to_bytes_le());
126
127 Fr::from_le_bytes_mod_order(&Sha256::new().chain_update(v).finalize())
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133}