Browse Source

Update clippy minor fixes, add clippy to GHA

main
arnaucube 3 years ago
parent
commit
e4b7ced755
3 changed files with 74 additions and 81 deletions
  1. +11
    -0
      .github/workflows/clippy.yml
  2. +44
    -59
      src/lib.rs
  3. +19
    -22
      src/utils.rs

+ 11
- 0
.github/workflows/clippy.yml

@ -0,0 +1,11 @@
name: Clippy check
on: [push, pull_request]
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: rustup component add clippy
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

+ 44
- 59
src/lib.rs

@ -1,8 +1,8 @@
// BabyJubJub elliptic curve implementation in Rust.
// For LICENSE check https://github.com/arnaucube/babyjubjub-rs // For LICENSE check https://github.com/arnaucube/babyjubjub-rs
extern crate rand;
#[macro_use]
extern crate ff; extern crate ff;
extern crate rand;
use ff::*; use ff::*;
use poseidon_rs::Poseidon; use poseidon_rs::Poseidon;
@ -16,14 +16,12 @@ extern crate num_bigint;
extern crate num_traits; extern crate num_traits;
extern crate rand6; extern crate rand6;
use rand6::Rng;
// use blake2::{Blake2b, Digest}; // use blake2::{Blake2b, Digest};
#[cfg(feature = "default")] #[cfg(feature = "default")]
extern crate blake_hash; // compatible version with Blake used at circomlib extern crate blake_hash; // compatible version with Blake used at circomlib
#[cfg(feature = "default")] #[cfg(feature = "default")]
#[macro_use]
use blake_hash::Digest; use blake_hash::Digest;
#[cfg(feature = "aarch64")] #[cfg(feature = "aarch64")]
@ -43,9 +41,9 @@ extern crate lazy_static;
lazy_static! { lazy_static! {
static ref D: Fr = Fr::from_str("168696").unwrap(); static ref D: Fr = Fr::from_str("168696").unwrap();
static ref D_big: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
static ref D_BIG: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
static ref A: Fr = Fr::from_str("168700").unwrap(); static ref A: Fr = Fr::from_str("168700").unwrap();
static ref A_big: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
static ref A_BIG: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
pub static ref Q: BigInt = BigInt::parse_bytes( pub static ref Q: BigInt = BigInt::parse_bytes(
b"21888242871839275222246405745257275088548364400416034343698204186575808495617",10 b"21888242871839275222246405745257275088548364400416034343698204186575808495617",10
) )
@ -72,7 +70,7 @@ lazy_static! {
) )
.unwrap() .unwrap()
>> 3; >> 3;
static ref poseidon: poseidon_rs::Poseidon = Poseidon::new();
static ref POSEIDON: poseidon_rs::Poseidon = Poseidon::new();
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -97,11 +95,10 @@ impl PointProjective {
let mut y = self.y; let mut y = self.y;
y.mul_assign(&zinv); y.mul_assign(&zinv);
Point {
x: x.clone(),
y: y.clone(),
}
Point { x, y }
} }
#[allow(clippy::many_single_char_names)]
pub fn add(&self, q: &PointProjective) -> PointProjective { pub fn add(&self, q: &PointProjective) -> PointProjective {
// add-2008-bbjlp https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp // add-2008-bbjlp https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
let mut a = self.z; let mut a = self.z;
@ -112,7 +109,7 @@ impl PointProjective {
c.mul_assign(&q.x); c.mul_assign(&q.x);
let mut d = self.y; let mut d = self.y;
d.mul_assign(&q.y); d.mul_assign(&q.y);
let mut e = D.clone();
let mut e = *D;
e.mul_assign(&c); e.mul_assign(&c);
e.mul_assign(&d); e.mul_assign(&d);
let mut f = b; let mut f = b;
@ -130,7 +127,7 @@ impl PointProjective {
let mut x3 = a; let mut x3 = a;
x3.mul_assign(&f); x3.mul_assign(&f);
x3.mul_assign(&aux); x3.mul_assign(&aux);
let mut ac = A.clone();
let mut ac = *A;
ac.mul_assign(&c); ac.mul_assign(&c);
let mut dac = d; let mut dac = d;
dac.sub_assign(&ac); dac.sub_assign(&ac);
@ -141,9 +138,9 @@ impl PointProjective {
z3.mul_assign(&g); z3.mul_assign(&g);
PointProjective { PointProjective {
x: x3.clone(),
y: y3.clone(),
z: z3.clone(),
x: x3,
y: y3,
z: z3,
} }
} }
} }
@ -157,8 +154,8 @@ pub struct Point {
impl Point { impl Point {
pub fn projective(&self) -> PointProjective { pub fn projective(&self) -> PointProjective {
PointProjective { PointProjective {
x: self.x.clone(),
y: self.y.clone(),
x: self.x,
y: self.y,
z: Fr::one(), z: Fr::one(),
} }
} }
@ -188,8 +185,8 @@ impl Point {
let (_, y_bytes) = y_big.to_bytes_le(); let (_, y_bytes) = y_big.to_bytes_le();
let len = min(y_bytes.len(), r.len()); let len = min(y_bytes.len(), r.len());
r[..len].copy_from_slice(&y_bytes[..len]); r[..len].copy_from_slice(&y_bytes[..len]);
if &x_big > &(&Q.clone() >> 1) {
r[31] = r[31] | 0x80;
if x_big > (&Q.clone() >> 1) {
r[31] |= 0x80;
} }
r r
} }
@ -202,17 +199,17 @@ impl Point {
} }
} }
pub fn test_bit(b: &Vec<u8>, i: usize) -> bool {
return b[i / 8] & (1 << (i % 8)) != 0;
pub fn test_bit(b: &[u8], i: usize) -> bool {
b[i / 8] & (1 << (i % 8)) != 0
} }
pub fn decompress_point(bb: [u8; 32]) -> Result<Point, String> { pub fn decompress_point(bb: [u8; 32]) -> Result<Point, String> {
// https://tools.ietf.org/html/rfc8032#section-5.2.3 // https://tools.ietf.org/html/rfc8032#section-5.2.3
let mut sign: bool = false; let mut sign: bool = false;
let mut b = bb.clone();
let mut b = bb;
if b[31] & 0x80 != 0x00 { if b[31] & 0x80 != 0x00 {
sign = true; sign = true;
b[31] = b[31] & 0x7F;
b[31] &= 0x7F;
} }
let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]); let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]);
if y >= Q.clone() { if y >= Q.clone() {
@ -223,7 +220,7 @@ pub fn decompress_point(bb: [u8; 32]) -> Result {
// x^2 = (1 - y^2) / (a - d * y^2) (mod p) // x^2 = (1 - y^2) / (a - d * y^2) (mod p)
let den = utils::modinv( let den = utils::modinv(
&utils::modulus( &utils::modulus(
&(&A_big.clone() - utils::modulus(&(&D_big.clone() * (&y * &y)), &Q)),
&(&A_BIG.clone() - utils::modulus(&(&D_BIG.clone() * (&y * &y)), &Q)),
&Q, &Q,
), ),
&Q, &Q,
@ -231,8 +228,8 @@ pub fn decompress_point(bb: [u8; 32]) -> Result {
let mut x: BigInt = utils::modulus(&((one - utils::modulus(&(&y * &y), &Q)) * den), &Q); let mut x: BigInt = utils::modulus(&((one - utils::modulus(&(&y * &y), &Q)) * den), &Q);
x = utils::modsqrt(&x, &Q)?; x = utils::modsqrt(&x, &Q)?;
if sign && !(&x > &(&Q.clone() >> 1)) || (!sign && (&x > &(&Q.clone() >> 1))) {
x = x * -1.to_bigint().unwrap();
if sign && (x <= (&Q.clone() >> 1)) || (!sign && (x > (&Q.clone() >> 1))) {
x *= -(1.to_bigint().unwrap());
} }
x = utils::modulus(&x, &Q); x = utils::modulus(&x, &Q);
let x_fr: Fr = Fr::from_str(&x.to_string()).unwrap(); let x_fr: Fr = Fr::from_str(&x.to_string()).unwrap();
@ -241,7 +238,7 @@ pub fn decompress_point(bb: [u8; 32]) -> Result {
} }
#[cfg(feature = "default")] #[cfg(feature = "default")]
fn blh(b: &Vec<u8>) -> Vec<u8> {
fn blh(b: &[u8]) -> Vec<u8> {
let hash = blake_hash::Blake512::digest(&b); let hash = blake_hash::Blake512::digest(&b);
hash.to_vec() hash.to_vec()
} }
@ -279,11 +276,8 @@ pub fn decompress_signature(b: &[u8; 64]) -> Result {
let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]); let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]);
let r_b8 = decompress_point(r_b8_bytes); let r_b8 = decompress_point(r_b8_bytes);
match r_b8 { match r_b8 {
Result::Err(err) => return Err(err.to_string()),
Result::Ok(res) => Ok(Signature {
r_b8: res.clone(),
s: s,
}),
Result::Err(err) => Err(err),
Result::Ok(res) => Ok(Signature { r_b8: res, s }),
} }
} }
@ -308,21 +302,19 @@ impl PrivateKey {
// let mut h = hasher.finalize(); // let mut h = hasher.finalize();
// compatible with circomlib implementation // compatible with circomlib implementation
let mut hash: Vec<u8> = blh(&self.key.to_vec());
let hash: Vec<u8> = blh(&self.key.to_vec());
let mut h: Vec<u8> = hash[..32].to_vec(); let mut h: Vec<u8> = hash[..32].to_vec();
h[0] = h[0] & 0xF8;
h[31] = h[31] & 0x7F;
h[31] = h[31] | 0x40;
h[0] &= 0xF8;
h[31] &= 0x7F;
h[31] |= 0x40;
let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]); let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
sk >> 3 sk >> 3
} }
pub fn public(&self) -> Point { pub fn public(&self) -> Point {
// https://tools.ietf.org/html/rfc8032#section-5.1.5
let pk = B8.mul_scalar(&self.scalar_key());
pk.clone()
B8.mul_scalar(&self.scalar_key())
} }
pub fn sign(&self, msg: BigInt) -> Result<Signature, String> { pub fn sign(&self, msg: BigInt) -> Result<Signature, String> {
@ -346,24 +338,22 @@ impl PrivateKey {
let r_hashed: Vec<u8> = blh(&r_bytes); let r_hashed: Vec<u8> = blh(&r_bytes);
let mut r = BigInt::from_bytes_le(Sign::Plus, &r_hashed[..]); let mut r = BigInt::from_bytes_le(Sign::Plus, &r_hashed[..]);
r = utils::modulus(&r, &SUBORDER); r = utils::modulus(&r, &SUBORDER);
let r8: Point = B8.mul_scalar(&r);
let r_b8: Point = B8.mul_scalar(&r);
let a = &self.public(); let a = &self.public();
let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msg_fr];
let hm = poseidon.hash(hm_input)?;
let hm_input = vec![r_b8.x, r_b8.y, a.x, a.y, msg_fr];
let hm = POSEIDON.hash(hm_input)?;
let mut s = &self.scalar_key() << 3; let mut s = &self.scalar_key() << 3;
let hm_b = BigInt::parse_bytes(to_hex(&hm).as_bytes(), 16).unwrap(); let hm_b = BigInt::parse_bytes(to_hex(&hm).as_bytes(), 16).unwrap();
s = hm_b * s; s = hm_b * s;
s = r + s; s = r + s;
s = s % &SUBORDER.clone();
s %= &SUBORDER.clone();
Ok(Signature {
r_b8: r8.clone(),
s: s,
})
Ok(Signature { r_b8, s })
} }
#[allow(clippy::many_single_char_names)]
pub fn sign_schnorr(&self, m: BigInt) -> Result<(Point, BigInt), String> { pub fn sign_schnorr(&self, m: BigInt) -> Result<(Point, BigInt), String> {
// random r // random r
let mut rng = rand6::thread_rng(); let mut rng = rand6::thread_rng();
@ -388,8 +378,8 @@ pub fn schnorr_hash(pk: &Point, msg: BigInt, c: &Point) -> Result
return Err("msg outside the Finite Field".to_string()); return Err("msg outside the Finite Field".to_string());
} }
let msg_fr: Fr = Fr::from_str(&msg.to_string()).unwrap(); let msg_fr: Fr = Fr::from_str(&msg.to_string()).unwrap();
let hm_input = vec![pk.x.clone(), pk.y.clone(), c.x.clone(), c.y.clone(), msg_fr];
let h = poseidon.hash(hm_input)?;
let hm_input = vec![pk.x, pk.y, c.x, c.y, msg_fr];
let h = POSEIDON.hash(hm_input)?;
let h_b = BigInt::parse_bytes(to_hex(&h).as_bytes(), 16).unwrap(); let h_b = BigInt::parse_bytes(to_hex(&h).as_bytes(), 16).unwrap();
Ok(h_b) Ok(h_b)
} }
@ -419,14 +409,8 @@ pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
return false; return false;
} }
let msg_fr: Fr = Fr::from_str(&msg.to_string()).unwrap(); let msg_fr: Fr = Fr::from_str(&msg.to_string()).unwrap();
let hm_input = vec![
sig.r_b8.x.clone(),
sig.r_b8.y.clone(),
pk.x.clone(),
pk.y.clone(),
msg_fr,
];
let hm = match poseidon.hash(hm_input) {
let hm_input = vec![sig.r_b8.x, sig.r_b8.y, pk.x, pk.y, msg_fr];
let hm = match POSEIDON.hash(hm_input) {
Result::Err(_) => return false, Result::Err(_) => return false,
Result::Ok(hm) => hm, Result::Ok(hm) => hm,
}; };
@ -443,6 +427,7 @@ pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
mod tests { mod tests {
use super::*; use super::*;
extern crate rustc_hex; extern crate rustc_hex;
use rand6::Rng;
use rustc_hex::{FromHex, ToHex}; use rustc_hex::{FromHex, ToHex};
#[test] #[test]
@ -720,7 +705,7 @@ mod tests {
.unwrap(); .unwrap();
// test blake compatible with circomlib implementation // test blake compatible with circomlib implementation
let mut h: Vec<u8> = blh(&sk_raw_bytes);
let h: Vec<u8> = blh(&sk_raw_bytes);
assert_eq!(h.to_hex(), "c992db23d6290c70ffcc02f7abeb00b9d00fa8b43e55d7949c28ba6be7545d3253882a61bd004a236ef1cdba01b27ba0aedfb08eefdbfb7c19657c880b43ddf1"); assert_eq!(h.to_hex(), "c992db23d6290c70ffcc02f7abeb00b9d00fa8b43e55d7949c28ba6be7545d3253882a61bd004a236ef1cdba01b27ba0aedfb08eefdbfb7c19657c880b43ddf1");
// test private key // test private key

+ 19
- 22
src/utils.rs

@ -1,3 +1,6 @@
// BabyJubJub elliptic curve implementation in Rust.
// For LICENSE check https://github.com/arnaucube/babyjubjub-rs
extern crate num; extern crate num;
extern crate num_bigint; extern crate num_bigint;
extern crate num_traits; extern crate num_traits;
@ -106,6 +109,7 @@ pub fn concatenate_arrays(x: &[T], y: &[T]) -> Vec {
x.iter().chain(y).cloned().collect() x.iter().chain(y).cloned().collect()
} }
#[allow(clippy::many_single_char_names)]
pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result<BigInt, String> { pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result<BigInt, String> {
// Tonelli-Shanks Algorithm (https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) // Tonelli-Shanks Algorithm (https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm)
// //
@ -115,11 +119,7 @@ pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result {
let zero: BigInt = Zero::zero(); let zero: BigInt = Zero::zero();
let one: BigInt = One::one(); let one: BigInt = One::one();
if legendre_symbol(&a, q) != 1 {
return Err("not a mod p square".to_string());
} else if a == &zero {
return Err("not a mod p square".to_string());
} else if q == &2.to_bigint().unwrap() {
if legendre_symbol(&a, q) != 1 || a == &zero || q == &2.to_bigint().unwrap() {
return Err("not a mod p square".to_string()); return Err("not a mod p square".to_string());
} else if q % 4.to_bigint().unwrap() == 3.to_bigint().unwrap() { } else if q % 4.to_bigint().unwrap() == 3.to_bigint().unwrap() {
let r = a.modpow(&((q + one) / 4), &q); let r = a.modpow(&((q + one) / 4), &q);
@ -129,8 +129,8 @@ pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result {
let mut s = q - &one; let mut s = q - &one;
let mut e: BigInt = Zero::zero(); let mut e: BigInt = Zero::zero();
while &s % 2 == zero { while &s % 2 == zero {
s = s >> 1;
e = e + &one;
s >>= 1;
e += &one;
} }
let mut n: BigInt = 2.to_bigint().unwrap(); let mut n: BigInt = 2.to_bigint().unwrap();
@ -146,13 +146,13 @@ pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result {
loop { loop {
let mut t = b.clone(); let mut t = b.clone();
let mut m: BigInt = Zero::zero(); let mut m: BigInt = Zero::zero();
while &t != &one {
while t != one {
t = modulus(&(&t * &t), q); t = modulus(&(&t * &t), q);
m = m + &one;
m += &one;
} }
if m == zero { if m == zero {
return Ok(y.clone());
return Ok(y);
} }
t = g.modpow(&(2.to_bigint().unwrap().modpow(&(&r - &m - 1), q)), q); t = g.modpow(&(2.to_bigint().unwrap().modpow(&(&r - &m - 1), q)), q);
@ -164,6 +164,7 @@ pub fn modsqrt(a: &BigInt, q: &BigInt) -> Result {
} }
#[allow(dead_code)] #[allow(dead_code)]
#[allow(clippy::many_single_char_names)]
pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result<BigInt, String> { pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result<BigInt, String> {
// Tonelli-Shanks Algorithm (https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) // Tonelli-Shanks Algorithm (https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm)
// //
@ -171,11 +172,7 @@ pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result {
let zero: BigInt = Zero::zero(); let zero: BigInt = Zero::zero();
let one: BigInt = One::one(); let one: BigInt = One::one();
if legendre_symbol(&a, q) != 1 {
return Err("not a mod p square".to_string());
} else if a == &zero {
return Err("not a mod p square".to_string());
} else if q == &2.to_bigint().unwrap() {
if legendre_symbol(&a, q) != 1 || a == &zero || q == &2.to_bigint().unwrap() {
return Err("not a mod p square".to_string()); return Err("not a mod p square".to_string());
} else if q % 4.to_bigint().unwrap() == 3.to_bigint().unwrap() { } else if q % 4.to_bigint().unwrap() == 3.to_bigint().unwrap() {
let r = a.modpow(&((q + one) / 4), &q); let r = a.modpow(&((q + one) / 4), &q);
@ -185,8 +182,8 @@ pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result {
let mut p = q - &one; let mut p = q - &one;
let mut s: BigInt = Zero::zero(); let mut s: BigInt = Zero::zero();
while &p % 2.to_bigint().unwrap() == zero { while &p % 2.to_bigint().unwrap() == zero {
s = s + &one;
p = p >> 1;
s += &one;
p >>= 1;
} }
let mut z: BigInt = One::one(); let mut z: BigInt = One::one();
@ -199,15 +196,15 @@ pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result {
let mut t = a.modpow(&p, q); let mut t = a.modpow(&p, q);
let mut m = s; let mut m = s;
while &t != &one {
while t != one {
let mut i: BigInt = One::one(); let mut i: BigInt = One::one();
let mut e: BigInt = 2.to_bigint().unwrap(); let mut e: BigInt = 2.to_bigint().unwrap();
while i < m { while i < m {
if t.modpow(&e, q) == one { if t.modpow(&e, q) == one {
break; break;
} }
e = e * 2.to_bigint().unwrap();
i = i + &one;
e *= 2.to_bigint().unwrap();
i += &one;
} }
let b = c.modpow(&(2.to_bigint().unwrap().modpow(&(&m - &i - 1), q)), q); let b = c.modpow(&(2.to_bigint().unwrap().modpow(&(&m - &i - 1), q)), q);
@ -216,14 +213,14 @@ pub fn modsqrt_v2(a: &BigInt, q: &BigInt) -> Result {
c = modulus(&(&b * &b), q); c = modulus(&(&b * &b), q);
m = i.clone(); m = i.clone();
} }
return Ok(x);
Ok(x)
} }
pub fn legendre_symbol(a: &BigInt, q: &BigInt) -> i32 { pub fn legendre_symbol(a: &BigInt, q: &BigInt) -> i32 {
// returns 1 if has a square root modulo q // returns 1 if has a square root modulo q
let one: BigInt = One::one(); let one: BigInt = One::one();
let ls: BigInt = a.modpow(&((q - &one) >> 1), &q); let ls: BigInt = a.modpow(&((q - &one) >> 1), &q);
if &(ls) == &(q - one) {
if ls == q - one {
return -1; return -1;
} }
1 1

Loading…
Cancel
Save