blob: bcf11b208a9e3beb214736049c4152e5c3d79c47 [file] [log] [blame]
//! Equivalence tests between `num-bigint` and `crypto-bigint`
use crypto_bigint::{Encoding, U256};
use num_bigint::BigUint;
use num_traits::identities::Zero;
use proptest::prelude::*;
use std::mem;
/// Example prime number (NIST P-256 curve order)
const P: U256 =
U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
fn to_biguint(uint: &U256) -> BigUint {
BigUint::from_bytes_le(uint.to_le_bytes().as_ref())
}
fn to_uint(big_uint: BigUint) -> U256 {
let mut input = [0u8; U256::BYTE_SIZE];
let encoded = big_uint.to_bytes_le();
let l = encoded.len().min(U256::BYTE_SIZE);
input[..l].copy_from_slice(&encoded[..l]);
U256::from_le_slice(&input)
}
prop_compose! {
fn uint()(bytes in any::<[u8; 32]>()) -> U256 {
U256::from_le_slice(&bytes)
}
}
prop_compose! {
fn uint_mod_p(p: U256)(a in uint()) -> U256 {
a.wrapping_rem(&p)
}
}
proptest! {
#[test]
fn roundtrip(a in uint()) {
assert_eq!(a, to_uint(to_biguint(&a)));
}
#[test]
fn wrapping_add(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
let expected = to_uint(a_bi + b_bi);
let actual = a.wrapping_add(&b);
assert_eq!(expected, actual);
}
#[test]
fn add_mod_nist_p256(a in uint_mod_p(P), b in uint_mod_p(P)) {
assert!(a < P);
assert!(b < P);
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
let p_bi = to_biguint(&P);
let expected = to_uint((a_bi + b_bi) % p_bi);
let actual = a.add_mod(&b, &P);
assert!(expected < P);
assert!(actual < P);
assert_eq!(expected, actual);
}
#[test]
fn sub_mod_nist_p256(mut a in uint_mod_p(P), mut b in uint_mod_p(P)) {
if b > a {
mem::swap(&mut a, &mut b);
}
assert!(a < P);
assert!(b < P);
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
let p_bi = to_biguint(&P);
let expected = to_uint((a_bi - b_bi) % p_bi);
let actual = a.sub_mod(&b, &P);
assert!(expected < P);
assert!(actual < P);
assert_eq!(expected, actual);
}
#[test]
fn wrapping_sub(mut a in uint(), mut b in uint()) {
if b > a {
mem::swap(&mut a, &mut b);
}
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
let expected = to_uint(a_bi - b_bi);
let actual = a.wrapping_sub(&b);
assert_eq!(expected, actual);
}
#[test]
fn wrapping_mul(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
let expected = to_uint(a_bi * b_bi);
let actual = a.wrapping_mul(&b);
assert_eq!(expected, actual);
}
#[test]
fn wrapping_div(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
if !b_bi.is_zero() {
let expected = to_uint(a_bi / b_bi);
let actual = a.wrapping_div(&b);
assert_eq!(expected, actual);
}
}
#[test]
fn wrapping_rem(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
if b_bi.is_zero() {
let expected = to_uint(a_bi % b_bi);
let actual = a.wrapping_rem(&b);
assert_eq!(expected, actual);
}
}
#[test]
fn wrapping_sqrt(a in uint()) {
let a_bi = to_biguint(&a);
let expected = to_uint(a_bi.sqrt());
let actual = a.wrapping_sqrt();
assert_eq!(expected, actual);
}
#[test]
fn wrapping_or(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
if !b_bi.is_zero() {
let expected = to_uint(a_bi | b_bi);
let actual = a.wrapping_or(&b);
assert_eq!(expected, actual);
}
}
#[test]
fn wrapping_and(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
if !b_bi.is_zero() {
let expected = to_uint(a_bi & b_bi);
let actual = a.wrapping_and(&b);
assert_eq!(expected, actual);
}
}
#[test]
fn wrapping_xor(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);
if !b_bi.is_zero() {
let expected = to_uint(a_bi ^ b_bi);
let actual = a.wrapping_xor(&b);
assert_eq!(expected, actual);
}
}
}