Remove the cryptonum stuff; it's been moved to a different crate.
This commit is contained in:
@@ -1,133 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::ops::Add;
|
|
||||||
|
|
||||||
pub trait UnsafeAdd {
|
|
||||||
fn unsafe_add(self, other: &Self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_adders
|
|
||||||
{
|
|
||||||
($name: ident, $size: expr) => {
|
|
||||||
impl UnsafeAdd for $name {
|
|
||||||
fn unsafe_add(self, other: &$name) -> $name {
|
|
||||||
let mut result = $name::zero();
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
for i in 0..$size/64 {
|
|
||||||
let x128 = self.values[i] as u128;
|
|
||||||
let y128 = other.values[i] as u128;
|
|
||||||
let bigger = x128 + y128 + carry;
|
|
||||||
carry = bigger >> 64;
|
|
||||||
result.values[i] = bigger as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
($name: ident, $bigger: ident, $size: expr) => {
|
|
||||||
generate_adders!($name, $size);
|
|
||||||
|
|
||||||
impl<'a,'b> Add<&'a $name> for &'b $name {
|
|
||||||
type Output = $bigger;
|
|
||||||
|
|
||||||
fn add(self, other: &$name) -> $bigger {
|
|
||||||
let mut result = $bigger::zero();
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
for i in 0..$size/64 {
|
|
||||||
let x128 = self.values[i] as u128;
|
|
||||||
let y128 = other.values[i] as u128;
|
|
||||||
let bigger = x128 + y128 + carry;
|
|
||||||
carry = bigger >> 64;
|
|
||||||
result.values[i] = bigger as u64;
|
|
||||||
}
|
|
||||||
result.values[$size/64] = carry as u64;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add<$name> for $name {
|
|
||||||
type Output = $bigger;
|
|
||||||
|
|
||||||
fn add(self, other: $name) -> $bigger {
|
|
||||||
&self + &other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_adders!(U192, U256, 192);
|
|
||||||
generate_adders!(U256, U320, 256);
|
|
||||||
generate_adders!(U384, U448, 384);
|
|
||||||
generate_adders!(U512, U576, 512);
|
|
||||||
generate_adders!(U576, U640, 576);
|
|
||||||
generate_adders!(U1024, U1088, 1024);
|
|
||||||
generate_adders!(U2048, U2112, 2048);
|
|
||||||
generate_adders!(U3072, U3136, 3072);
|
|
||||||
generate_adders!(U4096, U4160, 4096);
|
|
||||||
generate_adders!(U7680, U7744, 7680);
|
|
||||||
generate_adders!(U8192, U8256, 8192);
|
|
||||||
generate_adders!(U15360, U15424, 15360);
|
|
||||||
|
|
||||||
generate_adders!(U320, 320);
|
|
||||||
generate_adders!(U448, 448);
|
|
||||||
generate_adders!(U768, 768);
|
|
||||||
generate_adders!(U832, 832);
|
|
||||||
generate_adders!(U1088, 1088);
|
|
||||||
generate_adders!(U1216, 1216);
|
|
||||||
generate_adders!(U2112, 2112);
|
|
||||||
generate_adders!(U3136, 3136);
|
|
||||||
generate_adders!(U4160, 4160);
|
|
||||||
generate_adders!(U6144, 6144);
|
|
||||||
generate_adders!(U6208, 6208);
|
|
||||||
generate_adders!(U8256, 8256);
|
|
||||||
generate_adders!(U15424, 15424);
|
|
||||||
generate_adders!(U16384, 16384);
|
|
||||||
generate_adders!(U16448, 16448);
|
|
||||||
generate_adders!(U30720, 30720);
|
|
||||||
generate_adders!(U30784, 30784);
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( ($name:ident, $bigger: ident) ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod normal {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/addition{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, cbytes) = case.get("c").unwrap();
|
|
||||||
assert!(!neg0 && !neg1 && !neg2);
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let c = $bigger::from_bytes(cbytes);
|
|
||||||
assert_eq!(&a + &b, c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((U192, U256),
|
|
||||||
(U256, U320),
|
|
||||||
(U384, U448),
|
|
||||||
(U512, U576),
|
|
||||||
(U576, U640),
|
|
||||||
(U1024, U1088),
|
|
||||||
(U2048, U2112),
|
|
||||||
(U3072, U3136),
|
|
||||||
(U4096, U4160),
|
|
||||||
(U8192, U8256),
|
|
||||||
(U15360, U15424));
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
use cryptonum::addition::UnsafeAdd;
|
|
||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::cmp::min;
|
|
||||||
|
|
||||||
macro_rules! generate_barretts {
|
|
||||||
($bname:ident,$name:ident,$big:ident,$bg2:ident,$dbl:ident,$size:expr) =>
|
|
||||||
{
|
|
||||||
#[derive(Debug,PartialEq)]
|
|
||||||
pub struct $bname {
|
|
||||||
pub(crate) k: usize,
|
|
||||||
pub(crate) m: $big,
|
|
||||||
pub(crate) mu: $big
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $bname {
|
|
||||||
pub fn new(m: &$name) -> $bname {
|
|
||||||
// Step #1: Figure out k
|
|
||||||
let mut k = 0;
|
|
||||||
for i in 0..$size/64 {
|
|
||||||
if m.values[i] != 0 {
|
|
||||||
k = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k += 1;
|
|
||||||
// Step #2: Compute b
|
|
||||||
let mut b = $bg2::zero();
|
|
||||||
b.values[2*k] = 1;
|
|
||||||
// Step #3: Divide b by m.
|
|
||||||
let bigm = $bg2::from(m);
|
|
||||||
let (quot, _) = b.divmod(&bigm);
|
|
||||||
let resm = $big::from(m);
|
|
||||||
let mu = $big::from(");
|
|
||||||
// Done!
|
|
||||||
$bname{ k: k, m: resm, mu: mu }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ok_for_reduce(&self, x: &$dbl) -> bool {
|
|
||||||
for i in self.k*2 .. x.values.len() {
|
|
||||||
if x.values[i] != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reduce(&self, x: &$dbl) -> $name {
|
|
||||||
assert!(self.ok_for_reduce(x));
|
|
||||||
let m2: $bg2 = $bg2::from(&self.m);
|
|
||||||
// 1. q1←⌊x/bk−1⌋, q2←q1 · μ, q3←⌊q2/bk+1⌋.
|
|
||||||
let q1: $big = x.shiftr(self.k - 1);
|
|
||||||
let q2: $bg2 = q1.unsafe_mul(&self.mu);
|
|
||||||
let q3: $big = q2.check_shiftr(self.k + 1);
|
|
||||||
// 2. r1←x mod bk+1, r2←q3 · m mod bk+1, r←r1 − r2.
|
|
||||||
let mut r: $bg2 = x.mask(self.k + 1);
|
|
||||||
let mut r2: $bg2 = q3.unsafe_mul(&self.m);
|
|
||||||
r2.mask_inplace(self.k + 1);
|
|
||||||
let went_negative = &r < &r2;
|
|
||||||
r -= &r2;
|
|
||||||
// 3. If r<0 then r←r+bk+1.
|
|
||||||
if went_negative {
|
|
||||||
let mut bk1 = $bg2::zero();
|
|
||||||
bk1.values[self.k+1] = 1;
|
|
||||||
r = r.unsafe_add(&bk1);
|
|
||||||
}
|
|
||||||
// 4. While r≥m do: r←r−m.
|
|
||||||
while &r > &m2 {
|
|
||||||
r -= &m2;
|
|
||||||
}
|
|
||||||
// Done!
|
|
||||||
$name::from(&r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $dbl {
|
|
||||||
fn shiftr(&self, x: usize) -> $big {
|
|
||||||
let mut res = $big::zero();
|
|
||||||
for i in 0..self.values.len()-x {
|
|
||||||
if i >= res.values.len() {
|
|
||||||
assert_eq!(self.values[i+x], 0);
|
|
||||||
} else {
|
|
||||||
res.values[i] = self.values[i+x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mask(&self, len: usize) -> $bg2 {
|
|
||||||
let mut res = $bg2::zero();
|
|
||||||
let copylen = min(len, self.values.len());
|
|
||||||
for i in 0..copylen {
|
|
||||||
res.values[i] = self.values[i];
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $big {
|
|
||||||
fn unsafe_mul(&self, rhs: &$big) -> $bg2 {
|
|
||||||
let mut w = $bg2::zero();
|
|
||||||
let len = rhs.values.len();
|
|
||||||
|
|
||||||
for i in 0..len {
|
|
||||||
let mut carry = 0;
|
|
||||||
for j in 0..len {
|
|
||||||
if i+j >= w.values.len() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let old = w.values[i+j] as u128;
|
|
||||||
let x128 = self.values[j] as u128;
|
|
||||||
let y128 = rhs.values[i] as u128;
|
|
||||||
let uv = old + (x128 * y128) + carry;
|
|
||||||
w.values[i+j] = uv as u64;
|
|
||||||
carry = uv >> 64;
|
|
||||||
}
|
|
||||||
if i+len < w.values.len() {
|
|
||||||
w.values[i+len] = carry as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $bg2 {
|
|
||||||
fn check_shiftr(&self, x: usize) -> $big {
|
|
||||||
let mut res = $big::zero();
|
|
||||||
|
|
||||||
for i in 0..self.values.len()-x {
|
|
||||||
if i >= res.values.len() {
|
|
||||||
assert_eq!(self.values[i+x], 0);
|
|
||||||
} else {
|
|
||||||
res.values[i] = self.values[i+x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mask_inplace(&mut self, len: usize) {
|
|
||||||
let dellen = min(len, self.values.len());
|
|
||||||
for i in dellen..self.values.len() {
|
|
||||||
self.values[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_barretts!(BarrettU192, U192, U256, U448, U384, 192);
|
|
||||||
generate_barretts!(BarrettU256, U256, U320, U576, U512, 256);
|
|
||||||
generate_barretts!(BarrettU384, U384, U448, U832, U768, 384);
|
|
||||||
generate_barretts!(BarrettU512, U512, U576, U1088, U1024, 512);
|
|
||||||
generate_barretts!(BarrettU576, U576, U640, U1216, U1152, 576);
|
|
||||||
generate_barretts!(BarrettU1024, U1024, U1088, U2112, U2048, 1024);
|
|
||||||
generate_barretts!(BarrettU2048, U2048, U2112, U4160, U4096, 2048);
|
|
||||||
generate_barretts!(BarrettU3072, U3072, U3136, U6208, U6144, 3072);
|
|
||||||
generate_barretts!(BarrettU4096, U4096, U4160, U8256, U8192, 4096);
|
|
||||||
generate_barretts!(BarrettU8192, U8192, U8256, U16448, U16384, 8192);
|
|
||||||
generate_barretts!(BarrettU15360, U15360, U15424, U30784, U30720, 15360);
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( ($bname:ident,$name:ident,$big:ident,$dbl:ident,$size:expr) ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod generation {
|
|
||||||
use cryptonum::encoding::{Decoder,raw_decoder};
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/barrett_gen{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (neg0, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg1, ubytes) = case.get("u").unwrap();
|
|
||||||
let (neg2, kbytes) = case.get("k").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1 && !neg2);
|
|
||||||
let m = $name::from_bytes(mbytes);
|
|
||||||
let u = $big::from_bytes(ubytes);
|
|
||||||
let mut kbig = [0; 1];
|
|
||||||
raw_decoder(&kbytes, &mut kbig);
|
|
||||||
let k = kbig[0] as usize;
|
|
||||||
let r = $bname::new(&m);
|
|
||||||
assert_eq!(k,r.k);
|
|
||||||
assert_eq!(u,r.mu);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod reduction {
|
|
||||||
use cryptonum::encoding::{Decoder,raw_decoder};
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/barrett_reduce{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 5, |case| {
|
|
||||||
let (neg0, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg1, ubytes) = case.get("u").unwrap();
|
|
||||||
let (neg2, kbytes) = case.get("k").unwrap();
|
|
||||||
let (neg3, xbytes) = case.get("x").unwrap();
|
|
||||||
let (neg4, rbytes) = case.get("r").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4);
|
|
||||||
let m = $big::from_bytes(mbytes);
|
|
||||||
let u = $big::from_bytes(ubytes);
|
|
||||||
let mut kbig = [0; 1];
|
|
||||||
raw_decoder(&kbytes, &mut kbig);
|
|
||||||
let k = kbig[0] as usize;
|
|
||||||
let x = $dbl::from_bytes(xbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let bu = $bname{ k: k, m: m, mu: u };
|
|
||||||
let r2 = bu.reduce(&x);
|
|
||||||
assert_eq!(r, r2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((BarrettU192, U192, U256, U384, 192),
|
|
||||||
(BarrettU256, U256, U320, U512, 256),
|
|
||||||
(BarrettU384, U384, U448, U768, 384),
|
|
||||||
(BarrettU512, U512, U576, U1024, 512),
|
|
||||||
(BarrettU576, U576, U640, U1152, 576),
|
|
||||||
(BarrettU1024, U1024, U1088, U2048, 1024),
|
|
||||||
(BarrettU2048, U2048, U2112, U4096, 2048),
|
|
||||||
(BarrettU3072, U3072, U3136, U6144, 3072),
|
|
||||||
(BarrettU4096, U4096, U4160, U8192, 4096),
|
|
||||||
(BarrettU8192, U8192, U8256, U16384, 8192),
|
|
||||||
(BarrettU15360, U15360, U15424, U30720, 15360));
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
pub trait CryptoNum {
|
|
||||||
fn zero() -> Self;
|
|
||||||
fn is_odd(&self) -> bool;
|
|
||||||
fn is_even(&self) -> bool;
|
|
||||||
fn is_zero(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_unsigned
|
|
||||||
{
|
|
||||||
($name: ident, $size: expr) => {
|
|
||||||
pub struct $name {
|
|
||||||
pub(crate) values: [u64; $size/64]
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for $name {
|
|
||||||
fn clone(&self) -> $name {
|
|
||||||
let mut result = $name{ values: [0; $size/64] };
|
|
||||||
result.values.copy_from_slice(&self.values);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for $name {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, stringify!($name))?;
|
|
||||||
write!(f, "{{ ")?;
|
|
||||||
for x in self.values.iter() {
|
|
||||||
write!(f, "{:X} ", *x)?;
|
|
||||||
}
|
|
||||||
write!(f, "}} ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::UpperHex for $name {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
for x in self.values.iter().rev() {
|
|
||||||
f.write_char(tochar_upper(x >> 60))?;
|
|
||||||
f.write_char(tochar_upper(x >> 56))?;
|
|
||||||
f.write_char(tochar_upper(x >> 52))?;
|
|
||||||
f.write_char(tochar_upper(x >> 48))?;
|
|
||||||
f.write_char(tochar_upper(x >> 44))?;
|
|
||||||
f.write_char(tochar_upper(x >> 40))?;
|
|
||||||
f.write_char(tochar_upper(x >> 36))?;
|
|
||||||
f.write_char(tochar_upper(x >> 32))?;
|
|
||||||
f.write_char(tochar_upper(x >> 28))?;
|
|
||||||
f.write_char(tochar_upper(x >> 24))?;
|
|
||||||
f.write_char(tochar_upper(x >> 20))?;
|
|
||||||
f.write_char(tochar_upper(x >> 16))?;
|
|
||||||
f.write_char(tochar_upper(x >> 12))?;
|
|
||||||
f.write_char(tochar_upper(x >> 8))?;
|
|
||||||
f.write_char(tochar_upper(x >> 4))?;
|
|
||||||
f.write_char(tochar_upper(x >> 0))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::LowerHex for $name {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
for x in self.values.iter().rev() {
|
|
||||||
f.write_char(tochar_lower(x >> 60))?;
|
|
||||||
f.write_char(tochar_lower(x >> 56))?;
|
|
||||||
f.write_char(tochar_lower(x >> 52))?;
|
|
||||||
f.write_char(tochar_lower(x >> 48))?;
|
|
||||||
f.write_char(tochar_lower(x >> 44))?;
|
|
||||||
f.write_char(tochar_lower(x >> 40))?;
|
|
||||||
f.write_char(tochar_lower(x >> 36))?;
|
|
||||||
f.write_char(tochar_lower(x >> 32))?;
|
|
||||||
f.write_char(tochar_lower(x >> 28))?;
|
|
||||||
f.write_char(tochar_lower(x >> 24))?;
|
|
||||||
f.write_char(tochar_lower(x >> 20))?;
|
|
||||||
f.write_char(tochar_lower(x >> 16))?;
|
|
||||||
f.write_char(tochar_lower(x >> 12))?;
|
|
||||||
f.write_char(tochar_lower(x >> 8))?;
|
|
||||||
f.write_char(tochar_lower(x >> 4))?;
|
|
||||||
f.write_char(tochar_lower(x >> 0))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CryptoNum for $name {
|
|
||||||
fn zero() -> $name {
|
|
||||||
$name{ values: [0; $size/64 ] }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
(self.values[0] & 1) == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_even(&self) -> bool {
|
|
||||||
(self.values[0] & 1) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_zero(&self) -> bool {
|
|
||||||
for x in self.values.iter() {
|
|
||||||
if *x != 0 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tochar_upper(x: u64) -> char {
|
|
||||||
match (x as u8) & (0xF as u8) {
|
|
||||||
0x0 => '0',
|
|
||||||
0x1 => '1',
|
|
||||||
0x2 => '2',
|
|
||||||
0x3 => '3',
|
|
||||||
0x4 => '4',
|
|
||||||
0x5 => '5',
|
|
||||||
0x6 => '6',
|
|
||||||
0x7 => '7',
|
|
||||||
0x8 => '8',
|
|
||||||
0x9 => '9',
|
|
||||||
0xA => 'A',
|
|
||||||
0xB => 'B',
|
|
||||||
0xC => 'C',
|
|
||||||
0xD => 'D',
|
|
||||||
0xE => 'E',
|
|
||||||
0xF => 'F',
|
|
||||||
_ => panic!("the world is broken")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tochar_lower(x: u64) -> char {
|
|
||||||
match (x as u8) & (0xF as u8) {
|
|
||||||
0x0 => '0',
|
|
||||||
0x1 => '1',
|
|
||||||
0x2 => '2',
|
|
||||||
0x3 => '3',
|
|
||||||
0x4 => '4',
|
|
||||||
0x5 => '5',
|
|
||||||
0x6 => '6',
|
|
||||||
0x7 => '7',
|
|
||||||
0x8 => '8',
|
|
||||||
0x9 => '9',
|
|
||||||
0xA => 'a',
|
|
||||||
0xB => 'b',
|
|
||||||
0xC => 'c',
|
|
||||||
0xD => 'd',
|
|
||||||
0xE => 'e',
|
|
||||||
0xF => 'f',
|
|
||||||
_ => panic!("the world is broken")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_unsigned!(U192, 192);
|
|
||||||
generate_unsigned!(U256, 256);
|
|
||||||
generate_unsigned!(U320, 320); // this is just for expansion
|
|
||||||
generate_unsigned!(U384, 384);
|
|
||||||
generate_unsigned!(U448, 448); // this is just for expansion
|
|
||||||
generate_unsigned!(U512, 512);
|
|
||||||
generate_unsigned!(U576, 576);
|
|
||||||
generate_unsigned!(U640, 640); // this is just for expansion
|
|
||||||
generate_unsigned!(U768, 768); // this is just for expansion
|
|
||||||
generate_unsigned!(U832, 832); // this is just for Barrett
|
|
||||||
generate_unsigned!(U896, 896); // this is just for Barrett
|
|
||||||
generate_unsigned!(U1024, 1024);
|
|
||||||
generate_unsigned!(U1088, 1088); // this is just for expansion
|
|
||||||
generate_unsigned!(U1152, 1152); // this is just for expansion
|
|
||||||
generate_unsigned!(U1216, 1216); // this is just for Barrett
|
|
||||||
generate_unsigned!(U1536, 1536); // this is just for expansion
|
|
||||||
generate_unsigned!(U1664, 1664); // this is just for Barrett
|
|
||||||
generate_unsigned!(U2048, 2048);
|
|
||||||
generate_unsigned!(U2112, 2112); // this is just for expansion
|
|
||||||
generate_unsigned!(U2176, 2176); // this is just for Barrett
|
|
||||||
generate_unsigned!(U2304, 2304); // this is just for expansion
|
|
||||||
generate_unsigned!(U2432, 2432); // this is just for Barrett
|
|
||||||
generate_unsigned!(U3072, 3072);
|
|
||||||
generate_unsigned!(U3136, 3136); // this is just for expansion
|
|
||||||
generate_unsigned!(U4096, 4096);
|
|
||||||
generate_unsigned!(U4160, 4160); // this is just for expansion
|
|
||||||
generate_unsigned!(U4224, 4224); // this is just for Barrett
|
|
||||||
generate_unsigned!(U6144, 6144); // this is just for expansion
|
|
||||||
generate_unsigned!(U6208, 6208); // this is just for Barrett
|
|
||||||
generate_unsigned!(U7680, 7680); // Useful for RSA key generation
|
|
||||||
generate_unsigned!(U7744, 7744); // Addition on previous
|
|
||||||
generate_unsigned!(U8192, 8192);
|
|
||||||
generate_unsigned!(U8256, 8256); // this is just for expansion
|
|
||||||
generate_unsigned!(U8320, 8320); // this is just for Barrett
|
|
||||||
generate_unsigned!(U12288, 12288); // this is just for expansion
|
|
||||||
generate_unsigned!(U12416, 12416); // this is just for Barrett
|
|
||||||
generate_unsigned!(U15360, 15360);
|
|
||||||
generate_unsigned!(U15424, 15424); // this is just for expansion
|
|
||||||
generate_unsigned!(U16384, 16384); // this is just for expansion
|
|
||||||
generate_unsigned!(U16448, 16448); // this is just for Barrett
|
|
||||||
generate_unsigned!(U16512, 16512); // this is just for Barrett
|
|
||||||
generate_unsigned!(U30720, 30720); // this is just for expansion
|
|
||||||
generate_unsigned!(U30784, 30784); // this is just for Barrett
|
|
||||||
generate_unsigned!(U32768, 32768); // this is just for expansion
|
|
||||||
generate_unsigned!(U32896, 32896); // this is just for Barrett
|
|
||||||
generate_unsigned!(U61440, 61440); // this is just for expansion
|
|
||||||
generate_unsigned!(U61568, 61568); // this is just for Barrett
|
|
||||||
@@ -1,855 +0,0 @@
|
|||||||
macro_rules! construct_unsigned {
|
|
||||||
($type: ident, $modname: ident, $count: expr) => {
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct $type {
|
|
||||||
contents: [u64; $count]
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for $type {
|
|
||||||
fn eq(&self, other: &$type) -> bool {
|
|
||||||
for i in 0..$count {
|
|
||||||
if self.contents[i] != other.contents[i] {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for $type {}
|
|
||||||
|
|
||||||
impl Debug for $type {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(),Error> {
|
|
||||||
f.write_str("CryptoNum{{ ")?;
|
|
||||||
f.debug_list().entries(self.contents.iter()).finish()?;
|
|
||||||
f.write_str(" }}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $type {
|
|
||||||
/// 0!
|
|
||||||
pub fn zero() -> $type {
|
|
||||||
$type { contents: [0; $count] }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The maximum possible value we can hold.
|
|
||||||
pub fn max() -> $type {
|
|
||||||
$type { contents: [0xFFFFFFFFFFFFFFFF; $count] }
|
|
||||||
}
|
|
||||||
|
|
||||||
from_to!($type, $count, u8, from_u8, to_u8);
|
|
||||||
from_to!($type, $count, u16, from_u16, to_u16);
|
|
||||||
from_to!($type, $count, u32, from_u32, to_u32);
|
|
||||||
from_to!($type, $count, u64, from_u64, to_u64);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for $type {
|
|
||||||
fn partial_cmp(&self, other: &$type) -> Option<Ordering> {
|
|
||||||
Some(generic_cmp(&self.contents, &other.contents))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for $type {
|
|
||||||
fn cmp(&self, other: &$type) -> Ordering {
|
|
||||||
generic_cmp(&self.contents, &other.contents)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Not for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn not(self) -> $type {
|
|
||||||
let mut output = self.clone();
|
|
||||||
generic_not(&mut output.contents);
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Not for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn not(self) -> $type {
|
|
||||||
let mut output = self.clone();
|
|
||||||
generic_not(&mut output.contents);
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opers2!($type,BitOrAssign,bitor_assign,BitOr,bitor,generic_bitor);
|
|
||||||
opers2!($type,BitAndAssign,bitand_assign,BitAnd,bitand,generic_bitand);
|
|
||||||
opers2!($type,BitXorAssign,bitxor_assign,BitXor,bitxor,generic_bitxor);
|
|
||||||
|
|
||||||
shifts!($type, usize);
|
|
||||||
shifts!($type, u64);
|
|
||||||
shifts!($type, i64);
|
|
||||||
shifts!($type, u32);
|
|
||||||
shifts!($type, i32);
|
|
||||||
shifts!($type, u16);
|
|
||||||
shifts!($type, i16);
|
|
||||||
shifts!($type, u8);
|
|
||||||
shifts!($type, i8);
|
|
||||||
|
|
||||||
opers2!($type,AddAssign,add_assign,Add,add,generic_add);
|
|
||||||
opers2!($type,SubAssign,sub_assign,Sub,sub,generic_sub);
|
|
||||||
opers3!($type,MulAssign,mul_assign,Mul,mul,generic_mul);
|
|
||||||
|
|
||||||
impl DivAssign<$type> for $type {
|
|
||||||
fn div_assign(&mut self, rhs: $type) {
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
generic_div(©, &rhs.contents,
|
|
||||||
&mut self.contents, &mut dead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DivAssign<&'a $type> for $type {
|
|
||||||
fn div_assign(&mut self, rhs: &$type) {
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
generic_div(©, &rhs.contents,
|
|
||||||
&mut self.contents, &mut dead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Div<$type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn div(self, rhs: $type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut res.contents, &mut dead);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Div<$type> for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn div(self, rhs: $type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut res.contents, &mut dead);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Div<&'a $type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn div(self, rhs: &$type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut res.contents, &mut dead);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b> Div<&'a $type> for &'b $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn div(self, rhs: &$type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut res.contents, &mut dead);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RemAssign<$type> for $type {
|
|
||||||
fn rem_assign(&mut self, rhs: $type) {
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
generic_div(©, &rhs.contents,
|
|
||||||
&mut dead, &mut self.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> RemAssign<&'a $type> for $type {
|
|
||||||
fn rem_assign(&mut self, rhs: &$type) {
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
generic_div(©, &rhs.contents,
|
|
||||||
&mut dead, &mut self.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rem<$type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn rem(self, rhs: $type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut dead, &mut res.contents);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Rem<$type> for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn rem(self, rhs: $type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut dead, &mut res.contents);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Rem<&'a $type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn rem(self, rhs: &$type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut dead, &mut res.contents);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b> Rem<&'a $type> for &'b $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn rem(self, rhs: &$type) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut dead = [0; $count];
|
|
||||||
generic_div(&self.contents, &rhs.contents,
|
|
||||||
&mut dead, &mut res.contents);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CryptoNum for $type {
|
|
||||||
fn divmod(&self, a: &$type, q: &mut $type, r: &mut $type) {
|
|
||||||
generic_div(&self.contents, &a.contents,
|
|
||||||
&mut q.contents, &mut r.contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
let mut res = Vec::with_capacity($count * 8);
|
|
||||||
for x in self.contents.iter() {
|
|
||||||
res.push( (x >> 56) as u8 );
|
|
||||||
res.push( (x >> 48) as u8 );
|
|
||||||
res.push( (x >> 40) as u8 );
|
|
||||||
res.push( (x >> 32) as u8 );
|
|
||||||
res.push( (x >> 24) as u8 );
|
|
||||||
res.push( (x >> 16) as u8 );
|
|
||||||
res.push( (x >> 8) as u8 );
|
|
||||||
res.push( (x >> 0) as u8 );
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_bytes(x: &[u8]) -> $type {
|
|
||||||
let mut res = $type::zero();
|
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
assert!(x.len() >= ($count * 8));
|
|
||||||
for chunk in x.chunks(8) {
|
|
||||||
assert!(chunk.len() == 8);
|
|
||||||
res.contents[i] = ((chunk[0] as u64) << 56) |
|
|
||||||
((chunk[1] as u64) << 48) |
|
|
||||||
((chunk[2] as u64) << 40) |
|
|
||||||
((chunk[3] as u64) << 32) |
|
|
||||||
((chunk[4] as u64) << 24) |
|
|
||||||
((chunk[5] as u64) << 16) |
|
|
||||||
((chunk[6] as u64) << 8) |
|
|
||||||
((chunk[7] as u64) << 0);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
assert!(i == $count);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod $modname {
|
|
||||||
use quickcheck::{Arbitrary,Gen};
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
impl Arbitrary for $type {
|
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> $type {
|
|
||||||
let mut res = [0; $count];
|
|
||||||
|
|
||||||
for i in 0..$count {
|
|
||||||
res[i] = g.next_u64();
|
|
||||||
}
|
|
||||||
$type{ contents: res }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_builders() {
|
|
||||||
let mut buffer = [0; $count];
|
|
||||||
assert_eq!($type{ contents: buffer }, $type::from_u8(0));
|
|
||||||
buffer[0] = 0x7F;
|
|
||||||
assert_eq!($type{ contents: buffer }, $type::from_u8(0x7F));
|
|
||||||
buffer[0] = 0x7F7F;
|
|
||||||
assert_eq!($type{ contents: buffer }, $type::from_u16(0x7F7F));
|
|
||||||
buffer[0] = 0xCA5CADE5;
|
|
||||||
assert_eq!($type{ contents: buffer },
|
|
||||||
$type::from_u32(0xCA5CADE5));
|
|
||||||
assert_eq!($type{ contents: buffer },
|
|
||||||
$type::from_u64(0xCA5CADE5));
|
|
||||||
buffer[0] = 0xFFFFFFFFFFFFFFFF;
|
|
||||||
assert_eq!($type{ contents: buffer },
|
|
||||||
$type::from_u64(0xFFFFFFFFFFFFFFFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_max() {
|
|
||||||
assert_eq!($type::from_u64(u64::max_value()).to_u64(),
|
|
||||||
u64::max_value());
|
|
||||||
assert_eq!($type::max().to_u64(), u64::max_value());
|
|
||||||
assert_eq!($type::max() + $type::from_u8(1), $type::zero());
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn builder_u8_upgrade_u16(x: u8) -> bool {
|
|
||||||
$type::from_u8(x) == $type::from_u16(x as u16)
|
|
||||||
}
|
|
||||||
fn builder_u16_upgrade_u32(x: u16) -> bool {
|
|
||||||
$type::from_u16(x) == $type::from_u32(x as u32)
|
|
||||||
}
|
|
||||||
fn builder_u32_upgrade_u64(x: u32) -> bool {
|
|
||||||
$type::from_u32(x) == $type::from_u64(x as u64)
|
|
||||||
}
|
|
||||||
fn builder_u8_roundtrips(x: u8) -> bool {
|
|
||||||
x == $type::from_u8(x).to_u8()
|
|
||||||
}
|
|
||||||
fn builder_u16_roundtrips(x: u16) -> bool {
|
|
||||||
x == $type::from_u16(x).to_u16()
|
|
||||||
}
|
|
||||||
fn builder_u32_roundtrips(x: u32) -> bool {
|
|
||||||
x == $type::from_u32(x).to_u32()
|
|
||||||
}
|
|
||||||
fn builder_u64_roundtrips(x: u64) -> bool {
|
|
||||||
x == $type::from_u64(x).to_u64()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn partial_ord64_works(x: u64, y: u64) -> bool {
|
|
||||||
let xbig = $type::from_u64(x);
|
|
||||||
let ybig = $type::from_u64(y);
|
|
||||||
xbig.partial_cmp(&ybig) == x.partial_cmp(&y)
|
|
||||||
}
|
|
||||||
fn ord64_works(x: u64, y: u64) -> bool {
|
|
||||||
let xbig = $type::from_u64(x);
|
|
||||||
let ybig = $type::from_u64(y);
|
|
||||||
xbig.cmp(&ybig) == x.cmp(&y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn and_annulment(x: $type) -> bool {
|
|
||||||
(x & $type::zero()) == $type::zero()
|
|
||||||
}
|
|
||||||
fn or_annulment(x: $type) -> bool {
|
|
||||||
(x | $type::max()) == $type::max()
|
|
||||||
}
|
|
||||||
fn and_identity(x: $type) -> bool {
|
|
||||||
(&x & $type::max()) == x
|
|
||||||
}
|
|
||||||
fn or_identity(x: $type) -> bool {
|
|
||||||
(&x | $type::zero()) == x
|
|
||||||
}
|
|
||||||
fn and_idempotent(x: $type) -> bool {
|
|
||||||
(&x & &x) == x
|
|
||||||
}
|
|
||||||
fn or_idempotent(x: $type) -> bool {
|
|
||||||
(&x | &x) == x
|
|
||||||
}
|
|
||||||
fn and_complement(x: $type) -> bool {
|
|
||||||
(&x & &x) == x
|
|
||||||
}
|
|
||||||
fn or_complement(x: $type) -> bool {
|
|
||||||
(&x | !&x) == $type::max()
|
|
||||||
}
|
|
||||||
fn and_commutative(x: $type, y: $type) -> bool {
|
|
||||||
(&x & &y) == (&y & &x)
|
|
||||||
}
|
|
||||||
fn or_commutative(x: $type, y: $type) -> bool {
|
|
||||||
(&x | &y) == (&y | &x)
|
|
||||||
}
|
|
||||||
fn double_negation(x: $type) -> bool {
|
|
||||||
!!&x == x
|
|
||||||
}
|
|
||||||
fn or_distributive(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a & (&b | &c)) == ((&a & &b) | (&a & &c))
|
|
||||||
}
|
|
||||||
fn and_distributive(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a | (&b & &c)) == ((&a | &b) & (&a | &c))
|
|
||||||
}
|
|
||||||
fn or_absorption(a: $type, b: $type) -> bool {
|
|
||||||
(&a | (&a & &b)) == a
|
|
||||||
}
|
|
||||||
fn and_absorption(a: $type, b: $type) -> bool {
|
|
||||||
(&a & (&a | &b)) == a
|
|
||||||
}
|
|
||||||
fn or_associative(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a | (&b | &c)) == ((&a | &b) | &c)
|
|
||||||
}
|
|
||||||
fn and_associative(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a & (&b & &c)) == ((&a & &b) & &c)
|
|
||||||
}
|
|
||||||
fn xor_as_defined(a: $type, b: $type) -> bool {
|
|
||||||
(&a ^ &b) == ((&a | &b) & !(&a & &b))
|
|
||||||
}
|
|
||||||
fn small_or_check(x: u64, y: u64) -> bool {
|
|
||||||
let x512 = $type::from_u64(x);
|
|
||||||
let y512 = $type::from_u64(y);
|
|
||||||
let z512 = x512 | y512;
|
|
||||||
z512.to_u64() == (x | y)
|
|
||||||
}
|
|
||||||
fn small_and_check(x: u64, y: u64) -> bool {
|
|
||||||
let x512 = $type::from_u64(x);
|
|
||||||
let y512 = $type::from_u64(y);
|
|
||||||
let z512 = x512 & y512;
|
|
||||||
z512.to_u64() == (x & y)
|
|
||||||
}
|
|
||||||
fn small_xor_check(x: u64, y: u64) -> bool {
|
|
||||||
let x512 = $type::from_u64(x);
|
|
||||||
let y512 = $type::from_u64(y);
|
|
||||||
let z512 = x512 ^ y512;
|
|
||||||
z512.to_u64() == (x ^ y)
|
|
||||||
}
|
|
||||||
fn small_neg_check(x: u64) -> bool {
|
|
||||||
let x512 = $type::from_u64(x);
|
|
||||||
let z512 = !x512;
|
|
||||||
z512.to_u64() == !x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn shl_tests() {
|
|
||||||
let ones = [1; $count];
|
|
||||||
assert_eq!($type{ contents: ones.clone() } << 0,
|
|
||||||
$type{ contents: ones.clone() });
|
|
||||||
let mut notones = [0; $count];
|
|
||||||
for i in 0..$count {
|
|
||||||
notones[i] = (i + 1) as u64;
|
|
||||||
}
|
|
||||||
assert_eq!($type{ contents: notones.clone() } << 0,
|
|
||||||
$type{ contents: notones.clone() });
|
|
||||||
assert_eq!($type{ contents: ones.clone() } << ($count * 64),
|
|
||||||
$type::from_u64(0));
|
|
||||||
assert_eq!($type::from_u8(2) << 1, $type::from_u8(4));
|
|
||||||
let mut buffer = [0; $count];
|
|
||||||
buffer[1] = 1;
|
|
||||||
assert_eq!($type::from_u8(1) << 64,
|
|
||||||
$type{ contents: buffer.clone() });
|
|
||||||
buffer[0] = 0xFFFFFFFFFFFFFFFE;
|
|
||||||
assert_eq!($type::from_u64(0xFFFFFFFFFFFFFFFF) << 1,
|
|
||||||
$type{ contents: buffer.clone() });
|
|
||||||
buffer[0] = 0;
|
|
||||||
buffer[1] = 4;
|
|
||||||
assert_eq!($type::from_u8(1) << 66,
|
|
||||||
$type{ contents: buffer.clone() });
|
|
||||||
assert_eq!($type::from_u8(1) << 1, $type::from_u8(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn shr_tests() {
|
|
||||||
let ones = [1; $count];
|
|
||||||
assert_eq!($type{ contents: ones.clone() } >> 0,
|
|
||||||
$type{ contents: ones.clone() });
|
|
||||||
let mut notones = [0; $count];
|
|
||||||
for i in 0..$count {
|
|
||||||
notones[i] = (i + 1) as u64;
|
|
||||||
}
|
|
||||||
assert_eq!($type{ contents: ones.clone() } >> 0,
|
|
||||||
$type{ contents: ones.clone() });
|
|
||||||
assert_eq!($type{ contents: ones.clone() } >> ($count * 64),
|
|
||||||
$type::from_u8(0));
|
|
||||||
assert_eq!($type::from_u8(2) >> 1,
|
|
||||||
$type::from_u8(1));
|
|
||||||
let mut oneleft = [0; $count];
|
|
||||||
oneleft[1] = 1;
|
|
||||||
assert_eq!($type{ contents: oneleft.clone() } >> 1,
|
|
||||||
$type::from_u64(0x8000000000000000));
|
|
||||||
assert_eq!($type{ contents: oneleft.clone() } >> 64,
|
|
||||||
$type::from_u64(1));
|
|
||||||
oneleft[1] = 4;
|
|
||||||
assert_eq!($type{ contents: oneleft.clone() } >> 66,
|
|
||||||
$type::from_u64(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn shift_mask_equivr(x: $type, in_shift: usize) -> bool {
|
|
||||||
let shift = in_shift % ($count * 64);
|
|
||||||
let mask = $type::max() << shift;
|
|
||||||
let masked_x = &x & mask;
|
|
||||||
let shift_maskr = (x >> shift) << shift;
|
|
||||||
shift_maskr == masked_x
|
|
||||||
}
|
|
||||||
fn shift_mask_equivl(x: $type, in_shift: usize) -> bool {
|
|
||||||
let shift = in_shift % ($count * 64);
|
|
||||||
let mask = $type::max() >> shift;
|
|
||||||
let masked_x = &x & mask;
|
|
||||||
let shift_maskl = (x << shift) >> shift;
|
|
||||||
shift_maskl == masked_x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_tests() {
|
|
||||||
let ones = [1; $count];
|
|
||||||
let twos = [2; $count];
|
|
||||||
assert_eq!($type{ contents: ones.clone() } +
|
|
||||||
$type{ contents: ones.clone() },
|
|
||||||
$type{ contents: twos.clone() });
|
|
||||||
let mut buffer = [0; $count];
|
|
||||||
buffer[1] = 1;
|
|
||||||
assert_eq!($type::from_u64(1) + $type::from_u64(0xFFFFFFFFFFFFFFFF),
|
|
||||||
$type{ contents: buffer.clone() });
|
|
||||||
let mut high = [0; $count];
|
|
||||||
high[$count - 1] = 0xFFFFFFFFFFFFFFFF;
|
|
||||||
buffer[1] = 0;
|
|
||||||
buffer[$count - 1] = 1;
|
|
||||||
assert_eq!($type{ contents: buffer } + $type{ contents: high },
|
|
||||||
$type{ contents: [0; $count] });
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn add_symmetry(a: $type, b: $type) -> bool {
|
|
||||||
(&a + &b) == (&b + &a)
|
|
||||||
}
|
|
||||||
fn add_commutivity(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a + (&b + &c)) == ((&a + &b) + &c)
|
|
||||||
}
|
|
||||||
fn add_identity(a: $type) -> bool {
|
|
||||||
(&a + $type::zero()) == a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sub_tests() {
|
|
||||||
let ones = [1; $count];
|
|
||||||
assert_eq!($type{ contents: ones.clone() } -
|
|
||||||
$type{ contents: ones.clone() },
|
|
||||||
$type::from_u64(0));
|
|
||||||
let mut buffer = [0; $count];
|
|
||||||
buffer[1] = 1;
|
|
||||||
assert_eq!($type{ contents: buffer.clone() } - $type::from_u64(1),
|
|
||||||
$type::from_u64(0xFFFFFFFFFFFFFFFF));
|
|
||||||
assert_eq!($type::zero() - $type::from_u8(1), $type::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn sub_destroys(a: $type) -> bool {
|
|
||||||
(&a - &a) == $type::zero()
|
|
||||||
}
|
|
||||||
fn sub_add_ident(a: $type, b: $type) -> bool {
|
|
||||||
((&a - &b) + &b) == a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mul_tests() {
|
|
||||||
assert_eq!($type::from_u8(1) * $type::from_u8(1),
|
|
||||||
$type::from_u8(1));
|
|
||||||
assert_eq!($type::from_u8(1) * $type::from_u8(0),
|
|
||||||
$type::from_u8(0));
|
|
||||||
assert_eq!($type::from_u8(1) * $type::from_u8(2),
|
|
||||||
$type::from_u8(2));
|
|
||||||
let mut temp = $type::zero();
|
|
||||||
temp.contents[0] = 1;
|
|
||||||
temp.contents[1] = 0xFFFFFFFFFFFFFFFE;
|
|
||||||
assert_eq!($type::from_u64(0xFFFFFFFFFFFFFFFF) *
|
|
||||||
$type::from_u64(0xFFFFFFFFFFFFFFFF),
|
|
||||||
temp);
|
|
||||||
let effs = $type{ contents: [0xFFFFFFFFFFFFFFFF; $count] };
|
|
||||||
assert_eq!($type::from_u8(1) * &effs, effs);
|
|
||||||
temp = effs.clone();
|
|
||||||
temp.contents[0] = temp.contents[0] - 1;
|
|
||||||
assert_eq!($type::from_u8(2) * &effs, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn mul_symmetry(a: $type, b: $type) -> bool {
|
|
||||||
(&a * &b) == (&b * &a)
|
|
||||||
}
|
|
||||||
fn mul_commutivity(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a * (&b * &c)) == ((&a * &b) * &c)
|
|
||||||
}
|
|
||||||
fn mul_identity(a: $type) -> bool {
|
|
||||||
(&a * $type::from_u64(1)) == a
|
|
||||||
}
|
|
||||||
fn mul_zero(a: $type) -> bool {
|
|
||||||
(&a * $type::zero()) == $type::zero()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn addmul_distribution(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a * (&b + &c)) == ((&a * &b) + (&a * &c))
|
|
||||||
}
|
|
||||||
fn submul_distribution(a: $type, b: $type, c: $type) -> bool {
|
|
||||||
(&a * (&b - &c)) == ((&a * &b) - (&a * &c))
|
|
||||||
}
|
|
||||||
fn mul2shift1_equiv(a: $type) -> bool {
|
|
||||||
(&a << 1) == (&a * $type::from_u64(2))
|
|
||||||
}
|
|
||||||
fn mul16shift4_equiv(a: $type) -> bool {
|
|
||||||
(&a << 4) == (&a * $type::from_u64(16))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn div_tests() {
|
|
||||||
assert_eq!($type::from_u8(2) / $type::from_u8(2),
|
|
||||||
$type::from_u8(1));
|
|
||||||
assert_eq!($type::from_u8(2) / $type::from_u8(1),
|
|
||||||
$type::from_u8(2));
|
|
||||||
assert_eq!($type::from_u8(4) / $type::from_u8(3),
|
|
||||||
$type::from_u8(1));
|
|
||||||
assert_eq!($type::from_u8(4) / $type::from_u8(5),
|
|
||||||
$type::from_u8(0));
|
|
||||||
assert_eq!($type::from_u8(4) / $type::from_u8(4),
|
|
||||||
$type::from_u8(1));
|
|
||||||
let mut temp1 = $type::zero();
|
|
||||||
let mut temp2 = $type::zero();
|
|
||||||
temp1.contents[$count - 1] = 4;
|
|
||||||
temp2.contents[$count - 1] = 4;
|
|
||||||
assert_eq!(&temp1 / temp2, $type::from_u8(1));
|
|
||||||
assert_eq!(&temp1 / $type::from_u8(1), temp1);
|
|
||||||
temp1.contents[$count - 1] = u64::max_value();
|
|
||||||
assert_eq!(&temp1 / $type::from_u8(1), temp1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn div0_fails() {
|
|
||||||
$type::from_u64(0xabcd) / $type::zero();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mod_tests() {
|
|
||||||
assert_eq!($type::from_u8(4) % $type::from_u8(5),
|
|
||||||
$type::from_u8(4));
|
|
||||||
assert_eq!($type::from_u8(5) % $type::from_u8(4),
|
|
||||||
$type::from_u8(1));
|
|
||||||
let fives = $type{ contents: [5; $count] };
|
|
||||||
let fours = $type{ contents: [4; $count] };
|
|
||||||
let ones = $type{ contents: [1; $count] };
|
|
||||||
assert_eq!(fives % fours, ones);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn divmod_tests() {
|
|
||||||
let a = $type::from_u64(4);
|
|
||||||
let b = $type::from_u64(3);
|
|
||||||
let mut q = $type::zero();
|
|
||||||
let mut r = $type::zero();
|
|
||||||
a.divmod(&b, &mut q, &mut r);
|
|
||||||
let mut x = [0; $count];
|
|
||||||
x[0] = 1;
|
|
||||||
assert_eq!(q, $type{ contents: x });
|
|
||||||
assert_eq!(r, $type{ contents: x });
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
#[ignore]
|
|
||||||
fn div_identity(a: $type) -> bool {
|
|
||||||
&a / $type::from_u64(1) == a
|
|
||||||
}
|
|
||||||
fn div_self_is_one(a: $type) -> bool {
|
|
||||||
if a == $type::zero() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
&a / &a == $type::from_u64(1)
|
|
||||||
}
|
|
||||||
fn euclid_is_alive(a: $type, b: $type) -> bool {
|
|
||||||
let mut q = $type::zero();
|
|
||||||
let mut r = $type::zero();
|
|
||||||
a.divmod(&b, &mut q, &mut r);
|
|
||||||
a == ((b * q) + r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn serialization_inverts(a: $type) -> bool {
|
|
||||||
let bytes = a.to_bytes();
|
|
||||||
let b = $type::from_bytes(&bytes);
|
|
||||||
a == b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! from_to {
|
|
||||||
($type: ident, $count: expr, $base: ty, $from: ident, $to: ident) => {
|
|
||||||
/// Convert the given base type into this type. This is always safe.
|
|
||||||
pub fn $from(x: $base) -> $type {
|
|
||||||
let mut res = $type { contents: [0; $count] };
|
|
||||||
res.contents[0] = x as u64;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert this back into a base type. This is the equivalent of
|
|
||||||
/// masking off the relevant number of bits, and should work just
|
|
||||||
/// like the `as` keyword with normal word types.
|
|
||||||
pub fn $to(&self) -> $base {
|
|
||||||
self.contents[0] as $base
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! shifts {
|
|
||||||
($type: ident, $shtype: ty) => {
|
|
||||||
shifts!($type, $shtype, ShlAssign, shl_assign, Shl, shl, generic_shl);
|
|
||||||
shifts!($type, $shtype, ShrAssign, shr_assign, Shr, shr, generic_shr);
|
|
||||||
};
|
|
||||||
|
|
||||||
($type: ident, $shtype: ty, $asncl: ident, $asnfn: ident,
|
|
||||||
$cl: ident, $fn: ident, $impl: ident) => {
|
|
||||||
impl $asncl<$shtype> for $type {
|
|
||||||
fn $asnfn(&mut self, amount: $shtype) {
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
$impl(&mut self.contents, ©, amount as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $cl<$shtype> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $shtype) -> $type {
|
|
||||||
let mut res = self.clone();
|
|
||||||
$impl(&mut res.contents, &self.contents, rhs as usize);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $cl<$shtype> for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $shtype) -> $type {
|
|
||||||
let mut res = self.clone();
|
|
||||||
$impl(&mut res.contents, &self.contents, rhs as usize);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! opers2 {
|
|
||||||
($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => {
|
|
||||||
impl $asncl for $type {
|
|
||||||
fn $asnfn(&mut self, other: $type) {
|
|
||||||
$impl(&mut self.contents, &other.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $asncl<&'a $type> for $type {
|
|
||||||
fn $asnfn(&mut self, other: &$type) {
|
|
||||||
$impl(&mut self.contents, &other.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $cl for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $cl<&'a $type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: &$type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $cl<$type> for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b> $cl<&'a $type> for &'b $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: &$type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! opers3 {
|
|
||||||
($type:ident,$asncl:ident,$asnfn:ident,$cl:ident,$fn:ident,$impl:ident) => {
|
|
||||||
impl $asncl for $type {
|
|
||||||
fn $asnfn(&mut self, other: $type) {
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
$impl(&mut self.contents, ©, &other.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $asncl<&'a $type> for $type {
|
|
||||||
fn $asnfn(&mut self, other: &$type) {
|
|
||||||
let copy = self.contents.clone();
|
|
||||||
$impl(&mut self.contents, ©, &other.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $cl for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &self.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $cl<&'a $type> for $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: &$type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &self.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> $cl<$type> for &'a $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: $type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &self.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b> $cl<&'a $type> for &'b $type {
|
|
||||||
type Output = $type;
|
|
||||||
|
|
||||||
fn $fn(self, rhs: &$type) -> $type {
|
|
||||||
let mut copy = self.clone();
|
|
||||||
$impl(&mut copy.contents, &self.contents, &rhs.contents);
|
|
||||||
copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::cmp::{Ord,Ordering};
|
|
||||||
|
|
||||||
macro_rules! generate_compares
|
|
||||||
{
|
|
||||||
($name: ident, $size: expr) => {
|
|
||||||
impl PartialEq for $name {
|
|
||||||
fn eq(&self, other: &$name) -> bool {
|
|
||||||
for i in 0..($size/64) {
|
|
||||||
if self.values[i] != other.values[i] {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for $name {}
|
|
||||||
|
|
||||||
impl Ord for $name {
|
|
||||||
fn cmp(&self, other: &$name) -> Ordering {
|
|
||||||
let mut i = (($size / 64) - 1) as isize;
|
|
||||||
|
|
||||||
while i >= 0 {
|
|
||||||
let iu = i as usize;
|
|
||||||
match self.values[iu].cmp(&other.values[iu]) {
|
|
||||||
Ordering::Greater => return Ordering::Greater,
|
|
||||||
Ordering::Less => return Ordering::Less,
|
|
||||||
Ordering::Equal => i -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ordering::Equal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for $name {
|
|
||||||
fn partial_cmp(&self, other: &$name) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_compares!(U192, 192);
|
|
||||||
generate_compares!(U256, 256);
|
|
||||||
generate_compares!(U320, 320); // this is just for expansion
|
|
||||||
generate_compares!(U384, 384);
|
|
||||||
generate_compares!(U448, 448); // this is just for expansion
|
|
||||||
generate_compares!(U512, 512);
|
|
||||||
generate_compares!(U576, 576);
|
|
||||||
generate_compares!(U640, 640); // this is just for expansion
|
|
||||||
generate_compares!(U768, 768); // this is just for expansion
|
|
||||||
generate_compares!(U832, 832); // this is just for Barrett
|
|
||||||
generate_compares!(U896, 896); // this is just for Barrett
|
|
||||||
generate_compares!(U1024, 1024);
|
|
||||||
generate_compares!(U1088, 1088); // this is just for expansion
|
|
||||||
generate_compares!(U1152, 1152); // this is just for expansion
|
|
||||||
generate_compares!(U1216, 1216); // this is just for Barrett
|
|
||||||
generate_compares!(U1536, 1536); // this is just for expansion
|
|
||||||
generate_compares!(U1664, 1664); // this is just for Barrett
|
|
||||||
generate_compares!(U2048, 2048);
|
|
||||||
generate_compares!(U2112, 2112); // this is just for expansion
|
|
||||||
generate_compares!(U2176, 2176); // this is just for Barrett
|
|
||||||
generate_compares!(U2304, 2304); // this is just for expansion
|
|
||||||
generate_compares!(U2432, 2432); // this is just for Barrett
|
|
||||||
generate_compares!(U3072, 3072);
|
|
||||||
generate_compares!(U3136, 3136); // this is just for expansion
|
|
||||||
generate_compares!(U4096, 4096);
|
|
||||||
generate_compares!(U4160, 4160); // this is just for expansion
|
|
||||||
generate_compares!(U4224, 4224); // this is just for Barrett
|
|
||||||
generate_compares!(U6144, 6144); // this is just for expansion
|
|
||||||
generate_compares!(U6208, 6208); // this is just for Barrett
|
|
||||||
generate_compares!(U7680, 7680);
|
|
||||||
generate_compares!(U7744, 7744);
|
|
||||||
generate_compares!(U8192, 8192);
|
|
||||||
generate_compares!(U8256, 8256); // this is just for expansion
|
|
||||||
generate_compares!(U8320, 8320); // this is just for Barrett
|
|
||||||
generate_compares!(U12288, 12288); // this is just for expansion
|
|
||||||
generate_compares!(U12416, 12416); // this is just for Barrett
|
|
||||||
generate_compares!(U15360, 15360);
|
|
||||||
generate_compares!(U15424, 15424); // this is just for expansion
|
|
||||||
generate_compares!(U16384, 16384); // this is just for expansion
|
|
||||||
generate_compares!(U16448, 16448); // this is just for Barrett
|
|
||||||
generate_compares!(U16512, 16512); // this is just for Barrett
|
|
||||||
generate_compares!(U30720, 30720); // this is just for expansion
|
|
||||||
generate_compares!(U30784, 30784); // this is just for Barrett
|
|
||||||
generate_compares!(U32768, 32768); // this is just for expansion
|
|
||||||
generate_compares!(U32896, 32896); // this is just for Barrett
|
|
||||||
generate_compares!(U61440, 61440); // this is just for expansion
|
|
||||||
generate_compares!(U61568, 61568); // this is just for Barrett
|
|
||||||
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use cryptonum::encoding::Encoder;
|
|
||||||
use num::bigint::BigUint;
|
|
||||||
use num::{FromPrimitive,ToPrimitive};
|
|
||||||
|
|
||||||
macro_rules! generate_basetype_froms
|
|
||||||
{
|
|
||||||
($name: ident) => {
|
|
||||||
generate_basetype_from!($name, u8);
|
|
||||||
generate_basetype_from!($name, u16);
|
|
||||||
generate_basetype_from!($name, u32);
|
|
||||||
generate_basetype_from!($name, u64);
|
|
||||||
generate_basetype_from!($name, usize);
|
|
||||||
|
|
||||||
impl From<u128> for $name {
|
|
||||||
fn from(x: u128) -> $name {
|
|
||||||
let mut base = $name::zero();
|
|
||||||
base.values[0] = x as u64;
|
|
||||||
base.values[1] = (x >> 64) as u64;
|
|
||||||
base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BigUint> for $name {
|
|
||||||
fn from(mut x: BigUint) -> $name {
|
|
||||||
let mut res = $name::zero();
|
|
||||||
let mask = BigUint::from_u64(0xFFFFFFFFFFFFFFFF).unwrap();
|
|
||||||
|
|
||||||
for digit in res.values.iter_mut() {
|
|
||||||
*digit = (&x & &mask).to_u64().unwrap();
|
|
||||||
x >>= 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<$name> for BigUint {
|
|
||||||
fn from(x: $name) -> BigUint {
|
|
||||||
let bytes: Vec<u8> = x.to_bytes();
|
|
||||||
BigUint::from_bytes_be(&bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_basetype_from
|
|
||||||
{
|
|
||||||
($name: ident, $basetype: ident) => {
|
|
||||||
impl From<$basetype> for $name {
|
|
||||||
fn from(x: $basetype) -> $name {
|
|
||||||
let mut base = $name::zero();
|
|
||||||
base.values[0] = x as u64;
|
|
||||||
base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<$name> for $basetype {
|
|
||||||
fn from(x: $name) -> $basetype {
|
|
||||||
x.values[0] as $basetype
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_from_smaller
|
|
||||||
{
|
|
||||||
($name: ident, $smalltype: ident) => {
|
|
||||||
impl<'a> From<&'a $smalltype> for $name {
|
|
||||||
fn from(x: &$smalltype) -> $name {
|
|
||||||
let mut base = $name::zero();
|
|
||||||
for (idx, val) in x.values.iter().enumerate() {
|
|
||||||
base.values[idx] = *val;
|
|
||||||
}
|
|
||||||
base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<$smalltype> for $name {
|
|
||||||
fn from(x: $smalltype) -> $name {
|
|
||||||
let mut base = $name::zero();
|
|
||||||
for (idx, val) in x.values.iter().enumerate() {
|
|
||||||
base.values[idx] = *val;
|
|
||||||
}
|
|
||||||
base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_from_larger
|
|
||||||
{
|
|
||||||
($name: ident, $bigtype: ident) => {
|
|
||||||
impl<'a> From<&'a $bigtype> for $name {
|
|
||||||
fn from(x: &$bigtype) -> $name {
|
|
||||||
let mut base = $name::zero();
|
|
||||||
for i in 0..base.values.len() {
|
|
||||||
base.values[i] = x.values[i];
|
|
||||||
}
|
|
||||||
base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! convert_bignums
|
|
||||||
{
|
|
||||||
($smaller: ident, $bigger: ident) => {
|
|
||||||
convert_from_smaller!($bigger, $smaller);
|
|
||||||
convert_from_larger!($smaller, $bigger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! expand_bignums
|
|
||||||
{
|
|
||||||
($smaller: ident, $bigger: ident $(, $rest: ident)* ) => {
|
|
||||||
convert_bignums!($smaller, $bigger);
|
|
||||||
expand_bignums!($smaller, $($rest),*);
|
|
||||||
};
|
|
||||||
($smaller: ident, $(,)*) => {};
|
|
||||||
() => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! exhaustive_expansion
|
|
||||||
{
|
|
||||||
() => {};
|
|
||||||
($last: ident) => {
|
|
||||||
generate_basetype_froms!($last);
|
|
||||||
};
|
|
||||||
($smallest: ident $(, $other: ident)*) => {
|
|
||||||
generate_basetype_froms!($smallest);
|
|
||||||
expand_bignums!($smallest, $($other),*);
|
|
||||||
exhaustive_expansion!($($other),*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exhaustive_expansion!(U192, U256, U320, U384, U448, U512, U576,
|
|
||||||
U640, U768, U832, U896, U1024, U1088, U1152,
|
|
||||||
U1216, U1536, U1664, U2048, U2112, U2176, U2304,
|
|
||||||
U2432, U3072, U3136, U4096, U4224, U4160, U6144,
|
|
||||||
U6208, U7680, U7744, U8192, U8256, U8320, U12288,
|
|
||||||
U12416, U15360, U15424, U16384, U16448, U16512, U30720,
|
|
||||||
U30784, U32768, U32896, U61440, U61568);
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
|
|
||||||
pub trait ModReduce<T=Self> {
|
|
||||||
fn reduce(&self, value: &T) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! safesubidx
|
|
||||||
{
|
|
||||||
($array: expr, $index: expr, $amt: expr) => ({
|
|
||||||
let idx = $index;
|
|
||||||
let amt = $amt;
|
|
||||||
|
|
||||||
if idx < amt {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
$array[idx-amt]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_dividers
|
|
||||||
{
|
|
||||||
($name: ident, $bigger: ident) => {
|
|
||||||
impl $name {
|
|
||||||
// This is based on algorithm 14.20 from the Handbook of Applied
|
|
||||||
// Cryptography, slightly modified.
|
|
||||||
pub fn divmod(&self, rhs: &$name) -> ($name, $name) {
|
|
||||||
// if the divisor is larger, then the answer is pretty simple
|
|
||||||
if rhs > self {
|
|
||||||
return ($name::zero(), self.clone());
|
|
||||||
}
|
|
||||||
// compute the basic number sizes
|
|
||||||
let mut n = match get_number_size(&self.values) {
|
|
||||||
None => 0,
|
|
||||||
Some(v) => v
|
|
||||||
};
|
|
||||||
let t = match get_number_size(&rhs.values) {
|
|
||||||
None => panic!("Division by zero!"),
|
|
||||||
Some(v) => v
|
|
||||||
};
|
|
||||||
assert!(t <= n);
|
|
||||||
// now generate mutable versions we can mess with
|
|
||||||
let mut x = $bigger::from(self);
|
|
||||||
let mut y = $bigger::from(rhs);
|
|
||||||
// If we want this to perform reasonable, it's useful if the
|
|
||||||
// value of y[t] is shifted so that the high bit is set.
|
|
||||||
let lambda_shift = y.values[t].leading_zeros() as usize;
|
|
||||||
if lambda_shift != 0 {
|
|
||||||
shiftl(&mut x.values, lambda_shift);
|
|
||||||
shiftl(&mut y.values, lambda_shift);
|
|
||||||
n = get_number_size(&x.values).unwrap();
|
|
||||||
}
|
|
||||||
// now go!
|
|
||||||
// 1. For j from 0 to (n-t) do: q[j] = 0;
|
|
||||||
// [NB: I take some liberties with this concept]
|
|
||||||
let mut q = $bigger::zero();
|
|
||||||
// 2. While (x >= y * b^(n-t)) do the following:
|
|
||||||
let mut ybnt = $bigger::zero();
|
|
||||||
for i in 0..self.values.len() {
|
|
||||||
ybnt.values[(n-t)+i] = y.values[i];
|
|
||||||
if (n-t)+i >= ybnt.values.len() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while x > ybnt {
|
|
||||||
q.values[n - t] += 1;
|
|
||||||
x -= &ybnt;
|
|
||||||
}
|
|
||||||
// 3. For i from n down to t+1 do the following:
|
|
||||||
let mut i = n;
|
|
||||||
while i >= (t + 1) {
|
|
||||||
// 3.1. If x[i] = y[t]
|
|
||||||
if x.values[i] == y.values[t] {
|
|
||||||
// ... then set q[i-t-1] = b - 1
|
|
||||||
q.values[i-t-1] = 0xFFFFFFFFFFFFFFFF;
|
|
||||||
} else {
|
|
||||||
// ... otherwise set q[i-t-1] =
|
|
||||||
// floor((x[i] * b + x[i-1]) / y[t])
|
|
||||||
let xib = (x.values[i] as u128) << 64;
|
|
||||||
let xi1 = safesubidx!(x.values,i,1) as u128;
|
|
||||||
let yt = y.values[t] as u128;
|
|
||||||
let qit1 = (xib + xi1) / yt;
|
|
||||||
q.values[i-t-1] = qit1 as u64;
|
|
||||||
}
|
|
||||||
// 3.2. While q[i-t-1] * (y[t]*b + y[t-1]) >
|
|
||||||
// (x[i] * b^2 + x[i-1] * b + x[i-2])
|
|
||||||
loop {
|
|
||||||
// three is very close to 2.
|
|
||||||
let qit1 = U192::from(safesubidx!(q.values,i-t,1));
|
|
||||||
let mut ybits = U192::zero();
|
|
||||||
ybits.values[0] = safesubidx!(y.values, t, 1);
|
|
||||||
ybits.values[1] = y.values[t];
|
|
||||||
let qiybs = &qit1 * &ybits;
|
|
||||||
let mut xbits = U384::zero();
|
|
||||||
xbits.values[0] = safesubidx!(x.values,i,2);
|
|
||||||
xbits.values[1] = safesubidx!(x.values,i,1);
|
|
||||||
xbits.values[2] = x.values[i];
|
|
||||||
|
|
||||||
if !(&qiybs > &xbits) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... do q[i-t-1] = q[i-t-1] - 1
|
|
||||||
q.values[i-t-1] -= 1;
|
|
||||||
}
|
|
||||||
// 3.3. x = x - q[i-t-1] * y * b^(i-t-1)
|
|
||||||
// 3.4. If x < 0
|
|
||||||
// then set x = x + y * b^(i-t-1) and
|
|
||||||
// q[i-t-1] = q[i-t-1] - 1
|
|
||||||
let mut qbit1 = $name::zero();
|
|
||||||
qbit1.values[i-t-1] = q.values[i-t-1];
|
|
||||||
let smallery = $name::from(&y);
|
|
||||||
let mut subpart = &smallery * &qbit1;
|
|
||||||
if subpart > x {
|
|
||||||
let mut addback = $bigger::zero();
|
|
||||||
for (idx, val) in y.values.iter().enumerate() {
|
|
||||||
let dest = idx + (i - t - 1);
|
|
||||||
if dest < addback.values.len() {
|
|
||||||
addback.values[dest] = *val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
q.values[i-t-1] -= 1;
|
|
||||||
subpart -= &addback;
|
|
||||||
}
|
|
||||||
assert!(subpart <= x);
|
|
||||||
x -= &subpart;
|
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
// 4. r = x ... sort of. Remember, we potentially did a bit of shifting
|
|
||||||
// around at the very beginning, which we now need to account for. On the
|
|
||||||
// bright side, we only need to account for this in the remainder.
|
|
||||||
let mut r = $name::from(&x);
|
|
||||||
shiftr(&mut r.values, lambda_shift);
|
|
||||||
// 5. Return (q,r)
|
|
||||||
let resq = $name::from(&q);
|
|
||||||
(resq, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModReduce for $name {
|
|
||||||
fn reduce(&self, value: &$name) -> $name {
|
|
||||||
let (_, res) = self.divmod(value);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn shiftl(x: &mut [u64], amt: usize)
|
|
||||||
{
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
for v in x.iter_mut() {
|
|
||||||
let new_carry = *v >> (64 - amt);
|
|
||||||
*v = (*v << amt) | carry;
|
|
||||||
carry = new_carry;
|
|
||||||
}
|
|
||||||
assert!(carry == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn shiftr(x: &mut [u64], amt: usize)
|
|
||||||
{
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
for val in x.iter_mut().rev() {
|
|
||||||
let mask = !(0xFFFFFFFFFFFFFFFF << amt);
|
|
||||||
let newcarry = *val & mask;
|
|
||||||
*val = (*val >> amt) | carry;
|
|
||||||
carry = newcarry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_number_size(v: &[u64]) -> Option<usize>
|
|
||||||
{
|
|
||||||
for (idx, val) in v.iter().enumerate().rev() {
|
|
||||||
if *val != 0 {
|
|
||||||
return Some(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_dividers!(U192, U384);
|
|
||||||
generate_dividers!(U256, U512);
|
|
||||||
generate_dividers!(U384, U768);
|
|
||||||
generate_dividers!(U448, U896);
|
|
||||||
generate_dividers!(U512, U1024);
|
|
||||||
generate_dividers!(U576, U1152);
|
|
||||||
generate_dividers!(U768, U1536);
|
|
||||||
generate_dividers!(U832, U1664);
|
|
||||||
generate_dividers!(U1024, U2048);
|
|
||||||
generate_dividers!(U1088, U2176);
|
|
||||||
generate_dividers!(U1152, U2304);
|
|
||||||
generate_dividers!(U1216, U2432);
|
|
||||||
generate_dividers!(U2048, U4096);
|
|
||||||
generate_dividers!(U2112, U4224);
|
|
||||||
generate_dividers!(U3072, U6144);
|
|
||||||
generate_dividers!(U4096, U8192);
|
|
||||||
generate_dividers!(U4160, U8320);
|
|
||||||
generate_dividers!(U6144, U12288);
|
|
||||||
generate_dividers!(U6208, U12416);
|
|
||||||
generate_dividers!(U7680, U15360);
|
|
||||||
generate_dividers!(U8192, U16384);
|
|
||||||
generate_dividers!(U8256, U16512);
|
|
||||||
generate_dividers!(U15360, U30720);
|
|
||||||
generate_dividers!(U16384, U32768);
|
|
||||||
generate_dividers!(U16448, U32896);
|
|
||||||
generate_dividers!(U30720, U61440);
|
|
||||||
generate_dividers!(U30784, U61568);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod normal {
|
|
||||||
use testing::run_test;
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use cryptonum::{U192,U256,U384,U512,U576,U1024,
|
|
||||||
U2048,U3072,U4096,U8192,U15360};
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
($name: ident) => (
|
|
||||||
#[cfg(test)]
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/division{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 4, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, qbytes) = case.get("q").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
|
||||||
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let q = $name::from_bytes(qbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let (myq, myr) = a.divmod(&b);
|
|
||||||
assert_eq!(q, myq);
|
|
||||||
assert_eq!(r, myr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!(U192);
|
|
||||||
generate_tests!(U256);
|
|
||||||
generate_tests!(U384);
|
|
||||||
generate_tests!(U512);
|
|
||||||
generate_tests!(U576);
|
|
||||||
generate_tests!(U1024);
|
|
||||||
generate_tests!(U2048);
|
|
||||||
generate_tests!(U3072);
|
|
||||||
generate_tests!(U4096);
|
|
||||||
generate_tests!(U8192);
|
|
||||||
generate_tests!(U15360);
|
|
||||||
}
|
|
||||||
@@ -1,224 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
|
|
||||||
pub trait Decoder {
|
|
||||||
fn from_bytes(x: &[u8]) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Encoder {
|
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn raw_decoder(input: &[u8], output: &mut [u64])
|
|
||||||
{
|
|
||||||
let mut item = 0;
|
|
||||||
let mut shift = 0;
|
|
||||||
let mut idx = 0;
|
|
||||||
|
|
||||||
for v in input.iter().rev() {
|
|
||||||
item |= (*v as u64) << shift;
|
|
||||||
shift += 8;
|
|
||||||
if shift == 64 {
|
|
||||||
shift = 0;
|
|
||||||
output[idx] = item;
|
|
||||||
idx += 1;
|
|
||||||
item = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if item != 0 {
|
|
||||||
output[idx] = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_decoder {
|
|
||||||
($name: ident) => {
|
|
||||||
impl Decoder for $name {
|
|
||||||
fn from_bytes(x: &[u8]) -> $name {
|
|
||||||
let mut res = $name::zero();
|
|
||||||
raw_decoder(x, &mut res.values);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_encoder {
|
|
||||||
($name: ident) => {
|
|
||||||
impl Encoder for $name {
|
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
let mut res = Vec::with_capacity(self.values.len() * 8);
|
|
||||||
for v in self.values.iter().rev() {
|
|
||||||
let val = *v;
|
|
||||||
res.push( (val >> 56) as u8);
|
|
||||||
res.push( (val >> 48) as u8);
|
|
||||||
res.push( (val >> 40) as u8);
|
|
||||||
res.push( (val >> 32) as u8);
|
|
||||||
res.push( (val >> 24) as u8);
|
|
||||||
res.push( (val >> 16) as u8);
|
|
||||||
res.push( (val >> 8) as u8);
|
|
||||||
res.push( (val >> 0) as u8);
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_codec
|
|
||||||
{
|
|
||||||
($name: ident) => {
|
|
||||||
generate_decoder!($name);
|
|
||||||
generate_encoder!($name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_codec!(U192);
|
|
||||||
generate_codec!(U256);
|
|
||||||
generate_codec!(U320); // this is just for expansion
|
|
||||||
generate_codec!(U384);
|
|
||||||
generate_codec!(U448); // this is just for expansion
|
|
||||||
generate_codec!(U512);
|
|
||||||
generate_codec!(U576);
|
|
||||||
generate_codec!(U640); // this is just for expansion
|
|
||||||
generate_codec!(U768); // this is just for expansion
|
|
||||||
generate_codec!(U832); // this is just for expansion
|
|
||||||
generate_codec!(U896); // this is just for expansion
|
|
||||||
generate_codec!(U1024);
|
|
||||||
generate_codec!(U1088); // this is just for expansion
|
|
||||||
generate_codec!(U1152); // this is just for expansion
|
|
||||||
generate_codec!(U1216); // this is just for expansion
|
|
||||||
generate_codec!(U1536); // this is just for expansion
|
|
||||||
generate_codec!(U1664); // this is just for expansion
|
|
||||||
generate_codec!(U2048);
|
|
||||||
generate_codec!(U2112); // this is just for expansion
|
|
||||||
generate_codec!(U2176); // this is just for expansion
|
|
||||||
generate_codec!(U2304); // this is just for expansion
|
|
||||||
generate_codec!(U2432); // this is just for expansion
|
|
||||||
generate_codec!(U3072);
|
|
||||||
generate_codec!(U3136); // this is just for expansion
|
|
||||||
generate_codec!(U4224); // this is just for expansion
|
|
||||||
generate_codec!(U4096);
|
|
||||||
generate_codec!(U4160); // this is just for expansion
|
|
||||||
generate_codec!(U6144); // this is just for expansion
|
|
||||||
generate_codec!(U6208); // this is just for expansion
|
|
||||||
generate_codec!(U7680);
|
|
||||||
generate_codec!(U7744);
|
|
||||||
generate_codec!(U8192);
|
|
||||||
generate_codec!(U8256); // this is just for expansion
|
|
||||||
generate_codec!(U8320); // this is just for expansion
|
|
||||||
generate_codec!(U12288); // this is just for expansion
|
|
||||||
generate_codec!(U12416); // this is just for expansion
|
|
||||||
generate_codec!(U15360);
|
|
||||||
generate_codec!(U15424); // this is just for expansion
|
|
||||||
generate_codec!(U16384); // this is just for expansion
|
|
||||||
generate_codec!(U16448); // this is just for expansion
|
|
||||||
generate_codec!(U16512); // this is just for expansion
|
|
||||||
generate_codec!(U30720); // this is just for expansion
|
|
||||||
generate_codec!(U30784); // this is just for expansion
|
|
||||||
generate_codec!(U32768); // this is just for expansion
|
|
||||||
generate_codec!(U32896); // this is just for expansion
|
|
||||||
generate_codec!(U61440); // this is just for expansion
|
|
||||||
generate_codec!(U61568); // this is just for expansion
|
|
||||||
|
|
||||||
macro_rules! generate_tests
|
|
||||||
{
|
|
||||||
( $( ($name: ident, $num: ident, $size: expr) ),* ) => {
|
|
||||||
$(
|
|
||||||
#[cfg(test)]
|
|
||||||
mod $name {
|
|
||||||
use cryptonum::basetypes::{CryptoNum,$num};
|
|
||||||
use cryptonum::encoding::{Decoder,Encoder};
|
|
||||||
use quickcheck::{Arbitrary,Gen};
|
|
||||||
|
|
||||||
#[derive(Clone,Debug)]
|
|
||||||
struct MyBuffer {
|
|
||||||
x: Vec<u8>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Arbitrary for $num {
|
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> $num {
|
|
||||||
let mut res = $num::zero();
|
|
||||||
|
|
||||||
for v in res.values.iter_mut() {
|
|
||||||
*v = g.gen::<u64>();
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Arbitrary for MyBuffer {
|
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> MyBuffer {
|
|
||||||
let len = $size / 8;
|
|
||||||
let mut res = Vec::with_capacity(len);
|
|
||||||
|
|
||||||
for _ in 0..len {
|
|
||||||
res.push(g.gen::<u8>());
|
|
||||||
}
|
|
||||||
MyBuffer{ x: res }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn i2o2i(x: $num) -> bool {
|
|
||||||
let bstr = x.to_bytes();
|
|
||||||
let x2 = $num::from_bytes(&bstr);
|
|
||||||
x == x2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn o2i2o(x: MyBuffer) -> bool {
|
|
||||||
let val = $num::from_bytes(&x.x);
|
|
||||||
let x2 = val.to_bytes();
|
|
||||||
x.x == x2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((u192, U192, 192),
|
|
||||||
(u256, U256, 256),
|
|
||||||
(u320, U320, 320), // this is just for expansion
|
|
||||||
(u384, U384, 384),
|
|
||||||
(u448, U448, 448), // this is just for expansion
|
|
||||||
(u512, U512, 512),
|
|
||||||
(u576, U576, 576),
|
|
||||||
(u640, U640, 640), // this is just for expansion
|
|
||||||
(u768, U768, 768), // this is just for expansion
|
|
||||||
(u832, U832, 832), // this is just for Barrett
|
|
||||||
(u896, U896, 896), // this is just for Barrett
|
|
||||||
(u1024, U1024, 1024),
|
|
||||||
(u1088, U1088, 1088), // this is just for expansion
|
|
||||||
(u1152, U1152, 1152), // this is just for expansion
|
|
||||||
(u1216, U1216, 1216), // this is just for Barrett
|
|
||||||
(u1536, U1536, 1536), // this is just for expansion
|
|
||||||
(u1664, U1664, 1664), // this is just for Barrett
|
|
||||||
(u2048, U2048, 2048),
|
|
||||||
(u2112, U2112, 2112), // this is just for expansion
|
|
||||||
(u2176, U2176, 2176), // this is just for Barrett
|
|
||||||
(u2304, U2304, 2304), // this is just for expansion
|
|
||||||
(u2432, U2432, 2432), // this is just for Barrett
|
|
||||||
(u3072, U3072, 3072),
|
|
||||||
(u3136, U3136, 3136), // this is just for expansion
|
|
||||||
(u4096, U4096, 4096),
|
|
||||||
(u4160, U4160, 4160), // this is just for expansion
|
|
||||||
(u4224, U4224, 4224), // this is just for Barrett
|
|
||||||
(u6144, U6144, 6144), // this is just for expansion
|
|
||||||
(u6208, U6208, 6208), // this is just for Barrett
|
|
||||||
(u7680, U7680, 7680),
|
|
||||||
(u7744, U7744, 7744),
|
|
||||||
(u8192, U8192, 8192),
|
|
||||||
(u8256, U8256, 8256), // this is just for expansion
|
|
||||||
(u8320, U8320, 8320), // this is just for Barrett
|
|
||||||
(u12288, U12288, 12288), // this is just for expansion
|
|
||||||
(u12416, U12416, 12416), // this is just for Barrett
|
|
||||||
(u15360, U15360, 15360),
|
|
||||||
(u15424, U15424, 15424), // this is just for expansion
|
|
||||||
(u16384, U16384, 16384), // this is just for expansion
|
|
||||||
(u16448, U16448, 16448), // this is just for Barrett
|
|
||||||
(u16512, U16512, 16512), // this is just for Barrett
|
|
||||||
(u30720, U30720, 30720), // this is just for expansion
|
|
||||||
(u30784, U30784, 30784), // this is just for Barrett
|
|
||||||
(u32768, U32768, 32768), // this is just for expansion
|
|
||||||
(u32896, U32896, 32896), // this is just for Barrett
|
|
||||||
(u61440, U61440, 61440), // this is just for expansion
|
|
||||||
(u61568, U61568, 61568)); // this is just for Barrett
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
//! # Simple-Crypto CryptoNum
|
|
||||||
//!
|
|
||||||
//! This module is designed to provide large, fixed-width number support for
|
|
||||||
//! the rest of the Simple-Crypto libraries. Feel free to use it other places,
|
|
||||||
//! of course, but that's its origin.
|
|
||||||
//!
|
|
||||||
mod addition;
|
|
||||||
mod barrett;
|
|
||||||
mod basetypes;
|
|
||||||
mod comparison;
|
|
||||||
mod conversions;
|
|
||||||
mod division;
|
|
||||||
mod encoding;
|
|
||||||
mod modmath;
|
|
||||||
mod multiplication;
|
|
||||||
mod shifts;
|
|
||||||
mod signed;
|
|
||||||
mod squaring;
|
|
||||||
mod subtraction;
|
|
||||||
|
|
||||||
pub use self::barrett::*;
|
|
||||||
pub use self::basetypes::*;
|
|
||||||
pub use self::encoding::{Decoder,Encoder};
|
|
||||||
pub use self::signed::Signed;
|
|
||||||
#[allow(unused)]
|
|
||||||
pub(crate) use self::modmath::{ModExp,ModInv};
|
|
||||||
@@ -1,543 +0,0 @@
|
|||||||
use cryptonum::addition::UnsafeAdd;
|
|
||||||
use cryptonum::basetypes::*;
|
|
||||||
use cryptonum::barrett::*;
|
|
||||||
use cryptonum::signed::*;
|
|
||||||
|
|
||||||
pub trait ModAdd<T2> {
|
|
||||||
fn modadd(&mut self, y: &Self, m: &T2);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ModMul<T> {
|
|
||||||
fn modmul(&mut self, x: &Self, m: &T);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ModSquare<T> {
|
|
||||||
fn modsq(&mut self, m: &T);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ModExp<T> {
|
|
||||||
fn modexp(&self, e: &Self, m: &T) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ModInv
|
|
||||||
where Self: Sized
|
|
||||||
{
|
|
||||||
fn modinv(&self, phi: Self) -> Option<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_modmath_funs
|
|
||||||
{
|
|
||||||
($name: ident, $big: ident, $dbl: ident, $bar: ident, $size: expr) => {
|
|
||||||
impl ModAdd<$big> for $name {
|
|
||||||
fn modadd(&mut self, y: &$name, m: &$big) {
|
|
||||||
let mut base = &self.clone() + y;
|
|
||||||
if &base > m {
|
|
||||||
base -= m;
|
|
||||||
if &base > m {
|
|
||||||
base -= m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.values.copy_from_slice(&base.values[0..$size/64]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModMul<$name> for $name {
|
|
||||||
fn modmul(&mut self, x: &$name, m: &$name) {
|
|
||||||
let mulres = (self as &$name) * &x;
|
|
||||||
let bigm = $dbl::from(m);
|
|
||||||
let (_, bigres) = mulres.divmod(&bigm);
|
|
||||||
self.values.copy_from_slice(&bigres.values[0..$size/64]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModMul<$bar> for $name {
|
|
||||||
fn modmul(&mut self, x: &$name, m: &$bar) {
|
|
||||||
let mut mulres = (self as &$name) * &x;
|
|
||||||
let bigres = m.reduce(&mut mulres);
|
|
||||||
self.values.copy_from_slice(&bigres.values[0..$size/64]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModSquare<$name> for $name {
|
|
||||||
fn modsq(&mut self, m: &$name) {
|
|
||||||
let bigsquare = self.square();
|
|
||||||
let bigm = $dbl::from(m);
|
|
||||||
let (_, res) = bigsquare.divmod(&bigm);
|
|
||||||
self.values.copy_from_slice(&res.values[0..$size/64]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModSquare<$bar> for $name {
|
|
||||||
fn modsq(&mut self, m: &$bar) {
|
|
||||||
let bigsquare = self.square();
|
|
||||||
let bigres = m.reduce(&bigsquare);
|
|
||||||
self.values.copy_from_slice(&bigres.values[0..$size/64]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ModExp<T> for $name
|
|
||||||
where $name: ModMul<T> + ModSquare<T>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn modexp(&self, ine: &$name, m: &T) -> $name {
|
|
||||||
// S <- g
|
|
||||||
let mut s = self.clone();
|
|
||||||
// A <- 1
|
|
||||||
let mut a = $name::from(1u64);
|
|
||||||
// We do a quick skim through and find the highest index that
|
|
||||||
// actually has a value in it.
|
|
||||||
let mut e = ine.clone();
|
|
||||||
// While e != 0 do the following:
|
|
||||||
while e.values.iter().any(|x| *x != 0) {
|
|
||||||
// If e is odd then A <- A * S
|
|
||||||
if e.values[0] & 1 != 0 {
|
|
||||||
a.modmul(&s, m);
|
|
||||||
}
|
|
||||||
// e <- floor(e / 2)
|
|
||||||
let mut carry = 0;
|
|
||||||
e.values.iter_mut().rev().for_each(|x| {
|
|
||||||
let new_carry = *x & 1;
|
|
||||||
*x = (*x >> 1) | (carry << 63);
|
|
||||||
carry = new_carry;
|
|
||||||
});
|
|
||||||
// If e != 0 then S <- S * S
|
|
||||||
s.modsq(m);
|
|
||||||
}
|
|
||||||
// Return A
|
|
||||||
a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModInv for $name {
|
|
||||||
fn modinv(&self, phi: $name)
|
|
||||||
-> Option<$name>
|
|
||||||
{
|
|
||||||
let (_, _d, v) = self.egcd(phi);
|
|
||||||
|
|
||||||
if v != Signed::new(false, $name::from(1u64)) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
panic!("modinv stuff")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $name {
|
|
||||||
fn egcd(&self, rhs: $name)
|
|
||||||
-> (Signed<$name>, Signed<$name>, Signed<$name>)
|
|
||||||
{
|
|
||||||
println!("---------------------------------------------------");
|
|
||||||
// INPUT: two positive integers x and y.
|
|
||||||
let mut x = Signed::new(false, self.clone());
|
|
||||||
let mut y = Signed::new(false, rhs);
|
|
||||||
// OUTPUT: integers a, b, and v such that ax + by = v,
|
|
||||||
// where v = gcd(x, y).
|
|
||||||
// 1. g←1.
|
|
||||||
let mut gshift = 0;
|
|
||||||
// 2. While x and y are both even, do the following: x←x/2,
|
|
||||||
// y←y/2, g←2g.
|
|
||||||
while x.is_even() && y.is_even() {
|
|
||||||
x >>= 1;
|
|
||||||
y >>= 1;
|
|
||||||
gshift += 1;
|
|
||||||
}
|
|
||||||
// 3. u←x, v←y, A←1, B←0, C←0, D←1.
|
|
||||||
let mut u: Signed<$name> = x.clone();
|
|
||||||
let mut v: Signed<$name> = y.clone();
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let mut A: Signed<$name> = Signed::new(false, $name::from(1u64));
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let mut B: Signed<$name> = Signed::new(false, $name::zero());
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let mut C: Signed<$name> = Signed::new(false, $name::zero());
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let mut D: Signed<$name> = Signed::new(false, $name::from(1u64));
|
|
||||||
loop {
|
|
||||||
println!("START");
|
|
||||||
println!("u: {}{:X}", pos_space(&u), u);
|
|
||||||
println!("v: {}{:X}", pos_space(&v), v);
|
|
||||||
println!("A: {}{:X}", pos_space(&A), A);
|
|
||||||
println!("B: {}{:X}", pos_space(&B), B);
|
|
||||||
println!("C: {}{:X}", pos_space(&C), C);
|
|
||||||
println!("D: {}{:X}", pos_space(&D), D);
|
|
||||||
// 4. While u is even do the following:
|
|
||||||
while u.is_even() {
|
|
||||||
// 4.1 u←u/2.
|
|
||||||
u >>= 1;
|
|
||||||
// 4.2 If A≡B≡0 (mod 2) then A←A/2, B←B/2; otherwise,
|
|
||||||
// A←(A + y)/2, B←(B − x)/2.
|
|
||||||
if A.is_even() && B.is_even() {
|
|
||||||
A >>= 1;
|
|
||||||
B >>= 1;
|
|
||||||
} else {
|
|
||||||
let mut big_A: Signed<$big> = &A + &y;
|
|
||||||
big_A >>= 1;
|
|
||||||
A = Signed::new(big_A.negative, $name::from(&big_A.value));
|
|
||||||
B -= &x;
|
|
||||||
B >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("AFTER 4");
|
|
||||||
println!("u: {}{:X}", pos_space(&u), u);
|
|
||||||
println!("v: {}{:X}", pos_space(&v), v);
|
|
||||||
println!("A: {}{:X}", pos_space(&A), A);
|
|
||||||
println!("B: {}{:X}", pos_space(&B), B);
|
|
||||||
println!("C: {}{:X}", pos_space(&C), C);
|
|
||||||
println!("D: {}{:X}", pos_space(&D), D);
|
|
||||||
// 5. While v is even do the following:
|
|
||||||
while v.is_even() {
|
|
||||||
// 5.1 v←v/2.
|
|
||||||
v >>= 1;
|
|
||||||
// 5.2 If C ≡ D ≡ 0 (mod 2) then C←C/2, D←D/2; otherwise,
|
|
||||||
// C←(C + y)/2, D←(D − x)/2.
|
|
||||||
if C.is_even() && D.is_even() {
|
|
||||||
C >>= 1;
|
|
||||||
D >>= 1;
|
|
||||||
} else {
|
|
||||||
C = C.unsafe_add(&y);
|
|
||||||
C >>= 1;
|
|
||||||
D -= &x;
|
|
||||||
D >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("AFTER 5");
|
|
||||||
println!("u: {}{:X}", pos_space(&u), u);
|
|
||||||
println!("v: {}{:X}", pos_space(&v), v);
|
|
||||||
println!("A: {}{:X}", pos_space(&A), A);
|
|
||||||
println!("B: {}{:X}", pos_space(&B), B);
|
|
||||||
println!("C: {}{:X}", pos_space(&C), C);
|
|
||||||
println!("D: {}{:X}", pos_space(&D), D);
|
|
||||||
// 6. If u≥v then u←u−v, A←A−C,B←B−D;
|
|
||||||
// otherwise,v←v−u, C←C−A, D←D−B.
|
|
||||||
if u >= v {
|
|
||||||
u -= &v;
|
|
||||||
A -= &C;
|
|
||||||
B -= &D;
|
|
||||||
} else {
|
|
||||||
v -= &u;
|
|
||||||
C -= &A;
|
|
||||||
D -= &B;
|
|
||||||
}
|
|
||||||
// 7. If u = 0, then a←C, b←D, and return(a, b, g · v);
|
|
||||||
// otherwise, go to step 4.
|
|
||||||
println!("AFTER 6");
|
|
||||||
println!("u: {}{:X}", pos_space(&u), u);
|
|
||||||
println!("v: {}{:X}", pos_space(&v), v);
|
|
||||||
println!("A': {}{:X}", pos_space(&A), A);
|
|
||||||
println!("B': {}{:X}", pos_space(&B), B);
|
|
||||||
println!("C': {}{:X}", pos_space(&C), C);
|
|
||||||
println!("D': {}{:X}", pos_space(&D), D);
|
|
||||||
if u.is_zero() {
|
|
||||||
return (C, D, v << gshift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_modmath_funs!(U192, U256, U384, BarrettU192, 192);
|
|
||||||
generate_modmath_funs!(U256, U320, U512, BarrettU256, 256);
|
|
||||||
generate_modmath_funs!(U384, U448, U768, BarrettU384, 384);
|
|
||||||
generate_modmath_funs!(U512, U576, U1024, BarrettU512, 512);
|
|
||||||
generate_modmath_funs!(U1024, U1088, U2048, BarrettU1024, 1024);
|
|
||||||
generate_modmath_funs!(U2048, U2112, U4096, BarrettU2048, 2048);
|
|
||||||
generate_modmath_funs!(U3072, U3136, U6144, BarrettU3072, 3072);
|
|
||||||
generate_modmath_funs!(U4096, U4160, U8192, BarrettU4096, 4096);
|
|
||||||
generate_modmath_funs!(U8192, U8256, U16384, BarrettU8192, 8192);
|
|
||||||
generate_modmath_funs!(U15360, U15424, U30720, BarrettU15360, 15360);
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( ($name:ident, $barrett: ident, $bigger: ident, $dbl: ident) ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod addition {
|
|
||||||
use cryptonum::encoding::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modadd{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 4, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, cbytes) = case.get("c").unwrap();
|
|
||||||
let (neg3, mbytes) = case.get("m").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let m = $bigger::from_bytes(mbytes);
|
|
||||||
let c = $name::from_bytes(cbytes);
|
|
||||||
a.modadd(&b, &m);
|
|
||||||
assert_eq!(a, c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod multiplication {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modmul{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 4, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, cbytes) = case.get("c").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1 && !neg2 && !neg3);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let m = $name::from_bytes(mbytes);
|
|
||||||
let c = $name::from_bytes(cbytes);
|
|
||||||
a.modmul(&b, &m);
|
|
||||||
assert_eq!(a, c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod barrett_multiplication {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/barrett_mul{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 6, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
let (neg4, kbytes) = case.get("k").unwrap();
|
|
||||||
let (neg5, ubytes) = case.get("u").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let m = $bigger::from_bytes(mbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let k = $name::from_bytes(kbytes);
|
|
||||||
let u = $bigger::from_bytes(ubytes);
|
|
||||||
let mu = $barrett{ k: k.values[0] as usize, m:m, mu:u };
|
|
||||||
a.modmul(&b, &mu);
|
|
||||||
assert_eq!(a, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod modsq {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modsq{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 5, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0&&!neg2&&!neg3);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let m = $name::from_bytes(mbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
a.modsq(&m);
|
|
||||||
assert_eq!(a, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod barrett_squaring {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modsq{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 5, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
let (neg4, kbytes) = case.get("k").unwrap();
|
|
||||||
let (neg5, ubytes) = case.get("u").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0&&!neg2&&!neg3&&!neg4&&!neg5);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let m = $bigger::from_bytes(mbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let k = $name::from_bytes(kbytes);
|
|
||||||
let u = $bigger::from_bytes(ubytes);
|
|
||||||
let mu = $barrett{ k: k.values[0] as usize, m:m, mu:u };
|
|
||||||
a.modsq(&mu);
|
|
||||||
assert_eq!(a, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod modexp {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[ignore]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modexp{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 6, |case| {
|
|
||||||
let (neg0, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg1, ebytes) = case.get("e").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0&&!neg1&&!neg2&&!neg3);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let e = $name::from_bytes(ebytes);
|
|
||||||
let m = $name::from_bytes(mbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let me = b.modexp(&e, &m);
|
|
||||||
assert_eq!(me, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod barrett_exponentiation {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/modexp{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 6, |case| {
|
|
||||||
let (neg0, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg1, ebytes) = case.get("e").unwrap();
|
|
||||||
let (neg2, mbytes) = case.get("m").unwrap();
|
|
||||||
let (neg3, rbytes) = case.get("r").unwrap();
|
|
||||||
let (neg4, kbytes) = case.get("k").unwrap();
|
|
||||||
let (neg5, ubytes) = case.get("u").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let e = $name::from_bytes(ebytes);
|
|
||||||
let m = $bigger::from_bytes(mbytes);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
let k = $name::from_bytes(kbytes);
|
|
||||||
let u = $bigger::from_bytes(ubytes);
|
|
||||||
let mu = $barrett{ k: k.values[0] as usize, m:m, mu:u };
|
|
||||||
let me = b.modexp(&e, &mu);
|
|
||||||
assert_eq!(me, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod egcd {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/egcd{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (nega, abytes) = case.get("a").unwrap();
|
|
||||||
let (negb, bbytes) = case.get("b").unwrap();
|
|
||||||
let (negg, gbytes) = case.get("g").unwrap();
|
|
||||||
|
|
||||||
assert!(!nega && !negb);
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let ug = $dbl::from_bytes(gbytes);
|
|
||||||
let g = Signed::new(*negg, ug.clone());
|
|
||||||
|
|
||||||
let (mys, myt, myg) = a.egcd(b.clone());
|
|
||||||
let mybigg = Signed::new(g.negative, $dbl::from(&myg.value));
|
|
||||||
println!("mybigg: {}{:X}", pos_space(&mybigg), mybigg.value);
|
|
||||||
println!("g : {}{:X}", pos_space(&g), g.value);
|
|
||||||
assert_eq!(mybigg, g);
|
|
||||||
let part1: $dbl = &mys.value * &a;
|
|
||||||
let part2: $dbl = &myt.value * &b;
|
|
||||||
let mut spart1 = Signed::new(mys.negative, part1);
|
|
||||||
let spart2 = Signed::new(myt.negative, part2);
|
|
||||||
spart1 -= &spart2;
|
|
||||||
println!("spart1: {}{:X}", pos_space(&spart1), spart1);
|
|
||||||
println!("spart1: {}{:X}", pos_space(&spart2), spart2);
|
|
||||||
assert_eq!(spart1, g);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((U192, BarrettU192, U256, U384),
|
|
||||||
(U256, BarrettU256, U320, U512),
|
|
||||||
(U384, BarrettU384, U448, U768),
|
|
||||||
(U512, BarrettU512, U576, U1024),
|
|
||||||
(U1024, BarrettU1024, U1088, U2048),
|
|
||||||
(U2048, BarrettU2048, U2112, U4096),
|
|
||||||
(U3072, BarrettU3072, U3136, U6144),
|
|
||||||
(U4096, BarrettU4096, U4160, U8192),
|
|
||||||
(U8192, BarrettU8192, U8256, U16384),
|
|
||||||
(U15360, BarrettU15360, U15424, U30720));
|
|
||||||
|
|
||||||
//generate_tests!((U192, I192, BarrettU192, U256),
|
|
||||||
// (U256, I256, BarrettU256, U320),
|
|
||||||
// (U384, I384, BarrettU384, U448),
|
|
||||||
// (U512, I512, BarrettU512, U576),
|
|
||||||
// (U1024, I1024, BarrettU1024, U1088),
|
|
||||||
// (U2048, I2048, BarrettU2048, U2112),
|
|
||||||
// (U3072, I3072, BarrettU3072, U3136),
|
|
||||||
// (U4096, I4096, BarrettU4096, U4160),
|
|
||||||
// (U8192, I8192, BarrettU8192, U8256),
|
|
||||||
// (U15360, I15360, BarrettU15360, U15424));
|
|
||||||
fn pos_space<T>(x: &Signed<T>) -> &'static str {
|
|
||||||
if !x.negative {
|
|
||||||
return " ";
|
|
||||||
}
|
|
||||||
""
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::ops::Mul;
|
|
||||||
|
|
||||||
macro_rules! generate_multipliers
|
|
||||||
{
|
|
||||||
($name: ident, $bigger: ident, $size: expr) => {
|
|
||||||
impl<'a,'b> Mul<&'a $name> for &'b $name {
|
|
||||||
type Output = $bigger;
|
|
||||||
|
|
||||||
fn mul(self, rhs: &$name) -> $bigger {
|
|
||||||
let mut w = $bigger::zero();
|
|
||||||
let len = $size/64;
|
|
||||||
|
|
||||||
for i in 0..len {
|
|
||||||
let mut carry = 0;
|
|
||||||
for j in 0..len {
|
|
||||||
let old = w.values[i+j] as u128;
|
|
||||||
let x128 = self.values[j] as u128;
|
|
||||||
let y128 = rhs.values[i] as u128;
|
|
||||||
let uv = old + (x128 * y128) + carry;
|
|
||||||
w.values[i+j] = uv as u64;
|
|
||||||
carry = uv >> 64;
|
|
||||||
}
|
|
||||||
w.values[i+len] = carry as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
w
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_multipliers!(U192, U384, 192);
|
|
||||||
generate_multipliers!(U256, U512, 256);
|
|
||||||
generate_multipliers!(U384, U768, 384);
|
|
||||||
generate_multipliers!(U448, U896, 448);
|
|
||||||
generate_multipliers!(U512, U1024, 512);
|
|
||||||
generate_multipliers!(U576, U1152, 576);
|
|
||||||
generate_multipliers!(U768, U1536, 768);
|
|
||||||
generate_multipliers!(U832, U1664, 832);
|
|
||||||
generate_multipliers!(U1024, U2048, 1024);
|
|
||||||
generate_multipliers!(U1088, U2176, 1088);
|
|
||||||
generate_multipliers!(U1152, U2304, 1152);
|
|
||||||
generate_multipliers!(U1216, U2432, 1216);
|
|
||||||
generate_multipliers!(U1536, U3072, 1536);
|
|
||||||
generate_multipliers!(U2048, U4096, 2048);
|
|
||||||
generate_multipliers!(U2112, U4224, 2112);
|
|
||||||
generate_multipliers!(U3072, U6144, 3072);
|
|
||||||
generate_multipliers!(U4096, U8192, 4096);
|
|
||||||
generate_multipliers!(U4160, U8320, 4160);
|
|
||||||
generate_multipliers!(U6144, U12288, 6144);
|
|
||||||
generate_multipliers!(U6208, U12416, 6208);
|
|
||||||
generate_multipliers!(U7680, U15360, 7680);
|
|
||||||
generate_multipliers!(U8192, U16384, 8192);
|
|
||||||
generate_multipliers!(U8256, U16512, 8256);
|
|
||||||
generate_multipliers!(U15360, U30720, 15360);
|
|
||||||
generate_multipliers!(U16384, U32768, 16384);
|
|
||||||
generate_multipliers!(U16448, U32896, 16448);
|
|
||||||
generate_multipliers!(U30720, U61440, 30720);
|
|
||||||
generate_multipliers!(U30784, U61568, 30784);
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( ($name:ident, $bigger:ident) ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod normal {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/multiplication{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, cbytes) = case.get("c").unwrap();
|
|
||||||
assert!(!neg0 && !neg1 && !neg2);
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let c = $bigger::from_bytes(cbytes);
|
|
||||||
assert_eq!(&a * &b, c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((U192, U384),
|
|
||||||
(U256, U512),
|
|
||||||
(U384, U768),
|
|
||||||
(U512, U1024),
|
|
||||||
(U576, U1152),
|
|
||||||
(U1024, U2048),
|
|
||||||
(U2048, U4096),
|
|
||||||
(U3072, U6144),
|
|
||||||
(U4096, U8192),
|
|
||||||
(U8192, U16384),
|
|
||||||
(U15360, U30720));
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::ops::{Shl,ShrAssign};
|
|
||||||
|
|
||||||
macro_rules! generate_shifts
|
|
||||||
{
|
|
||||||
($num: ident, $size: expr) => {
|
|
||||||
impl ShrAssign<usize> for $num {
|
|
||||||
fn shr_assign(&mut self, amt: usize) {
|
|
||||||
let digits = amt / 64;
|
|
||||||
let bits = amt % 64;
|
|
||||||
|
|
||||||
let mut carry = 0;
|
|
||||||
let mask = !(0xFFFFFFFFFFFFFFFF << bits);
|
|
||||||
let copy = self.values.clone();
|
|
||||||
let shift = (64 - bits) as u32;
|
|
||||||
|
|
||||||
for (idx, val) in self.values.iter_mut().enumerate().rev() {
|
|
||||||
let target = idx + digits;
|
|
||||||
let base = if target >= ($size/64) { 0 } else { copy[target] };
|
|
||||||
let (new_carry, _) = (base & mask).overflowing_shl(shift);
|
|
||||||
*val = (base >> bits) | carry;
|
|
||||||
carry = new_carry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Shl<usize> for $num {
|
|
||||||
type Output = $num;
|
|
||||||
|
|
||||||
fn shl(mut self, amt: usize) -> $num {
|
|
||||||
let digits = amt / 64;
|
|
||||||
let bits = amt % 64;
|
|
||||||
|
|
||||||
let mut carry = 0;
|
|
||||||
let copy = self.values.clone();
|
|
||||||
let shift = 64 - bits;
|
|
||||||
|
|
||||||
for (idx, val) in self.values.iter_mut().enumerate() {
|
|
||||||
let base = if idx >= digits { copy[idx - digits] } else { 0 };
|
|
||||||
let new_carry = if shift == 64 { 0 } else { base >> shift };
|
|
||||||
*val = (base << bits) | carry;
|
|
||||||
carry = new_carry;
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_shifts!(U192, 192);
|
|
||||||
generate_shifts!(U256, 256);
|
|
||||||
generate_shifts!(U320, 320); // this is just for expansion
|
|
||||||
generate_shifts!(U384, 384);
|
|
||||||
generate_shifts!(U448, 448); // this is just for expansion
|
|
||||||
generate_shifts!(U512, 512);
|
|
||||||
generate_shifts!(U576, 576);
|
|
||||||
generate_shifts!(U640, 640); // this is just for expansion
|
|
||||||
generate_shifts!(U768, 768); // this is just for expansion
|
|
||||||
generate_shifts!(U832, 832); // this is just for Barrett
|
|
||||||
generate_shifts!(U896, 896); // this is just for Barrett
|
|
||||||
generate_shifts!(U1024, 1024);
|
|
||||||
generate_shifts!(U1088, 1088); // this is just for expansion
|
|
||||||
generate_shifts!(U1152, 1152); // this is just for expansion
|
|
||||||
generate_shifts!(U1216, 1216); // this is just for Barrett
|
|
||||||
generate_shifts!(U1536, 1536); // this is just for expansion
|
|
||||||
generate_shifts!(U1664, 1664); // this is just for Barrett
|
|
||||||
generate_shifts!(U2048, 2048);
|
|
||||||
generate_shifts!(U2112, 2112); // this is just for expansion
|
|
||||||
generate_shifts!(U2176, 2176); // this is just for Barrett
|
|
||||||
generate_shifts!(U2304, 2304); // this is just for expansion
|
|
||||||
generate_shifts!(U2432, 2432); // this is just for Barrett
|
|
||||||
generate_shifts!(U3072, 3072);
|
|
||||||
generate_shifts!(U3136, 3136); // this is just for expansion
|
|
||||||
generate_shifts!(U4096, 4096);
|
|
||||||
generate_shifts!(U4160, 4160); // this is just for expansion
|
|
||||||
generate_shifts!(U4224, 4224); // this is just for Barrett
|
|
||||||
generate_shifts!(U6144, 6144); // this is just for expansion
|
|
||||||
generate_shifts!(U6208, 6208); // this is just for Barrett
|
|
||||||
generate_shifts!(U7680, 7680); // Useful for RSA key generation
|
|
||||||
generate_shifts!(U7744, 7744); // Addition on previous
|
|
||||||
generate_shifts!(U8192, 8192);
|
|
||||||
generate_shifts!(U8256, 8256); // this is just for expansion
|
|
||||||
generate_shifts!(U8320, 8320); // this is just for Barrett
|
|
||||||
generate_shifts!(U12288, 12288); // this is just for expansion
|
|
||||||
generate_shifts!(U12416, 12416); // this is just for Barrett
|
|
||||||
generate_shifts!(U15360, 15360);
|
|
||||||
generate_shifts!(U15424, 15424); // this is just for expansion
|
|
||||||
generate_shifts!(U16384, 16384); // this is just for expansion
|
|
||||||
generate_shifts!(U16448, 16448); // this is just for Barrett
|
|
||||||
generate_shifts!(U16512, 16512); // this is just for Barrett
|
|
||||||
generate_shifts!(U30720, 30720); // this is just for expansion
|
|
||||||
generate_shifts!(U30784, 30784); // this is just for Barrett
|
|
||||||
generate_shifts!(U32768, 32768); // this is just for expansion
|
|
||||||
generate_shifts!(U32896, 32896); // this is just for Barrett
|
|
||||||
generate_shifts!(U61440, 61440); // this is just for expansion
|
|
||||||
generate_shifts!(U61568, 61568); // this is just for Barrett
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( $name:ident ), * ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod left {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/shift{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 4, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg3, lbytes) = case.get("l").unwrap();
|
|
||||||
assert!(!neg0 && !neg1 && !neg3);
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let bigb = $name::from_bytes(bbytes);
|
|
||||||
let b = usize::from(bigb);
|
|
||||||
let l = $name::from_bytes(lbytes);
|
|
||||||
let res = a << b;
|
|
||||||
assert_eq!(res, l);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod right {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/shift{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 4, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, rbytes) = case.get("r").unwrap();
|
|
||||||
assert!(!neg0 && !neg1 && !neg2);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let bigb = $name::from_bytes(bbytes);
|
|
||||||
let b = usize::from(bigb);
|
|
||||||
let r = $name::from_bytes(rbytes);
|
|
||||||
a >>= b;
|
|
||||||
assert_eq!(a, r);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!(U192, U256, U384, U512, U576, U1024, U2048, U3072,
|
|
||||||
U4096, U8192, U15360);
|
|
||||||
@@ -1,311 +0,0 @@
|
|||||||
use cryptonum::addition::UnsafeAdd;
|
|
||||||
use cryptonum::basetypes::*;
|
|
||||||
use cryptonum::encoding::Decoder;
|
|
||||||
use std::fmt;
|
|
||||||
use std::cmp::{Ord,Ordering};
|
|
||||||
use std::ops::{Add,Shl,ShrAssign,Sub,SubAssign};
|
|
||||||
|
|
||||||
pub struct Signed<T> {
|
|
||||||
pub(crate) negative: bool,
|
|
||||||
pub(crate) value: T
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Signed<T> {
|
|
||||||
pub fn new(negative: bool, value: T) -> Signed<T> {
|
|
||||||
Signed{ negative: negative, value: value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> Clone for Signed<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Signed{ negative: self.negative, value: self.value.clone() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: CryptoNum> CryptoNum for Signed<T> {
|
|
||||||
fn zero() -> Signed<T> {
|
|
||||||
Signed::new(false, T::zero())
|
|
||||||
}
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
self.value.is_odd()
|
|
||||||
}
|
|
||||||
fn is_even(&self) -> bool {
|
|
||||||
self.value.is_even()
|
|
||||||
}
|
|
||||||
fn is_zero(&self) -> bool {
|
|
||||||
self.value.is_zero()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Decoder> Decoder for Signed<T> {
|
|
||||||
fn from_bytes(x: &[u8]) -> Signed<T> {
|
|
||||||
let x: T = T::from_bytes(x);
|
|
||||||
Signed{ negative: false, value: x }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug> fmt::Debug for Signed<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
if self.negative {
|
|
||||||
write!(f, "NEGATIVE:")?;
|
|
||||||
} else {
|
|
||||||
write!(f, "POSITIVE:")?;
|
|
||||||
}
|
|
||||||
self.value.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::UpperHex> fmt::UpperHex for Signed<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
if self.negative {
|
|
||||||
write!(f, "-")?;
|
|
||||||
}
|
|
||||||
self.value.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::LowerHex> fmt::LowerHex for Signed<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
if self.negative {
|
|
||||||
write!(f, "-")?;
|
|
||||||
}
|
|
||||||
self.value.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq for Signed<T> {
|
|
||||||
fn eq(&self, other: &Signed<T>) -> bool {
|
|
||||||
(self.negative == other.negative) && (self.value == other.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq> Eq for Signed<T> {}
|
|
||||||
|
|
||||||
impl<T> ShrAssign<usize> for Signed<T>
|
|
||||||
where
|
|
||||||
T: ShrAssign<usize> + UnsafeAdd + CryptoNum + From<u64> + Clone + fmt::UpperHex,
|
|
||||||
T: Shl<usize,Output=T> + PartialEq
|
|
||||||
{
|
|
||||||
fn shr_assign(&mut self, rhs: usize) {
|
|
||||||
// arithmatic right shift is normal right shift, but always rounding
|
|
||||||
// to negative infinity. To implement this, we first shift right by
|
|
||||||
// rhs bits, and then shift that value back left rhs bits. If the two
|
|
||||||
// are the same, we just cleared out even bits, and there's no rounding
|
|
||||||
// to worry about. If they aren't the same, then we add one back.
|
|
||||||
let original = self.value.clone();
|
|
||||||
self.value.shr_assign(rhs);
|
|
||||||
if self.negative {
|
|
||||||
let review = self.value.clone() << rhs;
|
|
||||||
if review != original {
|
|
||||||
self.value = self.value.clone().unsafe_add(&T::from(1u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> UnsafeAdd for Signed<T>
|
|
||||||
where
|
|
||||||
T: UnsafeAdd + SubAssign + Sub<Output=T>,
|
|
||||||
T: PartialOrd + Ord,
|
|
||||||
T: Clone
|
|
||||||
{
|
|
||||||
fn unsafe_add(mut self, rhs: &Signed<T>) -> Signed<T> {
|
|
||||||
if self.negative == rhs.negative {
|
|
||||||
Signed{
|
|
||||||
negative: self.negative,
|
|
||||||
value: self.value.unsafe_add(&rhs.value)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if self.value > rhs.value {
|
|
||||||
self.value -= rhs.value.clone();
|
|
||||||
} else {
|
|
||||||
self.value = rhs.value.clone() - self.value.clone();
|
|
||||||
self.negative = rhs.negative;
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b,T,U> Add<&'a Signed<T>> for &'b Signed<T>
|
|
||||||
where
|
|
||||||
&'a T: Add<&'b T,Output=U> + Sub<&'b T,Output=T>,
|
|
||||||
T: PartialOrd + Ord,
|
|
||||||
T: Clone,
|
|
||||||
U: From<T>
|
|
||||||
{
|
|
||||||
type Output = Signed<U>;
|
|
||||||
|
|
||||||
fn add(self, rhs: &Signed<T>) -> Signed<U> {
|
|
||||||
if self.negative == rhs.negative {
|
|
||||||
Signed {
|
|
||||||
negative: self.negative,
|
|
||||||
value: &self.value + &rhs.value
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if self.value > rhs.value {
|
|
||||||
Signed {
|
|
||||||
negative: self.negative,
|
|
||||||
value: U::from(&self.value - &rhs.value)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Signed {
|
|
||||||
negative: rhs.negative,
|
|
||||||
value: U::from(&rhs.value - &self.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> SubAssign<&'a Signed<T>> for Signed<T>
|
|
||||||
where
|
|
||||||
T: SubAssign<T>,
|
|
||||||
T: Sub<T,Output=T>,
|
|
||||||
T: UnsafeAdd,
|
|
||||||
T: PartialOrd,
|
|
||||||
T: Clone
|
|
||||||
{
|
|
||||||
fn sub_assign(&mut self, rhs: &Signed<T>) {
|
|
||||||
if self.negative == rhs.negative {
|
|
||||||
if &self.value >= &rhs.value {
|
|
||||||
self.value -= rhs.value.clone();
|
|
||||||
} else {
|
|
||||||
self.value = rhs.value.clone() - self.value.clone();
|
|
||||||
self.negative = !self.negative;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.value = rhs.value.clone().unsafe_add(&self.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord + PartialOrd> PartialOrd for Signed<T> {
|
|
||||||
fn partial_cmp(&self, other: &Signed<T>) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(&other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord + PartialOrd> Ord for Signed<T> {
|
|
||||||
fn cmp(&self, other: &Signed<T>) -> Ordering {
|
|
||||||
match (self.negative, other.negative) {
|
|
||||||
(false, false) => self.value.cmp(&other.value),
|
|
||||||
(true, false) => Ordering::Greater,
|
|
||||||
(false, true) => Ordering::Less,
|
|
||||||
(true, true) => self.value.cmp(&other.value).reverse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Shl<usize> for Signed<T>
|
|
||||||
where T: Shl<usize,Output=T>
|
|
||||||
{
|
|
||||||
type Output = Signed<T>;
|
|
||||||
|
|
||||||
fn shl(mut self, amt: usize) -> Signed<T> {
|
|
||||||
self.value = self.value << amt;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( $name:ident ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod shr {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/sigshr{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (nega, abytes) = case.get("a").unwrap();
|
|
||||||
let (negb, bbytes) = case.get("b").unwrap();
|
|
||||||
let (negx, xbytes) = case.get("x").unwrap();
|
|
||||||
|
|
||||||
assert!(!negb);
|
|
||||||
let ua = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let ux = $name::from_bytes(xbytes);
|
|
||||||
let mut a = Signed::new(*nega, ua);
|
|
||||||
let x = Signed::new(*negx, ux);
|
|
||||||
|
|
||||||
a >>= usize::from(b);
|
|
||||||
assert_eq!(a, x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod add {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/sigadd{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (nega, abytes) = case.get("a").unwrap();
|
|
||||||
let (negb, bbytes) = case.get("b").unwrap();
|
|
||||||
let (negx, xbytes) = case.get("x").unwrap();
|
|
||||||
|
|
||||||
let ua = $name::from_bytes(abytes);
|
|
||||||
let ub = $name::from_bytes(bbytes);
|
|
||||||
let ux = $name::from_bytes(xbytes);
|
|
||||||
let a = Signed::new(*nega, ua);
|
|
||||||
let b = Signed::new(*negb, ub);
|
|
||||||
let x = Signed::new(*negx, ux);
|
|
||||||
|
|
||||||
let res = a.unsafe_add(&b);
|
|
||||||
assert_eq!(res, x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod sub {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/sigsub{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (nega, abytes) = case.get("a").unwrap();
|
|
||||||
let (negb, bbytes) = case.get("b").unwrap();
|
|
||||||
let (negx, xbytes) = case.get("x").unwrap();
|
|
||||||
|
|
||||||
let ua = $name::from_bytes(abytes);
|
|
||||||
let ub = $name::from_bytes(bbytes);
|
|
||||||
let ux = $name::from_bytes(xbytes);
|
|
||||||
let mut a = Signed::new(*nega, ua);
|
|
||||||
let b = Signed::new(*negb, ub);
|
|
||||||
let b2 = b.clone();
|
|
||||||
let x = Signed::new(*negx, ux);
|
|
||||||
|
|
||||||
a -= &b2;
|
|
||||||
assert_eq!(a, x);
|
|
||||||
assert_eq!(b, b2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!(U192, U256, U384, U512, U1024,
|
|
||||||
U2048, U3072, U4096, U8192, U15360);
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
|
|
||||||
macro_rules! generate_squarers
|
|
||||||
{
|
|
||||||
($name: ident, $bigger: ident, $size: expr) => {
|
|
||||||
impl $name {
|
|
||||||
pub fn square(&self) -> $bigger {
|
|
||||||
let mut w = [0; $size/32];
|
|
||||||
let t = $size / 64;
|
|
||||||
|
|
||||||
for i in 0..t {
|
|
||||||
let x128 = self.values[i] as u128;
|
|
||||||
let mut uvb = (w[2*i] as u128) + (x128 * x128);
|
|
||||||
w[2*i] = uvb & 0xFFFFFFFFFFFFFFFF;
|
|
||||||
let mut c = uvb >> 64;
|
|
||||||
for j in (i+1)..t {
|
|
||||||
let xj128 = self.values[j] as u128;
|
|
||||||
let xi128 = self.values[i] as u128;
|
|
||||||
// this first product is safely 128 bits or less,
|
|
||||||
// because the input arguments are both 64 bits.
|
|
||||||
let xij128 = xj128 * xi128;
|
|
||||||
// this next bit may overflow, but will do so by exactly
|
|
||||||
// one bit.
|
|
||||||
let twoxij128 = xij128 << 1;
|
|
||||||
let carried_shl = (xij128 & (1 << 127)) != 0;
|
|
||||||
// this next bit may *also* overflow, but should also do
|
|
||||||
// so by no more than one bit.
|
|
||||||
let (new,carry1) = twoxij128.overflowing_add(c);
|
|
||||||
// ditto ...
|
|
||||||
let wij = w[i+j];
|
|
||||||
let (uvb2,carry2) = new.overflowing_add(wij as u128);
|
|
||||||
// for the value we're going to save for this digit, we
|
|
||||||
// only care about the low bits, so we can forget about
|
|
||||||
// the carry stuff.
|
|
||||||
w[i+j] = uvb2 & 0xFFFFFFFFFFFFFFFF;
|
|
||||||
// for c, though, we do care about the carries, above.
|
|
||||||
// Fortunately, they were both by only one bit, so we
|
|
||||||
// should be able to just back-fix them.
|
|
||||||
c = uvb2 >> 64;
|
|
||||||
if carried_shl { c += 1 << 64; }
|
|
||||||
if carry1 { c += 1 << 64; }
|
|
||||||
if carry2 { c += 1 << 64; }
|
|
||||||
}
|
|
||||||
w[i+t] = c;
|
|
||||||
}
|
|
||||||
let mut res = $bigger::zero();
|
|
||||||
for i in 0..w.len() { res.values[i] = w[i] as u64; }
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// impl ModSquare for $name {
|
|
||||||
// fn modsq(&self, m: &$name) -> $name {
|
|
||||||
// let bigsquare = self.square();
|
|
||||||
// let bigm = $bigger::from(m);
|
|
||||||
// let bigres = bigsquare.reduce(&bigm);
|
|
||||||
// $name::from(bigres)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_squarers!(U192, U384, 192);
|
|
||||||
generate_squarers!(U256, U512, 256);
|
|
||||||
generate_squarers!(U384, U768, 384);
|
|
||||||
generate_squarers!(U512, U1024, 512);
|
|
||||||
generate_squarers!(U576, U1152, 576);
|
|
||||||
generate_squarers!(U1024, U2048, 1024);
|
|
||||||
generate_squarers!(U2048, U4096, 2048);
|
|
||||||
generate_squarers!(U3072, U6144, 3072);
|
|
||||||
generate_squarers!(U4096, U8192, 4096);
|
|
||||||
generate_squarers!(U8192, U16384, 8192);
|
|
||||||
generate_squarers!(U15360, U30720,15360);
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( ($name:ident, $bigger:ident) ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod normal {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/squaring{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 2, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, rbytes) = case.get("r").unwrap();
|
|
||||||
|
|
||||||
assert!(!neg0 && !neg1);
|
|
||||||
let a = $name::from_bytes(abytes);
|
|
||||||
let r = $bigger::from_bytes(rbytes);
|
|
||||||
let myres = a.square();
|
|
||||||
assert_eq!(r, myres);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!((U192, U384),
|
|
||||||
(U256, U512),
|
|
||||||
(U384, U768),
|
|
||||||
(U512, U1024),
|
|
||||||
(U576, U1152),
|
|
||||||
(U1024, U2048),
|
|
||||||
(U2048, U4096),
|
|
||||||
(U3072, U6144),
|
|
||||||
(U4096, U8192),
|
|
||||||
(U8192, U16384),
|
|
||||||
(U15360, U30720));
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
use cryptonum::basetypes::*;
|
|
||||||
use std::ops::{Sub,SubAssign};
|
|
||||||
|
|
||||||
macro_rules! generate_subbers
|
|
||||||
{
|
|
||||||
($name: ident, $size: expr) => {
|
|
||||||
impl<'a> SubAssign<&'a $name> for $name {
|
|
||||||
fn sub_assign(&mut self, rhs: &$name) {
|
|
||||||
// negate the right hand size
|
|
||||||
let mut negatedy: $name = rhs.clone();
|
|
||||||
for i in 0..$size/64 {
|
|
||||||
negatedy.values[i] = !negatedy.values[i];
|
|
||||||
}
|
|
||||||
// add one
|
|
||||||
let mut bigger = 1 + (negatedy.values[0] as u128);
|
|
||||||
let mut carry = bigger >> 64;
|
|
||||||
negatedy.values[0] = bigger as u64;
|
|
||||||
for i in 1..$size/64 {
|
|
||||||
bigger = carry + (negatedy.values[i] as u128);
|
|
||||||
negatedy.values[i] = bigger as u64;
|
|
||||||
carry = bigger >> 64;
|
|
||||||
}
|
|
||||||
// then add it to ourselves
|
|
||||||
carry = 0;
|
|
||||||
for i in 0..$size/64 {
|
|
||||||
let x128 = self.values[i] as u128;
|
|
||||||
let y128 = negatedy.values[i] as u128;
|
|
||||||
bigger = x128 + y128 + carry;
|
|
||||||
carry = bigger >> 64;
|
|
||||||
self.values[i] = bigger as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubAssign for $name {
|
|
||||||
fn sub_assign(&mut self, rhs: $name) {
|
|
||||||
self.sub_assign(&rhs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,'b> Sub<&'b $name> for &'a $name {
|
|
||||||
type Output = $name;
|
|
||||||
|
|
||||||
fn sub(self, rhs: &$name) -> $name {
|
|
||||||
let mut res = self.clone();
|
|
||||||
res -= rhs;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sub for $name {
|
|
||||||
type Output = $name;
|
|
||||||
|
|
||||||
fn sub(mut self, rhs: $name) -> $name {
|
|
||||||
self -= rhs;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_subbers!(U192, 192);
|
|
||||||
generate_subbers!(U256, 256);
|
|
||||||
generate_subbers!(U320, 320); // this is just for expansion
|
|
||||||
generate_subbers!(U384, 384);
|
|
||||||
generate_subbers!(U448, 448); // this is just for expansion
|
|
||||||
generate_subbers!(U512, 512);
|
|
||||||
generate_subbers!(U576, 576);
|
|
||||||
generate_subbers!(U640, 640); // this is just for expansion
|
|
||||||
generate_subbers!(U768, 768); // this is just for expansion
|
|
||||||
generate_subbers!(U832, 832); // this is just for Barrett
|
|
||||||
generate_subbers!(U896, 896); // this is just for Barrett
|
|
||||||
generate_subbers!(U1024, 1024);
|
|
||||||
generate_subbers!(U1088, 1088); // this is just for expansion
|
|
||||||
generate_subbers!(U1152, 1152); // this is just for expansion
|
|
||||||
generate_subbers!(U1216, 1216); // this is just for Barrett
|
|
||||||
generate_subbers!(U1536, 1536); // this is just for expansion
|
|
||||||
generate_subbers!(U1664, 1664); // this is just for Barrett
|
|
||||||
generate_subbers!(U2048, 2048);
|
|
||||||
generate_subbers!(U2112, 2112); // this is just for expansion
|
|
||||||
generate_subbers!(U2176, 2176); // this is just for Barrett
|
|
||||||
generate_subbers!(U2304, 2304); // this is just for expansion
|
|
||||||
generate_subbers!(U2432, 2432); // this is just for Barrett
|
|
||||||
generate_subbers!(U3072, 3072);
|
|
||||||
generate_subbers!(U3136, 3136); // this is just for expansion
|
|
||||||
generate_subbers!(U4096, 4096);
|
|
||||||
generate_subbers!(U4160, 4160); // this is just for expansion
|
|
||||||
generate_subbers!(U4224, 4224); // this is just for Barrett
|
|
||||||
generate_subbers!(U6144, 6144); // this is just for expansion
|
|
||||||
generate_subbers!(U6208, 6208); // this is just for Barrett
|
|
||||||
generate_subbers!(U7680, 7680);
|
|
||||||
generate_subbers!(U8192, 8192);
|
|
||||||
generate_subbers!(U8256, 8256); // this is just for expansion
|
|
||||||
generate_subbers!(U8320, 8320); // this is just for Barrett
|
|
||||||
generate_subbers!(U12288, 12288); // this is just for expansion
|
|
||||||
generate_subbers!(U12416, 12416); // this is just for Barrett
|
|
||||||
generate_subbers!(U15360, 15360);
|
|
||||||
generate_subbers!(U15424, 15424); // this is just for expansion
|
|
||||||
generate_subbers!(U16384, 16384); // this is just for expansion
|
|
||||||
generate_subbers!(U16448, 16448); // this is just for Barrett
|
|
||||||
generate_subbers!(U16512, 16512); // this is just for Barrett
|
|
||||||
generate_subbers!(U30720, 30720); // this is just for expansion
|
|
||||||
generate_subbers!(U30784, 30784); // this is just for Barrett
|
|
||||||
generate_subbers!(U32768, 32768); // this is just for expansion
|
|
||||||
generate_subbers!(U32896, 32896); // this is just for Barrett
|
|
||||||
generate_subbers!(U61440, 61440); // this is just for expansion
|
|
||||||
generate_subbers!(U61568, 61568); // this is just for Barrett
|
|
||||||
|
|
||||||
macro_rules! generate_tests {
|
|
||||||
( $( $name:ident ),* ) => {
|
|
||||||
#[cfg(test)]
|
|
||||||
mod normal {
|
|
||||||
use cryptonum::Decoder;
|
|
||||||
use super::*;
|
|
||||||
use testing::run_test;
|
|
||||||
|
|
||||||
$(
|
|
||||||
#[test]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn $name() {
|
|
||||||
let fname = format!("tests/math/subtraction{}.test",
|
|
||||||
stringify!($name));
|
|
||||||
run_test(fname.to_string(), 3, |case| {
|
|
||||||
let (neg0, abytes) = case.get("a").unwrap();
|
|
||||||
let (neg1, bbytes) = case.get("b").unwrap();
|
|
||||||
let (neg2, cbytes) = case.get("c").unwrap();
|
|
||||||
assert!(!neg0 && !neg1 && !neg2);
|
|
||||||
let mut a = $name::from_bytes(abytes);
|
|
||||||
let b = $name::from_bytes(bbytes);
|
|
||||||
let c = $name::from_bytes(cbytes);
|
|
||||||
a -= &b;
|
|
||||||
assert_eq!(a, c);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_tests!(U192, U256, U384, U512, U576,
|
|
||||||
U1024, U2048, U3072, U4096, U8192,
|
|
||||||
U15360);
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
pub trait FromHex {
|
|
||||||
fn from_hex(s: String) -> Self;
|
|
||||||
}
|
|
||||||
@@ -1,355 +0,0 @@
|
|||||||
import Control.Monad
|
|
||||||
import Data.Bits(Bits,shiftL,shiftR,(.&.))
|
|
||||||
import Data.Map.Strict(Map)
|
|
||||||
import qualified Data.Map.Strict as Map
|
|
||||||
import GHC.Integer.GMP.Internals(powModInteger)
|
|
||||||
import Numeric(showHex)
|
|
||||||
import Prelude hiding (log)
|
|
||||||
import System.Environment(getArgs)
|
|
||||||
import System.IO(hFlush,stdout,IOMode(..),withFile,Handle,hClose,hPutStrLn)
|
|
||||||
import System.Random(StdGen,newStdGen,random)
|
|
||||||
|
|
||||||
testTypes :: [(String, Int -> StdGen -> (Map String String, StdGen))]
|
|
||||||
testTypes = [("addition", addTest),
|
|
||||||
("modadd", modaddTest),
|
|
||||||
("subtraction", subTest),
|
|
||||||
("multiplication", mulTest),
|
|
||||||
("modmul", modmulTest),
|
|
||||||
("squaring", squareTest),
|
|
||||||
("modsq", modsqTest),
|
|
||||||
("modexp", modexpTest),
|
|
||||||
("bmodexp", bmodexpTest),
|
|
||||||
("division", divTest),
|
|
||||||
("shift", shiftTest),
|
|
||||||
("sigshr", signedShiftRightTest),
|
|
||||||
("sigadd", signedAddition),
|
|
||||||
("sigsub", signedSubtraction),
|
|
||||||
("barrett_gen", barrettGenTest),
|
|
||||||
("barrett_reduce", barrettReduceTest),
|
|
||||||
("barrett_mul", bmodmulTest),
|
|
||||||
("egcd", egcdTest)
|
|
||||||
]
|
|
||||||
|
|
||||||
bitSizes :: [Int]
|
|
||||||
bitSizes = [192,256,384,512,576,1024,2048,3072,4096,8192,15360]
|
|
||||||
|
|
||||||
numTests :: Int
|
|
||||||
numTests = 1000
|
|
||||||
|
|
||||||
mask :: Int -> Integer
|
|
||||||
mask bitsize = (1 `shiftL` bitsize) - 1
|
|
||||||
|
|
||||||
splitMod :: Int -> [Integer] -> [Integer]
|
|
||||||
splitMod bitsize xs = filtered ++ [m]
|
|
||||||
where
|
|
||||||
xs' = map (\x -> x .&. mask bitsize) xs
|
|
||||||
m = maximum xs'
|
|
||||||
filtered = go xs'
|
|
||||||
go [] = error "Didn't find case in splitMod"
|
|
||||||
go (x:rest) | x == m = rest
|
|
||||||
| otherwise = x : go rest
|
|
||||||
|
|
||||||
addTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
addTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. mask bitsize
|
|
||||||
c = a' + b'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("c", showHex c "")]
|
|
||||||
|
|
||||||
modaddTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
modaddTest bitsize gen0 = (res, gen3)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
(m, gen3) = random gen2
|
|
||||||
[a',b',m'] = splitMod bitsize [a,b,m]
|
|
||||||
c = (a' + b') `mod` m'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("c", showHex c "")]
|
|
||||||
|
|
||||||
subTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
subTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. mask bitsize
|
|
||||||
c = (a' - b') .&. mask bitsize
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("c", showHex c "")]
|
|
||||||
|
|
||||||
mulTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
mulTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. mask bitsize
|
|
||||||
c = (a' * b')
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("c", showHex c "")]
|
|
||||||
|
|
||||||
modmulTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
modmulTest bitsize gen0 = (res, gen3)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
(m, gen3) = random gen2
|
|
||||||
[a',b',m'] = splitMod bitsize [a,b,m]
|
|
||||||
c = (a' * b') `mod` m'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("c", showHex c "")]
|
|
||||||
|
|
||||||
squareTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
squareTest bitsize gen0 = (res, gen1)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
r = a' * a'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
modsqTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
modsqTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(m, gen2) = random gen1
|
|
||||||
[a',m'] = splitMod bitsize [a,m]
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
r = (a' * a') `mod` m'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
modexpTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
modexpTest bitsize gen0 = (res, gen3)
|
|
||||||
where
|
|
||||||
(b, gen1) = random gen0
|
|
||||||
(e, gen2) = random gen1
|
|
||||||
(m, gen3) = random gen2
|
|
||||||
[b',e',m'] = splitMod bitsize [b,e,m]
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
r = powModInteger b' e' m'
|
|
||||||
res = Map.fromList [("b", showHex b' ""),
|
|
||||||
("e", showHex e' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
|
|
||||||
divTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
divTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. mask bitsize
|
|
||||||
(q, r) = divMod a' b'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("q", showHex q ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
shiftTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
shiftTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. 0xFF
|
|
||||||
r = a' `shiftR` b'
|
|
||||||
l = (a' `shiftL` b') .&. mask bitsize
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("r", showHex r ""),
|
|
||||||
("l", showHex l "")]
|
|
||||||
|
|
||||||
signedMask :: (Ord a, Num a, Bits a) => a -> a -> a
|
|
||||||
signedMask x y | x < 0 = -(abs x .&. y)
|
|
||||||
| otherwise = x .&. y
|
|
||||||
|
|
||||||
signedShiftRightTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
signedShiftRightTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = signedMask a (mask bitsize)
|
|
||||||
b' = b .&. 0xFF
|
|
||||||
x = a' `shiftR` b'
|
|
||||||
prefixA = if a' < 0 then "-" else ""
|
|
||||||
prefixX = if x < 0 then "-" else ""
|
|
||||||
res = Map.fromList [("a", prefixA ++ showHex (abs a') ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("x", prefixX ++ showHex (abs x) "")]
|
|
||||||
|
|
||||||
signedAddition :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
signedAddition bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
mymask = mask (bitsize - 2)
|
|
||||||
a' = signedMask a mymask
|
|
||||||
b' = signedMask b mymask
|
|
||||||
x = a' + b'
|
|
||||||
prefixA = if a' < 0 then "-" else ""
|
|
||||||
prefixB = if b' < 0 then "-" else ""
|
|
||||||
prefixX = if x < 0 then "-" else ""
|
|
||||||
res = Map.fromList [("a", prefixA ++ showHex (abs a') ""),
|
|
||||||
("b", prefixB ++ showHex (abs b') ""),
|
|
||||||
("x", prefixX ++ showHex (abs x) "")]
|
|
||||||
|
|
||||||
signedSubtraction :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
signedSubtraction bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
mymask = mask (bitsize - 2)
|
|
||||||
a' = signedMask a mymask
|
|
||||||
b' = signedMask b mymask
|
|
||||||
x = a' - b'
|
|
||||||
prefixA = if a' < 0 then "-" else ""
|
|
||||||
prefixB = if b' < 0 then "-" else ""
|
|
||||||
prefixX = if x < 0 then "-" else ""
|
|
||||||
res = Map.fromList [("a", prefixA ++ showHex (abs a') ""),
|
|
||||||
("b", prefixB ++ showHex (abs b') ""),
|
|
||||||
("x", prefixX ++ showHex (abs x) "")]
|
|
||||||
|
|
||||||
barrettGenTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
barrettGenTest bitsize gen0 = (res, gen1)
|
|
||||||
where
|
|
||||||
(m, gen1) = random gen0
|
|
||||||
m' = m .&. mask bitsize
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
res = Map.fromList [("m", showHex m' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u "")]
|
|
||||||
|
|
||||||
barrettReduceTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
barrettReduceTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(m, gen1) = random gen0
|
|
||||||
(x, gen2) = random gen1
|
|
||||||
m' = m .&. mask bitsize
|
|
||||||
x' = x .&. mask (min bitsize (2 * k * 64))
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
r = x' `mod` m'
|
|
||||||
res = Map.fromList [("m", showHex m' ""),
|
|
||||||
("x", showHex x' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
bmodmulTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
bmodmulTest bitsize gen0 = (res, gen3)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
(m, gen3) = random gen2
|
|
||||||
[a',b',m'] = splitMod bitsize [a,b,m]
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
r = (a' * b') `mod` m'
|
|
||||||
res = Map.fromList [("a", showHex a' ""),
|
|
||||||
("b", showHex b' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
egcdTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
egcdTest bitsize gen0 = (res, gen2)
|
|
||||||
where
|
|
||||||
(a, gen1) = random gen0
|
|
||||||
(b, gen2) = random gen1
|
|
||||||
a' = a .&. mask bitsize
|
|
||||||
b' = b .&. mask bitsize
|
|
||||||
g = gcd a b
|
|
||||||
res = Map.fromList [("a", showSignedHex a' ""),
|
|
||||||
("b", showSignedHex b' ""),
|
|
||||||
("g", showSignedHex g "")]
|
|
||||||
|
|
||||||
showSignedHex :: (Integral a, Num a, Show a) => a -> ShowS
|
|
||||||
showSignedHex x str | x < 0 = "-" ++ showHex (abs x) str
|
|
||||||
| otherwise = showHex x str
|
|
||||||
|
|
||||||
bmodexpTest :: Int -> StdGen -> (Map String String, StdGen)
|
|
||||||
bmodexpTest bitsize gen0 = (res, gen3)
|
|
||||||
where
|
|
||||||
(b, gen1) = random gen0
|
|
||||||
(e, gen2) = random gen1
|
|
||||||
(m, gen3) = random gen2
|
|
||||||
[b',e',m'] = splitMod bitsize [b,e,m]
|
|
||||||
k = computeK m'
|
|
||||||
u = barrett m'
|
|
||||||
r = powModInteger b' e' m'
|
|
||||||
res = Map.fromList [("b", showHex b' ""),
|
|
||||||
("e", showHex e' ""),
|
|
||||||
("m", showHex m' ""),
|
|
||||||
("k", showHex k ""),
|
|
||||||
("u", showHex u ""),
|
|
||||||
("r", showHex r "")]
|
|
||||||
|
|
||||||
base :: Integer
|
|
||||||
base = 2 ^ (64 :: Integer)
|
|
||||||
|
|
||||||
barrett :: Integer -> Integer
|
|
||||||
barrett m = (base ^ (2 * k)) `div` m
|
|
||||||
where
|
|
||||||
k = computeK m
|
|
||||||
|
|
||||||
computeK :: Integer -> Int
|
|
||||||
computeK v = go 0 1
|
|
||||||
where
|
|
||||||
go k acc | v <= acc = k
|
|
||||||
| otherwise = go (k + 1) (acc * base)
|
|
||||||
|
|
||||||
log :: String -> IO ()
|
|
||||||
log str =
|
|
||||||
do putStr str
|
|
||||||
hFlush stdout
|
|
||||||
|
|
||||||
generateData :: Handle -> (StdGen -> (Map String String, StdGen)) ->
|
|
||||||
StdGen -> () ->
|
|
||||||
IO StdGen
|
|
||||||
generateData hndl generator gen () =
|
|
||||||
do let (res, gen') = generator gen
|
|
||||||
forM_ (Map.toList res) $ \ (key,val) ->
|
|
||||||
do hPutStrLn hndl (key ++ ": " ++ val)
|
|
||||||
log "."
|
|
||||||
return gen'
|
|
||||||
|
|
||||||
main :: IO ()
|
|
||||||
main =
|
|
||||||
do args <- getArgs
|
|
||||||
let tests = if null args
|
|
||||||
then testTypes
|
|
||||||
else filter (\ (name,_) -> name `elem` args) testTypes
|
|
||||||
forM_ tests $ \ (testName, testFun) ->
|
|
||||||
forM_ bitSizes $ \ bitsize ->
|
|
||||||
do log ("Generating "++show bitsize++"-bit "++testName++" tests")
|
|
||||||
withFile (testName ++ "U" ++ show bitsize ++ ".test") WriteMode $
|
|
||||||
\ hndl ->
|
|
||||||
do gen <- newStdGen
|
|
||||||
foldM_ (generateData hndl (testFun bitsize))
|
|
||||||
gen
|
|
||||||
(replicate numTests ())
|
|
||||||
hClose hndl
|
|
||||||
log " done\n"
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user