mirror of
https://github.com/arnaucube/babyjubjub-ark.git
synced 2026-01-13 17:21:29 +01:00
Update clippy minor fixes, add clippy to GHA
This commit is contained in:
11
.github/workflows/clippy.yml
vendored
Normal file
11
.github/workflows/clippy.yml
vendored
Normal file
@@ -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 }}
|
||||||
103
src/lib.rs
103
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 {
|
Point { x, y }
|
||||||
x: x.clone(),
|
|
||||||
y: y.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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(),
|
x: x3,
|
||||||
y: y3.clone(),
|
y: y3,
|
||||||
z: z3.clone(),
|
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(),
|
x: self.x,
|
||||||
y: self.y.clone(),
|
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) {
|
if x_big > (&Q.clone() >> 1) {
|
||||||
r[31] = r[31] | 0x80;
|
r[31] |= 0x80;
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
@@ -202,17 +199,17 @@ impl Point {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_bit(b: &Vec<u8>, i: usize) -> bool {
|
pub fn test_bit(b: &[u8], i: usize) -> bool {
|
||||||
return b[i / 8] & (1 << (i % 8)) != 0;
|
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<Point, String> {
|
|||||||
// 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<Point, String> {
|
|||||||
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))) {
|
if sign && (x <= (&Q.clone() >> 1)) || (!sign && (x > (&Q.clone() >> 1))) {
|
||||||
x = x * -1.to_bigint().unwrap();
|
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<Point, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[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<Signature, String> {
|
|||||||
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::Err(err) => Err(err),
|
||||||
Result::Ok(res) => Ok(Signature {
|
Result::Ok(res) => Ok(Signature { r_b8: res, s }),
|
||||||
r_b8: res.clone(),
|
|
||||||
s: 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[0] &= 0xF8;
|
||||||
h[31] = h[31] & 0x7F;
|
h[31] &= 0x7F;
|
||||||
h[31] = h[31] | 0x40;
|
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
|
B8.mul_scalar(&self.scalar_key())
|
||||||
let pk = B8.mul_scalar(&self.scalar_key());
|
|
||||||
pk.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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_input = vec![r_b8.x, r_b8.y, a.x, a.y, msg_fr];
|
||||||
let hm = poseidon.hash(hm_input)?;
|
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 {
|
Ok(Signature { r_b8, s })
|
||||||
r_b8: r8.clone(),
|
|
||||||
s: 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<BigInt, String
|
|||||||
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 hm_input = vec![pk.x, pk.y, c.x, c.y, msg_fr];
|
||||||
let h = poseidon.hash(hm_input)?;
|
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![
|
let hm_input = vec![sig.r_b8.x, sig.r_b8.y, pk.x, pk.y, msg_fr];
|
||||||
sig.r_b8.x.clone(),
|
let hm = match POSEIDON.hash(hm_input) {
|
||||||
sig.r_b8.y.clone(),
|
|
||||||
pk.x.clone(),
|
|
||||||
pk.y.clone(),
|
|
||||||
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
|
||||||
|
|||||||
41
src/utils.rs
41
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<T: Clone>(x: &[T], y: &[T]) -> Vec<T> {
|
|||||||
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<BigInt, String> {
|
|||||||
|
|
||||||
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 {
|
if legendre_symbol(&a, q) != 1 || a == &zero || q == &2.to_bigint().unwrap() {
|
||||||
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() {
|
|
||||||
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<BigInt, String> {
|
|||||||
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;
|
s >>= 1;
|
||||||
e = e + &one;
|
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<BigInt, String> {
|
|||||||
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<BigInt, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[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<BigInt, String> {
|
|||||||
|
|
||||||
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 {
|
if legendre_symbol(&a, q) != 1 || a == &zero || q == &2.to_bigint().unwrap() {
|
||||||
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() {
|
|
||||||
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<BigInt, String> {
|
|||||||
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;
|
s += &one;
|
||||||
p = p >> 1;
|
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<BigInt, String> {
|
|||||||
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();
|
e *= 2.to_bigint().unwrap();
|
||||||
i = i + &one;
|
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<BigInt, String> {
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user