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;
12use poseidon_rs::Poseidon;
13use std::cmp::min;
14
15use num_bigint::{BigInt, RandBigInt, Sign, ToBigInt};
16use num_traits::{One, Zero};
17
18use generic_array::GenericArray;
19
20mod utils;
21
22#[macro_use]
23extern crate lazy_static;
24
25lazy_static! {
26 static ref D: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
27 static ref A: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
28 static ref Q: BigInt = BigInt::parse_bytes(
29 b"21888242871839275222246405745257275088548364400416034343698204186575808495617",
30 10,
31 )
32 .unwrap();
33 static ref B8: Point = Point {
34 x: BigInt::parse_bytes(
35 b"5299619240641551281634865583518297030282874472190772894086521144482721001553",
36 10,
37 )
38 .unwrap(),
39 y: BigInt::parse_bytes(
40 b"16950150798460657717958625567821834550301663161624707787222815936182638968203",
41 10,
42 )
43 .unwrap(),
44 };
45 static ref ORDER: BigInt = BigInt::parse_bytes(
46 b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
47 10,
48 )
49 .unwrap();
50 static ref SUBORDER: BigInt = &BigInt::parse_bytes(
51 b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
52 10,
53 )
54 .unwrap()
55 >> 3;
56}
57
58#[derive(Clone, Debug)]
59pub struct Point {
60 pub x: BigInt,
61 pub y: BigInt,
62}
63
64impl Point {
65 pub fn add(&self, q: &Point) -> Result<Point, String> {
66 // x = (x1*y2+y1*x2)/(c*(1+d*x1*x2*y1*y2))
67 // y = (y1*y2-x1*x2)/(c*(1-d*x1*x2*y1*y2))
68
69 // x = (x1 * y2 + y1 * x2) / (1 + d * x1 * y1 * y2)
70 let one: BigInt = One::one();
71 let x_num: BigInt = &self.x * &q.y + &self.y * &q.x;
72 let x_den: BigInt = &one + &D.clone() * &self.x * &q.x * &self.y * &q.y;
73 let x_den_inv = utils::modinv(&x_den, &Q)?;
74 let x: BigInt = utils::modulus(&(&x_num * &x_den_inv), &Q);
75
76 // y = (y1 * y2 - a * x1 * x2) / (1 - d * x1 * x2 * y1 * y2)
77 let y_num = &self.y * &q.y - &A.clone() * &self.x * &q.x;
78 let y_den = utils::modulus(&(&one - &D.clone() * &self.x * &q.x * &self.y * &q.y), &Q);
79 let y_den_inv = utils::modinv(&y_den, &Q)?;
80 let y: BigInt = utils::modulus(&(&y_num * &y_den_inv), &Q);
81
82 Ok(Point { x: x, y: y })
83 }
84
85 pub fn mul_scalar(&self, n: &BigInt) -> Result<Point, String> {
86 // TODO use & in n to avoid clones on function call
87 let mut r: Point = Point {
88 x: Zero::zero(),
89 y: One::one(),
90 };
91 let mut rem: BigInt = n.clone();
92 let mut exp: Point = self.clone();
93
94 let zero: BigInt = Zero::zero();
95 let one: BigInt = One::one();
96 while rem != zero {
97 let is_odd = &rem & &one == one;
98 if is_odd == true {
99 r = r.add(&exp)?;
100 }
101 exp = exp.add(&exp)?;
102 rem = rem >> 1;
103 }
104 r.x = utils::modulus(&r.x, &Q);
105 r.y = utils::modulus(&r.y, &Q);
106 Ok(r)
107 }
108
109 pub fn compress(&self) -> [u8; 32] {
110 let mut r: [u8; 32] = [0; 32];
111 let (_, y_bytes) = self.y.to_bytes_le();
112 let len = min(y_bytes.len(), r.len());
113 r[..len].copy_from_slice(&y_bytes[..len]);
114 if &self.x > &(&Q.clone() >> 1) {
115 r[31] = r[31] | 0x80;
116 }
117 r
118 }
119}
120
121pub fn decompress_point(bb: [u8; 32]) -> Result<Point, String> {
122 // https://tools.ietf.org/html/rfc8032#section-5.2.3
123 let mut sign: bool = false;
124 let mut b = bb.clone();
125 if b[31] & 0x80 != 0x00 {
126 sign = true;
127 b[31] = b[31] & 0x7F;
128 }
129 let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]);
130 if y >= Q.clone() {
131 return Err("y outside the Finite Field over R".to_string());
132 }
133 let one: BigInt = One::one();
134
135 // x^2 = (1 - y^2) / (a - d * y^2) (mod p)
136 let den = utils::modinv(
137 &utils::modulus(
138 &(&A.clone() - utils::modulus(&(&D.clone() * (&y * &y)), &Q)),
139 &Q,
140 ),
141 &Q,
142 )?;
143 let mut x: BigInt = utils::modulus(&((one - utils::modulus(&(&y * &y), &Q)) * den), &Q);
144 x = utils::modsqrt(&x, &Q)?;
145
146 if sign && !(&x > &(&Q.clone() >> 1)) || (!sign && (&x > &(&Q.clone() >> 1))) {
147 x = x * -1.to_bigint().unwrap();
148 }
149 x = utils::modulus(&x, &Q);
150 Ok(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 (_, s_bytes) = self.s.to_bytes_le();
163 let mut s_32bytes: [u8; 32] = [0; 32];
164 let len = min(s_bytes.len(), s_32bytes.len());
165 s_32bytes[..len].copy_from_slice(&s_bytes[..len]);
166 b.append(&mut s_32bytes.to_vec());
167 let mut r: [u8; 64] = [0; 64];
168 r[..].copy_from_slice(&b[..]);
169 r
170 }
171}
172
173pub fn decompress_signature(b: &[u8; 64]) -> Result<Signature, String> {
174 let r_b8_bytes: [u8; 32] = *array_ref!(b[..32], 0, 32);
175 let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]);
176 let r_b8 = decompress_point(r_b8_bytes);
177 match r_b8 {
178 Result::Err(err) => return Err(err.to_string()),
179 Result::Ok(res) => Ok(Signature {
180 r_b8: res.clone(),
181 s: s,
182 }),
183 }
184}
185
186pub struct PrivateKey {
187 key: BigInt,
188}
189
190impl PrivateKey {
191 pub fn public(&self) -> Result<Point, String> {
192 // https://tools.ietf.org/html/rfc8032#section-5.1.5
193 let pk = B8.mul_scalar(&self.key)?;
194 Ok(pk.clone())
195 }
196
197 pub fn sign_mimc(&self, msg: BigInt) -> Result<Signature, String> {
198 // https://tools.ietf.org/html/rfc8032#section-5.1.6
199 let mut hasher = Blake2b::new();
200 let (_, sk_bytes) = self.key.to_bytes_be();
201 hasher.input(sk_bytes);
202 let mut h = hasher.result(); // h: hash(sk)
203 // s: h[32:64]
204 let s = GenericArray::<u8, generic_array::typenum::U32>::from_mut_slice(&mut h[32..64]);
205 let (_, msg_bytes) = msg.to_bytes_be();
206 let r_bytes = utils::concatenate_arrays(s, &msg_bytes);
207 let mut r = BigInt::from_bytes_be(Sign::Plus, &r_bytes[..]);
208 r = utils::modulus(&r, &SUBORDER);
209 let r8: Point = B8.mul_scalar(&r)?;
210 let a = &self.public()?;
211
212 let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg];
213 let mimc7 = Mimc7::new();
214 let hm = mimc7.hash(hm_input)?;
215
216 let mut s = &self.key << 3;
217 s = hm * s;
218 s = r + s;
219 s = s % &SUBORDER.clone();
220
221 Ok(Signature {
222 r_b8: r8.clone(),
223 s: s,
224 })
225 }
226 pub fn sign_poseidon(&self, msg: BigInt) -> Result<Signature, String> {
227 // https://tools.ietf.org/html/rfc8032#section-5.1.6
228 let mut hasher = Blake2b::new();
229 let (_, sk_bytes) = self.key.to_bytes_be();
230 hasher.input(sk_bytes);
231 let mut h = hasher.result(); // h: hash(sk)
232 // s: h[32:64]
233 let s = GenericArray::<u8, generic_array::typenum::U32>::from_mut_slice(&mut h[32..64]);
234 let (_, msg_bytes) = msg.to_bytes_be();
235 let r_bytes = utils::concatenate_arrays(s, &msg_bytes);
236 let mut r = BigInt::from_bytes_be(Sign::Plus, &r_bytes[..]);
237 r = utils::modulus(&r, &SUBORDER);
238 let r8: Point = B8.mul_scalar(&r)?;
239 let a = &self.public()?;
240
241 let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg];
242 let poseidon = Poseidon::new();
243 let hm = poseidon.hash(hm_input)?;
244
245 let mut s = &self.key << 3;
246 s = hm * s;
247 s = r + s;
248 s = s % &SUBORDER.clone();
249
250 Ok(Signature {
251 r_b8: r8.clone(),
252 s: s,
253 })
254 }
255}
256
257pub fn new_key() -> PrivateKey {
258 // https://tools.ietf.org/html/rfc8032#section-5.1.5
259 let mut rng = rand::thread_rng();
260 let sk_raw = rng.gen_biguint(1024).to_bigint().unwrap();
261
262 let mut hasher = Blake2b::new();
263 let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
264 hasher.input(sk_raw_bytes);
265 let mut h = hasher.result();
266
267 h[0] = h[0] & 0xF8;
268 h[31] = h[31] & 0x7F;
269 h[31] = h[31] | 0x40;
270
271 let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
272
273 PrivateKey { key: sk }
274}
275
276pub fn verify_mimc(pk: Point, sig: Signature, msg: BigInt) -> bool {
277 let hm_input = vec![
278 sig.r_b8.x.clone(),
279 sig.r_b8.y.clone(),
280 pk.x.clone(),
281 pk.y.clone(),
282 msg,
283 ];
284 let mimc7 = Mimc7::new();
285 let hm = match mimc7.hash(hm_input) {
286 Result::Err(_) => return false,
287 Result::Ok(hm) => hm,
288 };
289 let l = match B8.mul_scalar(&sig.s) {
290 Result::Err(_) => return false,
291 Result::Ok(l) => l,
292 };
293 let r = match sig
294 .r_b8
295 .add(&pk.mul_scalar(&(8.to_bigint().unwrap() * hm)).unwrap())
296 {
297 Result::Err(_) => return false,
298 Result::Ok(r) => r,
299 };
300 if l.x == r.x && l.y == r.y {
301 return true;
302 }
303 false
304}
305pub fn verify_poseidon(pk: Point, sig: Signature, msg: BigInt) -> bool {
306 let hm_input = vec![
307 sig.r_b8.x.clone(),
308 sig.r_b8.y.clone(),
309 pk.x.clone(),
310 pk.y.clone(),
311 msg,
312 ];
313 let poseidon = Poseidon::new();
314 let hm = match poseidon.hash(hm_input) {
315 Result::Err(_) => return false,
316 Result::Ok(hm) => hm,
317 };
318 let l = match B8.mul_scalar(&sig.s) {
319 Result::Err(_) => return false,
320 Result::Ok(l) => l,
321 };
322 let r = match sig
323 .r_b8
324 .add(&pk.mul_scalar(&(8.to_bigint().unwrap() * hm)).unwrap())
325 {
326 Result::Err(_) => return false,
327 Result::Ok(r) => r,
328 };
329 if l.x == r.x && l.y == r.y {
330 return true;
331 }
332 false
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 extern crate rustc_hex;
339 use rustc_hex::{FromHex, ToHex};
340
341 #[test]
342 fn test_add_same_point() {
343 let p: Point = Point {
344 x: BigInt::parse_bytes(
345 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
346 10,
347 )
348 .unwrap(),
349 y: BigInt::parse_bytes(
350 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
351 10,
352 )
353 .unwrap(),
354 };
355 let q: Point = Point {
356 x: BigInt::parse_bytes(
357 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
358 10,
359 )
360 .unwrap(),
361 y: BigInt::parse_bytes(
362 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
363 10,
364 )
365 .unwrap(),
366 };
367 let res = p.add(&q).unwrap();
368 assert_eq!(
369 res.x.to_string(),
370 "6890855772600357754907169075114257697580319025794532037257385534741338397365"
371 );
372 assert_eq!(
373 res.y.to_string(),
374 "4338620300185947561074059802482547481416142213883829469920100239455078257889"
375 );
376 }
377 #[test]
378 fn test_add_different_points() {
379 let p: Point = Point {
380 x: BigInt::parse_bytes(
381 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
382 10,
383 )
384 .unwrap(),
385 y: BigInt::parse_bytes(
386 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
387 10,
388 )
389 .unwrap(),
390 };
391 let q: Point = Point {
392 x: BigInt::parse_bytes(
393 b"16540640123574156134436876038791482806971768689494387082833631921987005038935",
394 10,
395 )
396 .unwrap(),
397 y: BigInt::parse_bytes(
398 b"20819045374670962167435360035096875258406992893633759881276124905556507972311",
399 10,
400 )
401 .unwrap(),
402 };
403 let res = p.add(&q).unwrap();
404 assert_eq!(
405 res.x.to_string(),
406 "7916061937171219682591368294088513039687205273691143098332585753343424131937"
407 );
408 assert_eq!(
409 res.y.to_string(),
410 "14035240266687799601661095864649209771790948434046947201833777492504781204499"
411 );
412 }
413
414 #[test]
415 fn test_mul_scalar() {
416 let p: Point = Point {
417 x: BigInt::parse_bytes(
418 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
419 10,
420 )
421 .unwrap(),
422 y: BigInt::parse_bytes(
423 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
424 10,
425 )
426 .unwrap(),
427 };
428 let res_m = p.mul_scalar(&3.to_bigint().unwrap()).unwrap();
429 let res_a = p.add(&p).unwrap();
430 let res_a = res_a.add(&p).unwrap();
431 assert_eq!(res_m.x, res_a.x);
432 assert_eq!(
433 res_m.x.to_string(),
434 "19372461775513343691590086534037741906533799473648040012278229434133483800898"
435 );
436 assert_eq!(
437 res_m.y.to_string(),
438 "9458658722007214007257525444427903161243386465067105737478306991484593958249"
439 );
440
441 let n = BigInt::parse_bytes(
442 b"14035240266687799601661095864649209771790948434046947201833777492504781204499",
443 10,
444 )
445 .unwrap();
446 let res2 = p.mul_scalar(&n).unwrap();
447 assert_eq!(
448 res2.x.to_string(),
449 "17070357974431721403481313912716834497662307308519659060910483826664480189605"
450 );
451 assert_eq!(
452 res2.y.to_string(),
453 "4014745322800118607127020275658861516666525056516280575712425373174125159339"
454 );
455 }
456
457 #[test]
458 fn test_new_key_sign_verify_mimc_0() {
459 let sk = new_key();
460 let pk = sk.public().unwrap();
461 let msg = 5.to_bigint().unwrap();
462 let sig = sk.sign_mimc(msg.clone()).unwrap();
463 let v = verify_mimc(pk, sig, msg);
464 assert_eq!(v, true);
465 }
466
467 #[test]
468 fn test_new_key_sign_verify_mimc_1() {
469 let sk = new_key();
470 let pk = sk.public().unwrap();
471 let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
472 let sig = sk.sign_mimc(msg.clone()).unwrap();
473 let v = verify_mimc(pk, sig, msg);
474 assert_eq!(v, true);
475 }
476 #[test]
477 fn test_new_key_sign_verify_poseidon_0() {
478 let sk = new_key();
479 let pk = sk.public().unwrap();
480 let msg = 5.to_bigint().unwrap();
481 let sig = sk.sign_poseidon(msg.clone()).unwrap();
482 let v = verify_poseidon(pk, sig, msg);
483 assert_eq!(v, true);
484 }
485
486 #[test]
487 fn test_new_key_sign_verify_poseidon_1() {
488 let sk = new_key();
489 let pk = sk.public().unwrap();
490 let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
491 let sig = sk.sign_poseidon(msg.clone()).unwrap();
492 let v = verify_poseidon(pk, sig, msg);
493 assert_eq!(v, true);
494 }
495
496 #[test]
497 fn test_point_compress_decompress() {
498 let p: Point = Point {
499 x: BigInt::parse_bytes(
500 b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
501 10,
502 )
503 .unwrap(),
504 y: BigInt::parse_bytes(
505 b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
506 10,
507 )
508 .unwrap(),
509 };
510 let p_comp = p.compress();
511 assert_eq!(
512 p_comp[..].to_hex(),
513 "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85"
514 );
515 let p2 = decompress_point(p_comp).unwrap();
516 assert_eq!(p.x, p2.x);
517 assert_eq!(p.y, p2.y);
518 }
519
520 #[test]
521 fn test_point_decompress0() {
522 let y_bytes_raw = "b5328f8791d48f20bec6e481d91c7ada235f1facf22547901c18656b6c3e042f"
523 .from_hex()
524 .unwrap();
525 let mut y_bytes: [u8; 32] = [0; 32];
526 y_bytes.copy_from_slice(&y_bytes_raw);
527 let p = decompress_point(y_bytes).unwrap();
528
529 let expected_px_raw = "b86cc8d9c97daef0afe1a4753c54fb2d8a530dc74c7eee4e72b3fdf2496d2113"
530 .from_hex()
531 .unwrap();
532 let mut e_px_bytes: [u8; 32] = [0; 32];
533 e_px_bytes.copy_from_slice(&expected_px_raw);
534 let expected_px: BigInt = BigInt::from_bytes_le(Sign::Plus, &e_px_bytes);
535 assert_eq!(&p.x, &expected_px);
536 }
537
538 #[test]
539 fn test_point_decompress1() {
540 let y_bytes_raw = "70552d3ff548e09266ded29b33ce75139672b062b02aa66bb0d9247ffecf1d0b"
541 .from_hex()
542 .unwrap();
543 let mut y_bytes: [u8; 32] = [0; 32];
544 y_bytes.copy_from_slice(&y_bytes_raw);
545 let p = decompress_point(y_bytes).unwrap();
546
547 let expected_px_raw = "30f1635ba7d56f9cb32c3ffbe6dca508a68c7f43936af11a23c785ce98cb3404"
548 .from_hex()
549 .unwrap();
550 let mut e_px_bytes: [u8; 32] = [0; 32];
551 e_px_bytes.copy_from_slice(&expected_px_raw);
552 let expected_px: BigInt = BigInt::from_bytes_le(Sign::Plus, &e_px_bytes);
553 assert_eq!(&p.x, &expected_px);
554 }
555
556 #[test]
557 fn test_point_decompress_loop() {
558 for _ in 0..5 {
559 let mut rng = rand::thread_rng();
560 let sk_raw = rng.gen_biguint(1024).to_bigint().unwrap();
561 let mut hasher = Blake2b::new();
562 let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
563 hasher.input(sk_raw_bytes);
564 let mut h = hasher.result();
565
566 h[0] = h[0] & 0xF8;
567 h[31] = h[31] & 0x7F;
568 h[31] = h[31] | 0x40;
569
570 let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
571 let point = B8.mul_scalar(&sk).unwrap();
572 let cmp_point = point.compress();
573 let dcmp_point = decompress_point(cmp_point).unwrap();
574
575 assert_eq!(&point.x, &dcmp_point.x);
576 assert_eq!(&point.y, &dcmp_point.y);
577 }
578 }
579
580 #[test]
581 fn test_signature_compress_decompress() {
582 let sk = new_key();
583 let pk = sk.public().unwrap();
584
585 for i in 0..5 {
586 let msg_raw = "123456".to_owned() + &i.to_string();
587 let msg = BigInt::parse_bytes(msg_raw.as_bytes(), 10).unwrap();
588 let sig = sk.sign_mimc(msg.clone()).unwrap();
589
590 let compressed_sig = sig.compress();
591 let decompressed_sig = decompress_signature(&compressed_sig).unwrap();
592 assert_eq!(&sig.r_b8.x, &decompressed_sig.r_b8.x);
593 assert_eq!(&sig.r_b8.y, &decompressed_sig.r_b8.y);
594 assert_eq!(&sig.s, &decompressed_sig.s);
595
596 let v = verify_mimc(pk.clone(), decompressed_sig, msg);
597 assert_eq!(v, true);
598 }
599 }
600}