babyjubjub-rs/src/lib.rs
src/lib.rsRaw
1#[macro_use]
2extern crate arrayref;
3extern crate generic_array;
4extern crate mimc_rs;
5extern crate num;
6extern crate num_bigint;
7extern crate num_traits;
8extern crate rand;
9
10use blake2::{Blake2b, Digest};
11use mimc_rs::Mimc7;
12
13use num_bigint::{BigInt, RandBigInt, Sign, ToBigInt};
14use num_traits::{One, Zero};
15
16use generic_array::GenericArray;
17
18mod utils;
19
20#[macro_use]
21extern crate lazy_static;
22
23lazy_static! {
24 static ref D: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
25 static ref A: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
26 static ref Q: BigInt = BigInt::parse_bytes(
27 b"21888242871839275222246405745257275088548364400416034343698204186575808495617",
28 10,
29 )
30 .unwrap();
31 static ref B8: Point = Point {
32 x: BigInt::parse_bytes(
33 b"5299619240641551281634865583518297030282874472190772894086521144482721001553",
34 10,
35 )
36 .unwrap(),
37 y: BigInt::parse_bytes(
38 b"16950150798460657717958625567821834550301663161624707787222815936182638968203",
39 10,
40 )
41 .unwrap(),
42 };
43 static ref ORDER: BigInt = BigInt::parse_bytes(
44 b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
45 10,
46 )
47 .unwrap();
48 static ref SUBORDER: BigInt = &BigInt::parse_bytes(
49 b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
50 10,
51 )
52 .unwrap()
53 >> 3;
54}
55
56#[derive(Clone, Debug)]
57pub struct Point {
58 pub x: BigInt,
59 pub y: BigInt,
60}
61
62impl Point {
63 pub fn add(&self, q: &Point) -> Point {
64 // x = (x1*y2+y1*x2)/(c*(1+d*x1*x2*y1*y2))
65 // y = (y1*y2-x1*x2)/(c*(1-d*x1*x2*y1*y2))
66
67 // x = (x1 * y2 + y1 * x2) / (1 + d * x1 * y1 * y2)
68 let one: BigInt = One::one();
69 let x_num: BigInt = &self.x * &q.y + &self.y * &q.x;
70 let x_den: BigInt = &one + &D.clone() * &self.x * &q.x * &self.y * &q.y;
71 let x_den_inv = utils::modinv(&x_den, &Q);
72 let x: BigInt = utils::modulus(&(&x_num * &x_den_inv), &Q);
73
74 // y = (y1 * y2 - a * x1 * x2) / (1 - d * x1 * x2 * y1 * y2)
75 let y_num = &self.y * &q.y - &A.clone() * &self.x * &q.x;
76 let y_den = utils::modulus(&(&one - &D.clone() * &self.x * &q.x * &self.y * &q.y), &Q);
77 let y_den_inv = utils::modinv(&y_den, &Q);
78 let y: BigInt = utils::modulus(&(&y_num * &y_den_inv), &Q);
79
80 Point { x: x, y: y }
81 }
82
83 pub fn mul_scalar(&self, n: BigInt) -> Point {
84 // TODO use & in n to avoid clones on function call
85 let mut r: Point = Point {
86 x: Zero::zero(),
87 y: One::one(),
88 };
89 let mut rem: BigInt = n;
90 let mut exp: Point = self.clone();
91
92 let zero: BigInt = Zero::zero();
93 let one: BigInt = One::one();
94 while rem != zero {
95 let is_odd = &rem & &one == one;
96 if is_odd == true {
97 r = r.add(&exp);
98 }
99 exp = exp.add(&exp);
100 rem = rem >> 1;
101 }
102 r.x = utils::modulus(&r.x, &Q);
103 r.y = utils::modulus(&r.y, &Q);
104 r
105 }
106
107 pub fn compress(&self) -> [u8; 32] {
108 let mut r: [u8; 32];
109 let (_, y_bytes) = self.y.to_bytes_le();
110 r = *array_ref!(y_bytes, 0, 32);
111 if &self.x > &(&Q.clone() >> 1) {
112 r[31] = r[31] | 0x80;
113 }
114 r
115 }
116}
117
118pub fn decompress_point(bb: [u8; 32]) -> Point {
119 // https://tools.ietf.org/html/rfc8032#section-5.2.3
120 let mut sign: bool = false;
121 let mut b = bb.clone();
122 if b[31] & 0x80 != 0x00 {
123 sign = true;
124 b[31] = b[31] & 0x7F;
125 }
126 let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]);
127 if y >= Q.clone() {
128 // println!("ERROR0");
129 }
130 let one: BigInt = One::one();
131
132 // x^2 = (1 - y^2) / (a - d * y^2) (mod p)
133 let mut x: BigInt = utils::modulus(
134 &((one - utils::modulus(&(&y * &y), &Q))
135 * utils::modinv(
136 &utils::modulus(
137 &(&A.clone() - utils::modulus(&(&D.clone() * (&y * &y)), &Q)),
138 &Q,
139 ),
140 &Q,
141 )),
142 &Q,
143 );
144 x = utils::modsqrt(&x, &Q);
145
146 if (sign && x >= Zero::zero()) || (!sign && x < Zero::zero()) {
147 x = x * -1.to_bigint().unwrap();
148 }
149 x = utils::modulus(&x, &Q);
150 Point { x: x, y: y }
151}
152
153pub struct Signature {
154 r_b8: Point,
155 s: BigInt,
156}
157
158impl Signature {
159 pub fn compress(&self) -> [u8; 64] {
160 let mut b: Vec<u8> = Vec::new();
161 b.append(&mut self.r_b8.compress().to_vec());
162 // let (_, mut s_bytes) = self.s.to_bytes_le();
163 let (_, mut s_bytes) = self.s.to_bytes_le();
164 println!("sbytes LENGTH {:?}", s_bytes.len());
165 // let mut s_32bytes: [u8; 32] = [0; 32];
166 // s_32bytes[..].copy_from_slice(&s_bytes[..]);
167 b.append(&mut s_bytes);
168 let mut r: [u8; 64] = [0; 64];
169 // r = *array_ref!(b, 0, 64);
170 // r.copy_from_slice(&b[..]);
171 println!("b LENGTH {:?}", b.len());
172 // if b.len() < 64 {
173 // // let diff = 64 - b.len();
174 // println!("less than 64, add padding");
175 // let e: [u8; 1] = [0];
176 // b.append(&mut e.to_vec());
177 // }
178 r[..].copy_from_slice(&b[..]);
179 println!("r {:?}", r.len());
180 r
181 }
182}
183
184pub fn decompress_signature(b: &[u8; 64]) -> Signature {
185 let r_b8_bytes: [u8; 32] = *array_ref!(b[..32], 0, 32);
186 let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]);
187 let r_b8 = decompress_point(r_b8_bytes);
188 Signature {
189 r_b8: r_b8.clone(),
190 s: s,
191 }
192}
193
194pub struct PrivateKey {
195 key: BigInt,
196}
197
198impl PrivateKey {
199 pub fn public(&self) -> Point {
200 // https://tools.ietf.org/html/rfc8032#section-5.1.5
201 let pk = B8.mul_scalar(self.key.clone());
202 pk.clone()
203 }
204
205 pub fn sign(&self, msg: BigInt) -> Signature {
206 // https://tools.ietf.org/html/rfc8032#section-5.1.6
207 let mut hasher = Blake2b::new();
208 let (_, sk_bytes) = self.key.to_bytes_be();
209 hasher.input(sk_bytes);
210 let mut h = hasher.result(); // h: hash(sk)
211 // s: h[32:64]
212 let s = GenericArray::<u8, generic_array::typenum::U32>::from_mut_slice(&mut h[32..64]);
213 let (_, msg_bytes) = msg.to_bytes_be();
214 let r_bytes = utils::concatenate_arrays(s, &msg_bytes);
215 let mut r = BigInt::from_bytes_be(Sign::Plus, &r_bytes[..]);
216 r = utils::modulus(&r, &SUBORDER);
217 let r8: Point = B8.mul_scalar(r.clone());
218 let a = &self.public();
219
220 let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg];
221 let mimc7 = Mimc7::new();
222 let hm = mimc7.hash(hm_input);
223
224 let mut s = &self.key << 3;
225 s = hm * s;
226 s = r + s;
227 s = s % &SUBORDER.clone();
228
229 Signature {
230 r_b8: r8.clone(),
231 s: s,
232 }
233 }
234}
235
236pub fn new_key() -> PrivateKey {
237 // https://tools.ietf.org/html/rfc8032#section-5.1.5
238 let mut rng = rand::thread_rng();
239 let sk_raw = rng.gen_biguint(1024).to_bigint().unwrap();
240
241 let mut hasher = Blake2b::new();
242 let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
243 hasher.input(sk_raw_bytes);
244 let mut h = hasher.result();
245
246 h[0] = h[0] & 0xF8;
247 h[31] = h[31] & 0x7F;
248 h[31] = h[31] | 0x40;
249
250 let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
251
252 PrivateKey { key: sk }
253}
254
255pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
256 let hm_input = vec![
257 sig.r_b8.x.clone(),
258 sig.r_b8.y.clone(),
259 pk.x.clone(),
260 pk.y.clone(),
261 msg,
262 ];
263 let mimc7 = Mimc7::new();
264 let hm = mimc7.hash(hm_input);
265 let l = B8.mul_scalar(sig.s);
266 let r = sig.r_b8.add(&pk.mul_scalar(8.to_bigint().unwrap() * hm));
267 if l.x == r.x && l.y == r.y {
268 return true;
269 }
270 false
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276 extern crate rustc_hex;
277 use rustc_hex::ToHex;
278
279 #[test]
280 fn test_add_same_point() {
281 let p: Point = Point {
282 x: BigInt::parse_bytes(
283 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
284 10,
285 )
286 .unwrap(),
287 y: BigInt::parse_bytes(
288 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
289 10,
290 )
291 .unwrap(),
292 };
293 let q: Point = Point {
294 x: BigInt::parse_bytes(
295 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
296 10,
297 )
298 .unwrap(),
299 y: BigInt::parse_bytes(
300 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
301 10,
302 )
303 .unwrap(),
304 };
305 let res = p.add(&q);
306 assert_eq!(
307 res.x.to_string(),
308 "6890855772600357754907169075114257697580319025794532037257385534741338397365"
309 );
310 assert_eq!(
311 res.y.to_string(),
312 "4338620300185947561074059802482547481416142213883829469920100239455078257889"
313 );
314 }
315 #[test]
316 fn test_add_different_points() {
317 let p: Point = Point {
318 x: BigInt::parse_bytes(
319 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
320 10,
321 )
322 .unwrap(),
323 y: BigInt::parse_bytes(
324 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
325 10,
326 )
327 .unwrap(),
328 };
329 let q: Point = Point {
330 x: BigInt::parse_bytes(
331 b"16540640123574156134436876038791482806971768689494387082833631921987005038935",
332 10,
333 )
334 .unwrap(),
335 y: BigInt::parse_bytes(
336 b"20819045374670962167435360035096875258406992893633759881276124905556507972311",
337 10,
338 )
339 .unwrap(),
340 };
341 let res = p.add(&q);
342 assert_eq!(
343 res.x.to_string(),
344 "7916061937171219682591368294088513039687205273691143098332585753343424131937"
345 );
346 assert_eq!(
347 res.y.to_string(),
348 "14035240266687799601661095864649209771790948434046947201833777492504781204499"
349 );
350 }
351
352 #[test]
353 fn test_mul_scalar() {
354 let p: Point = Point {
355 x: BigInt::parse_bytes(
356 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
357 10,
358 )
359 .unwrap(),
360 y: BigInt::parse_bytes(
361 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
362 10,
363 )
364 .unwrap(),
365 };
366 let res_m = p.mul_scalar(3.to_bigint().unwrap());
367 let res_a = p.add(&p);
368 let res_a = res_a.add(&p);
369 assert_eq!(res_m.x, res_a.x);
370 assert_eq!(
371 res_m.x.to_string(),
372 "19372461775513343691590086534037741906533799473648040012278229434133483800898"
373 );
374 assert_eq!(
375 res_m.y.to_string(),
376 "9458658722007214007257525444427903161243386465067105737478306991484593958249"
377 );
378
379 let n = BigInt::parse_bytes(
380 b"14035240266687799601661095864649209771790948434046947201833777492504781204499",
381 10,
382 )
383 .unwrap();
384 let res2 = p.mul_scalar(n);
385 assert_eq!(
386 res2.x.to_string(),
387 "17070357974431721403481313912716834497662307308519659060910483826664480189605"
388 );
389 assert_eq!(
390 res2.y.to_string(),
391 "4014745322800118607127020275658861516666525056516280575712425373174125159339"
392 );
393 }
394
395 #[test]
396 fn test_point_compress_decompress() {
397 let p: Point = Point {
398 x: BigInt::parse_bytes(
399 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
400 10,
401 )
402 .unwrap(),
403 y: BigInt::parse_bytes(
404 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
405 10,
406 )
407 .unwrap(),
408 };
409 let p_comp = p.compress();
410 assert_eq!(
411 p_comp[..].to_hex(),
412 "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85"
413 );
414 let p2 = decompress_point(p_comp);
415 assert_eq!(p.x, p2.x);
416 assert_eq!(p.y, p2.y);
417 }
418
419 #[test]
420 fn test_new_key_sign_verify0() {
421 let sk = new_key();
422 let pk = sk.public();
423 let msg = 5.to_bigint().unwrap();
424 let sig = sk.sign(msg.clone());
425 let v = verify(pk, sig, msg);
426 assert_eq!(v, true);
427 }
428
429 #[test]
430 fn test_new_key_sign_verify1() {
431 let sk = new_key();
432 let pk = sk.public();
433 let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
434 let sig = sk.sign(msg.clone());
435 let v = verify(pk, sig, msg);
436 assert_eq!(v, true);
437 }
438
439 #[test]
440 fn test_signature_compress_decompress() {
441 let sk = new_key();
442 let pk = sk.public();
443
444 for i in 0..1 {
445 println!("i {:?}", i);
446 let msg_raw = "123456".to_owned() + &i.to_string();
447 let msg = BigInt::parse_bytes(msg_raw.as_bytes(), 10).unwrap();
448 let sig = sk.sign(msg.clone());
449
450 let compressed_sig = sig.compress();
451 println!("compressedsig {:?}", compressed_sig.to_hex());
452 let decompressed_sig = decompress_signature(&compressed_sig);
453 assert_eq!(&sig.r_b8.x, &decompressed_sig.r_b8.x);
454 assert_eq!(&sig.r_b8.y, &decompressed_sig.r_b8.y);
455 assert_eq!(&sig.s, &decompressed_sig.s);
456
457 let v = verify(pk.clone(), decompressed_sig, msg);
458 assert_eq!(v, true);
459 }
460 }
461}