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
101pub fn verify(
102 ring: Vec<PublicKey>,
103 m: Vec<u8>,
104 key_image: EdwardsProjective,
105 sig: Signature,
106) -> bool {
107 let ring_size = ring.len();
108
109 let c1 = sig.0;
110 let r = sig.1;
111 if ring_size != r.len() {
112 println!("ERROR"); // TODO
113 return false;
114 }
115 // TODO check that key_image \in G (EC), by l * key_image == 0
116
117 let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
118 c[0] = c1;
119 for j in 0..ring_size {
120 let i = j % ring_size;
121 let i1 = (j + 1) % ring_size;
122 c[i1] = hash(
123 &ring,
124 &m,
125 G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
126 hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
127 );
128 }
129
130 println!("c {:?}\n{:?}", c1, c[0]);
131
132 if c1 == c[0] {
133 return true;
134 }
135 false
136}
137
138fn hash_to_point(a: EdwardsProjective) -> EdwardsProjective {
139 // TODO use a proper hash_to_point method
140 let mut v: Vec<u8> = Vec::new();
141 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
142 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
143 let mut hasher = Sha256::new();
144 hasher.update(v);
145 let h = hasher.finalize();
146 let v = Fr::from_le_bytes_mod_order(&h[..]);
147
148 G.mul(v.into_repr())
149}
150
151fn hash(ring: &Vec<PublicKey>, m: &Vec<u8>, a: EdwardsProjective, b: EdwardsProjective) -> Fr {
152 let mut v: Vec<u8> = Vec::new();
153
154 for i in 0..ring.len() {
155 v.append(&mut ring[i].into_affine().x.into_repr().to_bytes_le());
156 v.append(&mut ring[i].into_affine().y.into_repr().to_bytes_le());
157 }
158 v.append(&mut m.clone());
159 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
160 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
161 v.append(&mut b.into_affine().x.into_repr().to_bytes_le());
162 v.append(&mut b.into_affine().y.into_repr().to_bytes_le());
163
164 Fr::from_le_bytes_mod_order(&Sha256::new().chain_update(v).finalize())
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 #[allow(non_snake_case)]
173 fn test_bLSAG() {
174 let n = 5; // ring size
175 let pi = 3; // position of prover key in the ring
176
177 let k_pi = new_key();
178 println!("{:?}", k_pi);
179
180 // generate other n public keys
181 let mut ring: Vec<PublicKey> = vec![G.clone(); n];
182 for i in 0..n {
183 let k = new_key();
184 ring[i] = k.pk;
185 }
186 // set K_pi
187 ring[pi] = k_pi.pk;
188
189 let m: Vec<u8> = vec![1, 2, 3, 4];
190 let sig = k_pi.sign(ring.clone(), m.clone());
191 println!("sig {:?}", sig);
192
193 let key_image = k_pi.key_image();
194
195 let v = verify(ring.clone(), m.clone(), key_image, sig.clone());
196 println!("v {:?}", v);
197 assert!(v);
198
199 let m: Vec<u8> = vec![1, 2, 3, 3];
200 let v = verify(ring, m, key_image, sig);
201 assert!(!v);
202 }
203}