Browse Source

fix point & signature compress & decompress

main
arnaucube 5 years ago
parent
commit
ad33bbd537
2 changed files with 89 additions and 34 deletions
  1. +4
    -1
      README.md
  2. +85
    -33
      src/lib.rs

+ 4
- 1
README.md

@ -3,7 +3,10 @@ BabyJubJub elliptic curve implementation in Rust.
BabyJubJub is a twisted edwards curve embedded in the curve of BN128.
Uses MiMC7 hash function: https://github.com/arnaucube/mimc-rs
BabyJubJub curve explanation: https://medium.com/zokrates/efficient-ecc-in-zksnarks-using-zokrates-bd9ae37b8186
Uses:
- MiMC7 hash function: https://github.com/arnaucube/mimc-rs
## Warning
Doing this in my free time to get familiar with Rust, do not use in production.

+ 85
- 33
src/lib.rs

@ -9,6 +9,7 @@ extern crate rand;
use blake2::{Blake2b, Digest};
use mimc_rs::Mimc7;
use std::cmp::min;
use num_bigint::{BigInt, RandBigInt, Sign, ToBigInt};
use num_traits::{One, Zero};
@ -105,17 +106,18 @@ impl Point {
}
pub fn compress(&self) -> [u8; 32] {
let mut r: [u8; 32];
let mut r: [u8; 32] = [0; 32];
let (_, y_bytes) = self.y.to_bytes_le();
r = *array_ref!(y_bytes, 0, 32);
if &self.x > &(&Q.clone() >> 1) {
let len = min(y_bytes.len(), r.len());
r[..len].copy_from_slice(&y_bytes[..len]);
if &self.x >= &(&Q.clone() >> 1) {
r[31] = r[31] | 0x80;
}
r
}
}
pub fn decompress_point(bb: [u8; 32]) -> Point {
pub fn decompress_point(bb: [u8; 32]) -> Result<Point, String> {
// https://tools.ietf.org/html/rfc8032#section-5.2.3
let mut sign: bool = false;
let mut b = bb.clone();
@ -125,7 +127,7 @@ pub fn decompress_point(bb: [u8; 32]) -> Point {
}
let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]);
if y >= Q.clone() {
// println!("ERROR0");
return Err("y outside the Finite Field over R".to_string());
}
let one: BigInt = One::one();
@ -143,11 +145,11 @@ pub fn decompress_point(bb: [u8; 32]) -> Point {
);
x = utils::modsqrt(&x, &Q);
if (sign && x >= Zero::zero()) || (!sign && x < Zero::zero()) {
if sign && !(&x > &(&Q.clone() >> 1)) || (!sign && (&x > &(&Q.clone() >> 1))) {
x = x * -1.to_bigint().unwrap();
}
x = utils::modulus(&x, &Q);
Point { x: x, y: y }
Ok(Point { x: x, y: y })
}
pub struct Signature {
@ -159,35 +161,27 @@ impl Signature {
pub fn compress(&self) -> [u8; 64] {
let mut b: Vec<u8> = Vec::new();
b.append(&mut self.r_b8.compress().to_vec());
// let (_, mut s_bytes) = self.s.to_bytes_le();
let (_, mut s_bytes) = self.s.to_bytes_le();
println!("sbytes LENGTH {:?}", s_bytes.len());
// let mut s_32bytes: [u8; 32] = [0; 32];
// s_32bytes[..].copy_from_slice(&s_bytes[..]);
b.append(&mut s_bytes);
let (_, s_bytes) = self.s.to_bytes_le();
let mut s_32bytes: [u8; 32] = [0; 32];
let len = min(s_bytes.len(), s_32bytes.len());
s_32bytes[..len].copy_from_slice(&s_bytes[..len]);
b.append(&mut s_32bytes.to_vec());
let mut r: [u8; 64] = [0; 64];
// r = *array_ref!(b, 0, 64);
// r.copy_from_slice(&b[..]);
println!("b LENGTH {:?}", b.len());
// if b.len() < 64 {
// // let diff = 64 - b.len();
// println!("less than 64, add padding");
// let e: [u8; 1] = [0];
// b.append(&mut e.to_vec());
// }
r[..].copy_from_slice(&b[..]);
println!("r {:?}", r.len());
r
}
}
pub fn decompress_signature(b: &[u8; 64]) -> Signature {
pub fn decompress_signature(b: &[u8; 64]) -> Result<Signature, String> {
let r_b8_bytes: [u8; 32] = *array_ref!(b[..32], 0, 32);
let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]);
let r_b8 = decompress_point(r_b8_bytes);
Signature {
r_b8: r_b8.clone(),
s: s,
match r_b8 {
Result::Err(err) => return Err(err.to_string()),
Result::Ok(res) => Ok(Signature {
r_b8: res.clone(),
s: s,
}),
}
}
@ -274,7 +268,7 @@ pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
mod tests {
use super::*;
extern crate rustc_hex;
use rustc_hex::ToHex;
use rustc_hex::{FromHex, ToHex};
#[test]
fn test_add_same_point() {
@ -411,7 +405,7 @@ mod tests {
p_comp[..].to_hex(),
"53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85"
);
let p2 = decompress_point(p_comp);
let p2 = decompress_point(p_comp).unwrap();
assert_eq!(p.x, p2.x);
assert_eq!(p.y, p2.y);
}
@ -436,20 +430,78 @@ mod tests {
assert_eq!(v, true);
}
#[test]
fn test_point_decompress0() {
let y_bytes_raw = "b5328f8791d48f20bec6e481d91c7ada235f1facf22547901c18656b6c3e042f"
.from_hex()
.unwrap();
let mut y_bytes: [u8; 32] = [0; 32];
y_bytes.copy_from_slice(&y_bytes_raw);
let p = decompress_point(y_bytes).unwrap();
let expected_px_raw = "b86cc8d9c97daef0afe1a4753c54fb2d8a530dc74c7eee4e72b3fdf2496d2113"
.from_hex()
.unwrap();
let mut e_px_bytes: [u8; 32] = [0; 32];
e_px_bytes.copy_from_slice(&expected_px_raw);
let expected_px: BigInt = BigInt::from_bytes_le(Sign::Plus, &e_px_bytes);
assert_eq!(&p.x, &expected_px);
}
#[test]
fn test_point_decompress1() {
let y_bytes_raw = "70552d3ff548e09266ded29b33ce75139672b062b02aa66bb0d9247ffecf1d0b"
.from_hex()
.unwrap();
let mut y_bytes: [u8; 32] = [0; 32];
y_bytes.copy_from_slice(&y_bytes_raw);
let p = decompress_point(y_bytes).unwrap();
let expected_px_raw = "30f1635ba7d56f9cb32c3ffbe6dca508a68c7f43936af11a23c785ce98cb3404"
.from_hex()
.unwrap();
let mut e_px_bytes: [u8; 32] = [0; 32];
e_px_bytes.copy_from_slice(&expected_px_raw);
let expected_px: BigInt = BigInt::from_bytes_le(Sign::Plus, &e_px_bytes);
assert_eq!(&p.x, &expected_px);
}
#[test]
fn test_point_decompress_loop() {
for _ in 0..5 {
let mut rng = rand::thread_rng();
let sk_raw = rng.gen_biguint(1024).to_bigint().unwrap();
let mut hasher = Blake2b::new();
let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
hasher.input(sk_raw_bytes);
let mut h = hasher.result();
h[0] = h[0] & 0xF8;
h[31] = h[31] & 0x7F;
h[31] = h[31] | 0x40;
let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
let point = B8.mul_scalar(sk.clone());
let cmp_point = point.compress();
let dcmp_point = decompress_point(cmp_point).unwrap();
assert_eq!(&point.x, &dcmp_point.x);
assert_eq!(&point.y, &dcmp_point.y);
}
}
#[test]
fn test_signature_compress_decompress() {
let sk = new_key();
let pk = sk.public();
for i in 0..1 {
println!("i {:?}", i);
for i in 0..5 {
let msg_raw = "123456".to_owned() + &i.to_string();
let msg = BigInt::parse_bytes(msg_raw.as_bytes(), 10).unwrap();
let sig = sk.sign(msg.clone());
let compressed_sig = sig.compress();
println!("compressedsig {:?}", compressed_sig.to_hex());
let decompressed_sig = decompress_signature(&compressed_sig);
let decompressed_sig = decompress_signature(&compressed_sig).unwrap();
assert_eq!(&sig.r_b8.x, &decompressed_sig.r_b8.x);
assert_eq!(&sig.r_b8.y, &decompressed_sig.r_b8.y);
assert_eq!(&sig.s, &decompressed_sig.s);

Loading…
Cancel
Save