Browse Source

add sign & verify with Poseidon hash, update MiMC use to v0.0.2

aggregated-schnorr-musig
arnaucube 4 years ago
parent
commit
2ab48ff3ad
3 changed files with 116 additions and 34 deletions
  1. +5
    -2
      Cargo.toml
  2. +5
    -4
      README.md
  3. +106
    -28
      src/lib.rs

+ 5
- 2
Cargo.toml

@ -1,10 +1,12 @@
[package]
name = "babyjubjub-rs"
version = "0.0.1"
version = "0.0.2"
authors = ["arnaucube <root@arnaucube.com>"]
edition = "2018"
license = "GPL-3.0"
description = "BabyJubJub elliptic curve implementation"
repository = "https://github.com/arnaucube/babyjubjub-rs"
readme = "README.md"
[dependencies]
num = "0.2.0"
@ -15,6 +17,7 @@ blake2 = "0.8"
generic-array = "0.13.2"
tiny-keccak = "1.5"
rustc-hex = "1.0.0"
mimc-rs = "0.0.1"
mimc-rs = "0.0.2"
poseidon-rs = "0.0.1"
arrayref = "0.3.5"
lazy_static = "1.4.0"

+ 5
- 4
README.md

@ -1,12 +1,13 @@
# babyjubjub-rs [![Crates.io](https://img.shields.io/crates/v/babyjubjub-rs.svg)](https://crates.io/crates/babyjubjub-rs) [![Build Status](https://travis-ci.org/arnaucube/babyjubjub-rs.svg?branch=master)](https://travis-ci.org/arnaucube/babyjubjub-rs)
BabyJubJub elliptic curve implementation in Rust.
BabyJubJub is a twisted edwards curve embedded in the curve of BN128.
BabyJubJub elliptic curve implementation in Rust. Is a twisted edwards curve embedded in the curve of BN128.
BabyJubJub curve explanation: https://medium.com/zokrates/efficient-ecc-in-zksnarks-using-zokrates-bd9ae37b8186
Uses:
- MiMC7 hash function: https://github.com/arnaucube/mimc-rs
- Poseidon hash function https://github.com/arnaucube/poseidon-rs
Compatible with the BabyJubJub Go implementation from https://github.com/iden3/go-iden3-crypto
## Warning
Doing this in my free time to get familiar with Rust, do not use in production.
@ -16,7 +17,7 @@ Doing this in my free time to get familiar with Rust, do not use in production.
- [x] eddsa keys generation
- [x] eddsa signature
- [x] eddsa signature verification
- [ ] {point, pk, signature} compress&decompress parsers
- [x] {point, pk, signature} compress&decompress parsers

+ 106
- 28
src/lib.rs

@ -9,6 +9,7 @@ extern crate rand;
use blake2::{Blake2b, Digest};
use mimc_rs::Mimc7;
use poseidon_rs::Poseidon;
use std::cmp::min;
use num_bigint::{BigInt, RandBigInt, Sign, ToBigInt};
@ -196,7 +197,7 @@ impl PrivateKey {
pk.clone()
}
pub fn sign(&self, msg: BigInt) -> Signature {
pub fn sign_mimc(&self, msg: BigInt) -> Result<Signature, String> {
// https://tools.ietf.org/html/rfc8032#section-5.1.6
let mut hasher = Blake2b::new();
let (_, sk_bytes) = self.key.to_bytes_be();
@ -213,17 +214,52 @@ impl PrivateKey {
let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg];
let mimc7 = Mimc7::new();
let hm = mimc7.hash(hm_input);
let hm = match mimc7.hash(hm_input) {
Result::Err(err) => return Err(err.to_string()),
Result::Ok(hm) => hm,
};
let mut s = &self.key << 3;
s = hm * s;
s = r + s;
s = s % &SUBORDER.clone();
Signature {
Ok(Signature {
r_b8: r8.clone(),
s: s,
}
})
}
pub fn sign_poseidon(&self, msg: BigInt) -> Result<Signature, String> {
// https://tools.ietf.org/html/rfc8032#section-5.1.6
let mut hasher = Blake2b::new();
let (_, sk_bytes) = self.key.to_bytes_be();
hasher.input(sk_bytes);
let mut h = hasher.result(); // h: hash(sk)
// s: h[32:64]
let s = GenericArray::<u8, generic_array::typenum::U32>::from_mut_slice(&mut h[32..64]);
let (_, msg_bytes) = msg.to_bytes_be();
let r_bytes = utils::concatenate_arrays(s, &msg_bytes);
let mut r = BigInt::from_bytes_be(Sign::Plus, &r_bytes[..]);
r = utils::modulus(&r, &SUBORDER);
let r8: Point = B8.mul_scalar(r.clone());
let a = &self.public();
let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg];
let poseidon = Poseidon::new();
let hm = match poseidon.hash(hm_input) {
Result::Err(err) => return Err(err.to_string()),
Result::Ok(hm) => hm,
};
let mut s = &self.key << 3;
s = hm * s;
s = r + s;
s = s % &SUBORDER.clone();
Ok(Signature {
r_b8: r8.clone(),
s: s,
})
}
}
@ -246,7 +282,7 @@ pub fn new_key() -> PrivateKey {
PrivateKey { key: sk }
}
pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
pub fn verify_mimc(pk: Point, sig: Signature, msg: BigInt) -> bool {
let hm_input = vec![
sig.r_b8.x.clone(),
sig.r_b8.y.clone(),
@ -255,7 +291,30 @@ pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
msg,
];
let mimc7 = Mimc7::new();
let hm = mimc7.hash(hm_input);
let hm = match mimc7.hash(hm_input) {
Result::Err(_) => return false,
Result::Ok(hm) => hm,
};
let l = B8.mul_scalar(sig.s);
let r = sig.r_b8.add(&pk.mul_scalar(8.to_bigint().unwrap() * hm));
if l.x == r.x && l.y == r.y {
return true;
}
false
}
pub fn verify_poseidon(pk: Point, sig: Signature, msg: BigInt) -> bool {
let hm_input = vec![
sig.r_b8.x.clone(),
sig.r_b8.y.clone(),
pk.x.clone(),
pk.y.clone(),
msg,
];
let poseidon = Poseidon::new();
let hm = match poseidon.hash(hm_input) {
Result::Err(_) => return false,
Result::Ok(hm) => hm,
};
let l = B8.mul_scalar(sig.s);
let r = sig.r_b8.add(&pk.mul_scalar(8.to_bigint().unwrap() * hm));
if l.x == r.x && l.y == r.y {
@ -386,6 +445,45 @@ mod tests {
);
}
#[test]
fn test_new_key_sign_verify_mimc_0() {
let sk = new_key();
let pk = sk.public();
let msg = 5.to_bigint().unwrap();
let sig = sk.sign_mimc(msg.clone()).unwrap();
let v = verify_mimc(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_new_key_sign_verify_mimc_1() {
let sk = new_key();
let pk = sk.public();
let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
let sig = sk.sign_mimc(msg.clone()).unwrap();
let v = verify_mimc(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_new_key_sign_verify_poseidon_0() {
let sk = new_key();
let pk = sk.public();
let msg = 5.to_bigint().unwrap();
let sig = sk.sign_poseidon(msg.clone()).unwrap();
let v = verify_poseidon(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_new_key_sign_verify_poseidon_1() {
let sk = new_key();
let pk = sk.public();
let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
let sig = sk.sign_poseidon(msg.clone()).unwrap();
let v = verify_poseidon(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_point_compress_decompress() {
let p: Point = Point {
@ -410,26 +508,6 @@ mod tests {
assert_eq!(p.y, p2.y);
}
#[test]
fn test_new_key_sign_verify0() {
let sk = new_key();
let pk = sk.public();
let msg = 5.to_bigint().unwrap();
let sig = sk.sign(msg.clone());
let v = verify(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_new_key_sign_verify1() {
let sk = new_key();
let pk = sk.public();
let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
let sig = sk.sign(msg.clone());
let v = verify(pk, sig, msg);
assert_eq!(v, true);
}
#[test]
fn test_point_decompress0() {
let y_bytes_raw = "b5328f8791d48f20bec6e481d91c7ada235f1facf22547901c18656b6c3e042f"
@ -498,7 +576,7 @@ mod tests {
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 sig = sk.sign_mimc(msg.clone()).unwrap();
let compressed_sig = sig.compress();
let decompressed_sig = decompress_signature(&compressed_sig).unwrap();
@ -506,7 +584,7 @@ mod tests {
assert_eq!(&sig.r_b8.y, &decompressed_sig.r_b8.y);
assert_eq!(&sig.s, &decompressed_sig.s);
let v = verify(pk.clone(), decompressed_sig, msg);
let v = verify_mimc(pk.clone(), decompressed_sig, msg);
assert_eq!(v, true);
}
}

Loading…
Cancel
Save