mirror of
https://github.com/arnaucube/babyjubjub-ark.git
synced 2026-01-13 09:11:28 +01:00
add sign & verify with Poseidon hash, update MiMC use to v0.0.2
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# babyjubjub-rs [](https://crates.io/crates/babyjubjub-rs) [](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
|
||||
|
||||
|
||||
|
||||
|
||||
134
src/lib.rs
134
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user