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::{fields::PrimeField, BigInteger, Fp256};
5use ark_std::{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
37#[allow(clippy::many_single_char_names)]
38impl KeyPair {
39 pub fn key_image(&self) -> EdwardsProjective {
40 hash_to_point(self.pk).mul(self.sk.into_repr())
41 }
42
43 pub fn sign(&self, ring: Vec<PublicKey>, m: Vec<u8>) -> Signature {
44 let ring_size = ring.len();
45 // determine pi (the position of signer's public key in R
46 let mut pi = 0;
47 let mut found = false;
48 // for i in 0..ring_size {
49 for (i, ring_key) in ring.iter().enumerate() {
50 if &self.pk == ring_key {
51 pi = i;
52 found = true;
53 break;
54 }
55 }
56 if !found {
57 // error
58 println!("key not found in the ring");
59 }
60
61 let mut rng = ark_std::rand::thread_rng();
62 let a: Fr = Fr::rand(&mut rng);
63 let mut r: Vec<Fr> = vec![Fr::zero(); ring_size];
64
65 // for i \in {1, 2, ..., n} \ {i=pi}
66 #[allow(clippy::needless_range_loop)]
67 for i in 0..ring_size {
68 if i == pi {
69 continue;
70 }
71 r[i] = Fr::rand(&mut rng);
72 }
73
74 let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
75 // c_{pi+1}
76 let pi1 = (pi + 1) % ring_size;
77 c[pi1] = hash(
78 &ring,
79 &m,
80 G.mul(a.into_repr()),
81 hash_to_point(ring[pi]).mul(a.into_repr()),
82 );
83
84 let key_image = self.key_image();
85 // do c_{i+1} from i=pi+1 to pi-1:
86 for j in 0..(ring_size - 1) {
87 let i = (pi1 + j) % ring_size;
88 let i1 = (pi1 + j + 1) % ring_size;
89 c[i1] = hash(
90 &ring,
91 &m,
92 G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
93 hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
94 );
95 println!("i {:?}, {:?}", i, c[i1]);
96 }
97
98 // compute r_pi
99 r[pi] = a - c[pi] * self.sk;
100 (c[0], r)
101 }
102}
103
104pub fn verify(
105 ring: Vec<PublicKey>,
106 m: Vec<u8>,
107 key_image: EdwardsProjective,
108 sig: Signature,
109) -> bool {
110 let ring_size = ring.len();
111
112 let c1 = sig.0;
113 let r = sig.1;
114 if ring_size != r.len() {
115 println!("ERROR"); // TODO
116 return false;
117 }
118 // TODO check that key_image \in G (EC), by l * key_image == 0
119
120 let mut c: Vec<Fr> = vec![Fr::zero(); ring_size];
121 c[0] = c1;
122 for j in 0..ring_size {
123 let i = j % ring_size;
124 let i1 = (j + 1) % ring_size;
125 c[i1] = hash(
126 &ring,
127 &m,
128 G.mul(r[i].into_repr()) + ring[i].mul(c[i].into_repr()),
129 hash_to_point(ring[i]).mul(r[i].into_repr()) + key_image.mul(c[i].into_repr()),
130 );
131 }
132
133 println!("c {:?}\n{:?}", c1, c[0]);
134
135 if c1 == c[0] {
136 return true;
137 }
138 false
139}
140
141fn hash_to_point(a: EdwardsProjective) -> EdwardsProjective {
142 // TODO use a proper hash_to_point method
143 let mut v: Vec<u8> = Vec::new();
144 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
145 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
146 let mut hasher = Sha256::new();
147 hasher.update(v);
148 let h = hasher.finalize();
149 let v = Fr::from_le_bytes_mod_order(&h[..]);
150
151 G.mul(v.into_repr())
152}
153
154fn hash(ring: &[PublicKey], m: &[u8], a: EdwardsProjective, b: EdwardsProjective) -> Fr {
155 let mut v: Vec<u8> = Vec::new();
156
157 for ring_key in ring.iter() {
158 v.append(&mut ring_key.into_affine().x.into_repr().to_bytes_le());
159 v.append(&mut ring_key.into_affine().y.into_repr().to_bytes_le());
160 }
161 v.append(&mut m.to_vec());
162 v.append(&mut a.into_affine().x.into_repr().to_bytes_le());
163 v.append(&mut a.into_affine().y.into_repr().to_bytes_le());
164 v.append(&mut b.into_affine().x.into_repr().to_bytes_le());
165 v.append(&mut b.into_affine().y.into_repr().to_bytes_le());
166
167 Fr::from_le_bytes_mod_order(&Sha256::new().chain_update(v).finalize())
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173
174 #[test]
175 #[allow(non_snake_case)]
176 fn test_bLSAG() {
177 let n = 5; // ring size
178 let pi = 3; // position of prover key in the ring
179
180 let k_pi = new_key();
181 println!("{:?}", k_pi);
182
183 // generate other n public keys
184 let mut ring: Vec<PublicKey> = vec![G.clone(); n];
185 for i in 0..n {
186 let k = new_key();
187 ring[i] = k.pk;
188 }
189 // set K_pi
190 ring[pi] = k_pi.pk;
191
192 let m: Vec<u8> = vec![1, 2, 3, 4];
193 let sig = k_pi.sign(ring.clone(), m.clone());
194 println!("sig {:?}", sig);
195
196 let key_image = k_pi.key_image();
197
198 let v = verify(ring.clone(), m.clone(), key_image, sig.clone());
199 println!("v {:?}", v);
200 assert!(v);
201
202 let m: Vec<u8> = vec![1, 2, 3, 3];
203 let v = verify(ring, m, key_image, sig);
204 assert!(!v);
205 }
206}