diff --git a/src/cryptonum/builder.rs b/src/cryptonum/builder.rs deleted file mode 100644 index ecbaae2..0000000 --- a/src/cryptonum/builder.rs +++ /dev/null @@ -1,1066 +0,0 @@ -macro_rules! construct_unsigned { - ($type: ident, $barrett: ident, $modname: ident, $count: expr) => { - #[derive(Clone)] - pub struct $type { - contents: [u64; $count] - } - - pub struct $barrett { - k: usize, - progenitor: $type, - contents: [u64; $count + 1] - } - - 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 Debug for $barrett { - fn fmt(&self, f: &mut Formatter) -> Result<(),Error> { - f.write_str("BarrettMu{{ ")?; - f.write_fmt(format_args!("k = {}, ", self.k))?; - f.write_fmt(format_args!("progen = {:?}, ",self.progenitor))?; - f.write_str("contents: ")?; - f.debug_list().entries(self.contents.iter()).finish()?; - f.write_str(" }}") - } - } - - impl PartialOrd for $type { - fn partial_cmp(&self, other: &$type) -> Option { - 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 CryptoNumBase for $type { - fn zero() -> $type { - $type { contents: [0; $count] } - } - - fn max_value() -> $type { - $type { contents: [0xFFFFFFFFFFFFFFFF; $count] } - } - - fn is_zero(&self) -> bool { - for x in self.contents.iter() { - if *x != 0 { - return false; - } - } - true - } - - fn is_odd(&self) -> bool { - (self.contents[0] & 1) == 1 - } - - fn is_even(&self) -> bool { - (self.contents[0] & 1) == 0 - } - - 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 CryptoNumSerialization for $type { - fn bit_size(&self) -> usize { - $count * 64 - } - - fn byte_size(&self) -> usize { - $count * 8 - } - - fn to_bytes(&self) -> Vec { - 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 - } - } - - impl CryptoNumFastMod for $type { - type BarrettMu = $barrett; - - fn barrett_mu(&self) -> Option<$barrett> { - // Step #0: Don't divide by 0. - if self.is_zero() { - return None - } - // Step #1: Compute k. - let mut k = $count; - while self.contents[k - 1] == 0 { k -= 1 }; - // Step #2: The algorithm below only works if x has at most 2k - // digits, so if k*2 < count, abort this whole process. - if (k * 2) < $count { - return None - } - // Step #2: Compute floor(b^2k / m), where m is this value. - let mut widebody_b2k = [0; ($count * 2) + 1]; - let mut widebody_self = [0; ($count * 2) + 1]; - let mut quotient = [0; ($count * 2) + 1]; - let mut remainder = [0; ($count * 2) + 1]; - widebody_b2k[$count * 2] = 1; - for i in 0..k { - widebody_self[i] = self.contents[i]; - } - generic_div(&widebody_b2k, &widebody_self, - &mut quotient, &mut remainder); - let mut result = [0; $count + 1]; - for (idx, val) in quotient.iter().enumerate() { - if idx < ($count + 1) { - result[idx] = *val; - } else { - if quotient[idx] != 0 { - return None; - } - } - } - Some($barrett{k: k, progenitor: self.clone(), contents: result}) - } - - fn fastmod(&self, mu: &$barrett) -> $type { - // This algorithm is from our friends at the Handbook of - // Applied Cryptography, Chapter 14, Algorithm 14.42. - // Step #0: - // Expand x so that it has the same size as the Barrett - // value. - let mut x = [0; $count + 1]; - for i in 0..$count { - x[i] = self.contents[i]; - } - // Step #1: - // q1 <- floor(x / b^(k-1)) - let mut q1 = x.clone(); - generic_shr(&mut q1, &x, 64 * (mu.k - 1)); - // q2 <- q1 * mu - let q2 = expanding_mul(&q1, &mu.contents); - // q3 <- floor(q2 / b^(k+1)) - let mut q3big = q2.clone(); - generic_shr(&mut q3big, &q2, 64 * (mu.k + 1)); - let mut q3 = [0; $count + 1]; - for (idx, val) in q3big.iter().enumerate() { - if idx <= $count { - q3[idx] = *val; - } else { - assert_eq!(*val, 0); - } - } - // Step #2: - // r1 <- x mod b^(k+1) - let mut r1 = x.clone(); - for i in mu.k..($count+1) { - r1[i] = 0; - } - // r2 <- q3 * m mod b^(k+1) - let mut moddedm = [0; $count + 1]; - for i in 0..mu.k { - moddedm[i] = mu.progenitor.contents[i]; - } - let mut r2 = q3.clone(); - generic_mul(&mut r2, &q3, &moddedm); - // r <- r1 - r2 - let mut r = r1.clone(); - generic_sub(&mut r, &r2); - let is_negative = !ge(&r1, &r2); - // Step #3: - // if r < 0 then r <- r + b^(k + 1) - if is_negative { - let mut bk1 = [0; $count + 1]; - bk1[mu.k] = 1; - generic_add(&mut r, &bk1); - } - // Step #4: - // while r >= m do: r <- r - m. - while ge(&r, &moddedm) { - generic_sub(&mut r, &moddedm); - } - // Step #5: - // return r - let mut retval = [0; $count]; - for i in 0..$count { - retval[i] = r[i]; - } - assert_eq!(r[$count], 0); - $type{ contents: retval } - } - } - - #[cfg(test)] - mod $modname { - use quickcheck::{Arbitrary,Gen}; - use super::*; - - impl Arbitrary for $type { - fn arbitrary(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_value().to_u64(), u64::max_value()); - assert_eq!($type::max_value() + $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_value()) == $type::max_value() - } - fn and_identity(x: $type) -> bool { - (&x & $type::max_value()) == 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_value() - } - 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_value() << 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_value() >> 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_value()); - } - - 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); - } - - 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 q = &a / &b; - let r = &a % &b; - a == ((b * q) + r) - } - } - - quickcheck! { - fn serialization_inverts(a: $type) -> bool { - let bytes = a.to_bytes(); - let b = $type::from_bytes(&bytes); - a == b - } - } - - quickcheck! { - fn fastmod_works(a: $type, b: $type) -> bool { - assert!(b != $type::zero()); - match b.barrett_mu() { - None => - true, - Some(barrett) => { - a.fastmod(&barrett) == (&a % &b) - } - } - } - } - } - }; -} - -macro_rules! from_to { - ($type: ident, $count: expr, $base: ty, $from: ident, $to: ident) => { - fn $from(x: $base) -> $type { - let mut res = $type { contents: [0; $count] }; - res.contents[0] = x as u64; - res - } - - 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 - } - } - } -} - -macro_rules! math_operator { - ($cl: ident, $fn: ident, $asn: ident) => { - impl $cl for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - { - type Output = Signed; - - fn $fn(self, rhs: Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl<&'a Signed> for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: &'a Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl for &'a Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: &'a Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - - impl<'a,T> $cl> for &'a Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: AddAssign<&'a T> + SubAssign<&'a T>, - T: MulAssign<&'a T> + DivAssign<&'a T> - { - type Output = Signed; - - fn $fn(self, rhs: Signed) -> Signed - { - let mut res = self.clone(); - res.$asn(rhs); - res - } - } - } -} - - diff --git a/src/cryptonum/core.rs b/src/cryptonum/core.rs deleted file mode 100644 index 1f3eda5..0000000 --- a/src/cryptonum/core.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::cmp::Ordering; - -#[inline(always)] -pub fn generic_cmp(a: &[u64], b: &[u64]) -> Ordering { - let mut i = a.len() - 1; - - assert!(a.len() == b.len()); - loop { - match a[i].cmp(&b[i]) { - Ordering::Equal if i == 0 => - return Ordering::Equal, - Ordering::Equal => - i -= 1, - res => - return res - } - } -} - -fn le(a: &[u64], b: &[u64]) -> bool { - generic_cmp(a, b) != Ordering::Greater -} - -pub fn ge(a: &[u64], b: &[u64]) -> bool { - generic_cmp(a, b) != Ordering::Less -} - -#[inline(always)] -pub fn generic_bitand(a: &mut [u64], b: &[u64]) { - let mut i = 0; - - assert!(a.len() == b.len()); - while i < a.len() { - a[i] &= b[i]; - i += 1; - } -} - -#[inline(always)] -pub fn generic_bitor(a: &mut [u64], b: &[u64]) { - let mut i = 0; - - assert!(a.len() == b.len()); - while i < a.len() { - a[i] |= b[i]; - i += 1; - } -} - -#[inline(always)] -pub fn generic_bitxor(a: &mut [u64], b: &[u64]) { - let mut i = 0; - - assert!(a.len() == b.len()); - while i < a.len() { - a[i] ^= b[i]; - i += 1; - } -} - -#[inline(always)] -pub fn generic_not(a: &mut [u64]) { - for x in a.iter_mut() { - *x = !*x; - } -} - -#[inline(always)] -pub fn generic_shl(a: &mut [u64], orig: &[u64], amount: usize) { - let digits = amount / 64; - let bits = amount % 64; - - assert!(a.len() == orig.len()); - for i in 0..a.len() { - if i < digits { - a[i] = 0; - } else { - let origidx = i - digits; - let prev = if origidx == 0 { 0 } else { orig[origidx - 1] }; - let (carry,_) = if bits == 0 { (0, false) } - else { prev.overflowing_shr(64 - bits as u32) }; - a[i] = (orig[origidx] << bits) | carry; - } - } -} - -#[inline(always)] -pub fn generic_shr(a: &mut [u64], orig: &[u64], amount: usize) { - let digits = amount / 64; - let bits = amount % 64; - - assert!(a.len() == orig.len()); - for i in 0..a.len() { - let oldidx = i + digits; - let caridx = i + digits + 1; - let old = if oldidx >= a.len() { 0 } else { orig[oldidx] }; - let carry = if caridx >= a.len() { 0 } else { orig[caridx] }; - let cb = if bits == 0 { 0 } else { carry << (64 - bits) }; - a[i] = (old >> bits) | cb; - } -} - -#[inline(always)] -pub fn generic_add(a: &mut [u64], b: &[u64]) { - let mut carry = 0; - - assert!(a.len() == b.len()); - for i in 0..a.len() { - let x = a[i] as u128; - let y = b[i] as u128; - let total = x + y + carry; - a[i] = total as u64; - carry = total >> 64; - } -} - -#[inline(always)] -pub fn generic_sub(a: &mut [u64], b: &[u64]) { - let mut negated_rhs = b.to_vec(); - generic_not(&mut negated_rhs); - let mut one = Vec::with_capacity(a.len()); - one.resize(a.len(), 0); - one[0] = 1; - generic_add(&mut negated_rhs, &one); - generic_add(a, &negated_rhs); -} - -#[inline(always)] -pub fn generic_mul(a: &mut [u64], orig: &[u64], b: &[u64]) { - assert!(a.len() == orig.len()); - assert!(a.len() == b.len()); - assert!(a == orig); - - // Build the output table. This is a little bit awkward because we don't - // know how big we're running, but hopefully the compiler is smart enough - // to work all this out. - let mut table = Vec::with_capacity(a.len()); - for _ in 0..a.len() { - let mut row = Vec::with_capacity(a.len()); - row.resize(a.len(), 0); - table.push(row); - } - // This uses "simple" grade school techniques to work things out. But, - // for reference, consider two 4 digit numbers: - // - // l0c3 l0c2 l0c1 l0c0 [orig] - // x l1c3 l1c2 l1c1 l1c0 [b] - // ------------------------------------------------------------ - // (l0c3*l1c0) (l0c2*l1c0) (l0c1*l1c0) (l0c0*l1c0) - // (l0c2*l1c1) (l0c1*l1c1) (l0c0*l1c1) - // (l0c1*l1c2) (l0c0*l1c2) - // (l0c0*l1c3) - // ------------------------------------------------------------ - // AAAAA BBBBB CCCCC DDDDD - for line in 0..a.len() { - let maxcol = a.len() - line; - for col in 0..maxcol { - let left = orig[col] as u128; - let right = b[line] as u128; - table[line][col + line] = left * right; - } - } - // ripple the carry across each line, ensuring that each entry in the - // table is 64-bits - for line in 0..a.len() { - let mut carry = 0; - for col in 0..a.len() { - table[line][col] = table[line][col] + carry; - carry = table[line][col] >> 64; - table[line][col] &= 0xFFFFFFFFFFFFFFFF; - } - } - // now do the final addition across the lines, rippling the carry as - // normal - let mut carry = 0; - for col in 0..a.len() { - let mut total = carry; - for line in 0..a.len() { - total += table[line][col]; - } - a[col] = total as u64; - carry = total >> 64; - } -} - -#[inline(always)] -pub fn expanding_mul(a: &[u64], b: &[u64]) -> Vec { - assert!(a.len() == b.len()); - // The maximum size of an n x n digit multiplication is 2n digits, so - // here's our output array. - let mut result = Vec::with_capacity(a.len() * 2); - result.resize(a.len() * 2, 0); - - for (base_idx, digit) in b.iter().enumerate() { - let mut myrow = Vec::with_capacity(a.len() * 2); - let mut carry = 0; - - myrow.resize(a.len() * 2, 0); - for (col_idx, digit2) in a.iter().enumerate() { - let left = *digit2 as u128; - let right = *digit as u128; - let combo = (left * right) + carry; - - myrow[base_idx + col_idx] = combo as u64; - carry = combo >> 64; - } - generic_add(&mut result, &myrow); - } - result -} - -#[inline(always)] -pub fn generic_div(inx: &[u64], iny: &[u64], - outq: &mut [u64], outr: &mut [u64]) -{ - assert!(inx.len() == inx.len()); - assert!(inx.len() == iny.len()); - assert!(inx.len() == outq.len()); - assert!(inx.len() == outr.len()); - // This algorithm is from the Handbook of Applied Cryptography, Chapter 14, - // algorithm 14.20. It has a couple assumptions about the inputs, namely that - // n >= t >= 1 and y[t] != 0, where n and t refer to the number of digits in - // the numbers. Which means that if we used the inputs unmodified, we can't - // divide by single-digit numbers. - // - // To deal with this, we multiply inx and iny by 2^64, so that we push out - // t by one. - // - // In addition, this algorithm starts to go badly when y[t] is very small - // and x[n] is very large. Really, really badly. This can be fixed by - // insuring that the top bit is set in y[t], which we can achieve by - // shifting everyone over a maxiumum of 63 bits. - // - // What this means is, just for safety, we add a 0 at the beginning and - // end of each number. - let mut y = iny.to_vec(); - let mut x = inx.to_vec(); - y.insert(0,0); y.push(0); - x.insert(0,0); x.push(0); - // 0. Compute 'n' and 't' - let n = x.len() - 1; - let mut t = y.len() - 1; - while (t > 0) && (y[t] == 0) { t -= 1 } - assert!(y[t] != 0); // this is where division by zero will fire - // 0.5. Figure out a shift we can do such that the high bit of y[t] is - // set, and then shift x and y left by that much. - let additional_shift: usize = y[t].leading_zeros() as usize; - let origx = x.clone(); - let origy = y.clone(); - generic_shl(&mut x, &origx, additional_shift); - generic_shl(&mut y, &origy, additional_shift); - // 1. For j from 0 to (n - 1) do: q_j <- 0 - let mut q = Vec::with_capacity(y.len()); - q.resize(y.len(), 0); - for qj in q.iter_mut() { *qj = 0 } - // 2. While (x >= yb^(n-t)) do the following: - // q_(n-t) <- q_(n-t) + 1 - // x <- x - yb^(n-t) - let mut ybnt = y.clone(); - generic_shl(&mut ybnt, &y, 64 * (n - t)); - while ge(&x, &ybnt) { - q[n-t] = q[n-t] + 1; - generic_sub(&mut 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, then set q_(i-t-1) <- b - 1; otherwise set - // q_(i-t-1) <- floor((x_i * b + x_(i-1)) / y_t). - if x[i] == y[t] { - q[i-t-1] = 0xFFFFFFFFFFFFFFFF; - } else { - let top = ((x[i] as u128) << 64) + (x[i-1] as u128); - let bot = y[t] as u128; - let solution = top / bot; - q[i-t-1] = solution as u64; - } - // 3.2. While (q_(i-t-1)(y_t * b + y_(t-1)) > x_i(b2) + x_(i-1)b + - // x_(i-2)) do: - // q_(i - t - 1) <- q_(i - t 1) - 1. - loop { - let mut left = Vec::with_capacity(x.len()); - left.resize(x.len(), 0); - left[0] = q[i - t - 1]; - let mut leftright = Vec::with_capacity(x.len()); - leftright.resize(x.len(), 0); - leftright[0] = y[t-1]; - - let copy = left.clone(); - generic_mul(&mut left, ©, &leftright); - let mut right = Vec::with_capacity(x.len()); - right.resize(x.len(), 0); - right[0] = x[i-2]; - right[1] = x[i-1]; - right[2] = x[i]; - - if le(&left, &right) { - break - } - - q[i - t - 1] -= 1; - } - // 3.3. x <- x - q_(i - t - 1) * y * b^(i-t-1) - let mut right = Vec::with_capacity(y.len()); - right.resize(y.len(), 0); - right[i - t - 1] = q[i - t - 1]; - let rightclone = right.clone(); - generic_mul(&mut right, &rightclone, &y); - let wentnegative = generic_cmp(&x, &right) == Ordering::Less; - generic_sub(&mut x, &right); - // 3.4. if x < 0 then set x <- x + yb^(i-t-1) and - // q_(i-t-1) <- q_(i-t-1) - 1 - if wentnegative { - let mut ybit1 = y.to_vec(); - generic_shl(&mut ybit1, &y, 64 * (i - t - 1)); - generic_add(&mut x, &ybit1); - q[i - t - 1] -= 1; - } - i -= 1; - } - // 4. r <- x - let finalx = x.clone(); - generic_shr(&mut x, &finalx, additional_shift); - for i in 0..outr.len() { - outr[i] = x[i + 1]; // note that for the remainder, we're dividing by - // our normalization value. - } - // 5. return (q,r) - for i in 0..outq.len() { - outq[i] = q[i]; - } -} diff --git a/src/cryptonum/extended_math.rs b/src/cryptonum/extended_math.rs deleted file mode 100644 index 186a2aa..0000000 --- a/src/cryptonum/extended_math.rs +++ /dev/null @@ -1,71 +0,0 @@ -use cryptonum::signed::Signed; -use cryptonum::traits::*; -use std::ops::*; - -pub fn modinv<'a,T>(e: &T, phi: &T) -> T - where - T: Clone + CryptoNumBase + Ord, - T: AddAssign + SubAssign + MulAssign + DivAssign, - T: Add + Sub + Mul + Div, - &'a T: Sub, - T: 'a -{ - let (_, mut x, _) = extended_euclidean(e, phi); - let int_phi = Signed::::new(phi.clone()); - while x.is_negative() { - x += &int_phi; - } - x.abs() -} - -pub fn modexp(b: &T, e: &T, m: &T) -> T -{ - panic!("modexp") -} - -pub fn extended_euclidean(a: &T, b: &T) -> (Signed, Signed, Signed) - where - T: Clone + CryptoNumBase + Div + Mul + Sub -{ - let posinta = Signed::::new(a.clone()); - let posintb = Signed::::new(b.clone()); - let (mut d, mut x, mut y) = egcd(&posinta, &posintb); - - if d.is_negative() { - d.negate(); - x.negate(); - y.negate(); - } - - (d, x, y) -} - -pub fn egcd(a: &Signed, b: &Signed) -> (Signed,Signed,Signed) - where - T: Clone + CryptoNumBase + Div + Mul + Sub -{ - let mut s = Signed::::zero(); - let mut old_s = Signed::::from_u8(1); - let mut t = Signed::::from_u8(1); - let mut old_t = Signed::::zero(); - let mut r = b.clone(); - let mut old_r = a.clone(); - - while !r.is_zero() { - let quotient = old_r.clone() / r.clone(); - - let prov_r = r.clone(); - let prov_s = s.clone(); - let prov_t = t.clone(); - - r = old_r - (r * "ient); - s = old_s - (s * "ient); - t = old_t - (t * "ient); - - old_r = prov_r; - old_s = prov_s; - old_t = prov_t; - } - - (old_r, old_s, old_t) -} diff --git a/src/cryptonum/mod.rs b/src/cryptonum/mod.rs deleted file mode 100644 index 5e3fd59..0000000 --- a/src/cryptonum/mod.rs +++ /dev/null @@ -1,18 +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 core; -#[macro_use] -mod builder; -//mod extended_math; -// mod primes; -mod signed; -mod traits; -mod unsigned; - -// pub use self::extended_math::{modexp,modinv,extended_euclidean,egcd}; -// pub use self::primes::{probably_prime}; -pub use self::signed::{Signed}; -pub use self::unsigned::{U512,U1024,U2048,U3072,U4096,U7680,U8192,U15360}; diff --git a/src/cryptonum/primes.rs b/src/cryptonum/primes.rs deleted file mode 100644 index 27ae90a..0000000 --- a/src/cryptonum/primes.rs +++ /dev/null @@ -1,129 +0,0 @@ -use cryptonum::extended_math::modexp; -use cryptonum::traits::*; -use rand::Rng; -use std::ops::*; - -static SMALL_PRIMES: [u64; 310] = [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, - 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, - 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, - 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, - 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, - 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, - 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, - 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, - 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, - 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, - 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, - 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, - 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, - 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, - 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, - 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, - 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, - 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053]; - - -pub fn probably_prime(x: &T, g: &mut G, iters: usize) -> bool - where - G: Rng, - T: Clone + PartialOrd + Rem + Sub, - T: CryptoNumBase + CryptoNumSerialization, -{ - for tester in SMALL_PRIMES.iter() { - if (x % T::from_u64(*tester)) == T::zero() { - return false; - } - } - miller_rabin(g, x, iters) -} - -fn miller_rabin(g: &mut G, n: T, iters: usize) -> bool - where - G: Rng, - T: Clone + PartialEq + PartialOrd + Sub, - T: CryptoNumBase + CryptoNumSerialization, -{ - let one = T::from_u8(1); - let two = T::from_u8(2); - let nm1 = n - one; - // Quoth Wikipedia: - // write n - 1 as 2^r*d with d odd by factoring powers of 2 from n - 1 - let mut d = nm1.clone(); - let mut r = 0; - while d.is_even() { - d >>= 1; - r += 1; - assert!(r < n.bit_size()); - } - // WitnessLoop: repeat k times - 'WitnessLoop: for _k in 0..iters { - // pick a random integer a in the range [2, n - 2] - let a = random_in_range(g, &two, &nm1); - // x <- a^d mod n - let mut x = modexp(&a, &d, &n); - // if x = 1 or x = n - 1 then - if (&x == &one) || (&x == &nm1) { - // continue WitnessLoop - continue 'WitnessLoop; - } - // repeat r - 1 times: - for _i in 0..r { - // x <- x^2 mod n - x = modexp(&x, &two, &n); - // if x = 1 then - if &x == &one { - // return composite - return false; - } - // if x = n - 1 then - if &x == &nm1 { - // continue WitnessLoop - continue 'WitnessLoop; - } - } - // return composite - return false; - } - // return probably prime - true -} - -fn random_in_range(rng: &mut G, min: &T, max: &T) -> T - where - G: Rng, - T: CryptoNumSerialization + PartialOrd -{ - assert_eq!(min.byte_size(), max.byte_size()); - loop { - let candidate = random_number(rng, min.byte_size()); - - if (&candidate >= min) && (&candidate < max) { - return candidate; - } - } -} - -fn random_number(rng: &mut G, bytelen: usize) -> T - where - G: Rng, - T: CryptoNumSerialization -{ - let components: Vec = rng.gen_iter().take(bytelen).collect(); - T::from_bytes(&components) -} - - diff --git a/src/cryptonum/signed.rs b/src/cryptonum/signed.rs deleted file mode 100644 index 2c64b28..0000000 --- a/src/cryptonum/signed.rs +++ /dev/null @@ -1,431 +0,0 @@ -use cryptonum::traits::*; -use std::cmp::Ordering; -use std::fmt::{Debug,Error,Formatter}; -use std::ops::*; - -pub struct Signed { - positive: bool, - value: T -} - -impl Signed { - pub fn new(v: T) -> Signed { - Signed{ positive: true, value: v } - } - - pub fn abs(&self) -> T - where T: Clone - { - self.value.clone() - } - - pub fn is_positive(&self) -> bool - where T: CryptoNumBase - { - self.positive && !self.value.is_zero() - } - - pub fn is_negative(&self) -> bool - where T: CryptoNumBase - { - !self.positive && !self.value.is_zero() - } - - pub fn negate(&mut self) - { - self.positive = !self.positive; - } -} - -impl CryptoNumBase for Signed { - fn zero() -> Signed { - Signed{ positive: true, value: T::zero() } - } - fn max_value() -> Signed { - Signed{ positive: true, value: T::max_value() } - } - fn is_zero(&self) -> bool { - self.value.is_zero() - } - fn is_odd(&self) -> bool { - self.value.is_odd() - } - fn is_even(&self) -> bool { - self.value.is_even() - } - fn from_u8(x: u8) -> Signed { - Signed{ positive: true, value: T::from_u8(x) } - } - fn to_u8(&self) -> u8 { - self.value.to_u8() - } - fn from_u16(x: u16) -> Signed { - Signed{ positive: true, value: T::from_u16(x) } - } - fn to_u16(&self) -> u16 { - self.value.to_u16() - } - fn from_u32(x: u32) -> Signed { - Signed{ positive: true, value: T::from_u32(x) } - } - fn to_u32(&self) -> u32 { - self.value.to_u32() - } - fn from_u64(x: u64) -> Signed { - Signed{ positive: true, value: T::from_u64(x) } - } - fn to_u64(&self) -> u64 { - self.value.to_u64() - } -} - -impl CryptoNumFastMod for Signed { - type BarrettMu = T::BarrettMu; - - fn barrett_mu(&self) -> Option { - if self.positive { - self.value.barrett_mu() - } else { - None - } - } - - fn fastmod(&self, mu: &T::BarrettMu) -> Signed { - Signed{ positive: self.positive, value: self.value.fastmod(&mu) } - } -} - -impl Clone for Signed { - fn clone(&self) -> Signed { - Signed{ positive: self.positive, value: self.value.clone() } - } -} - -impl<'a,T: PartialEq> PartialEq<&'a Signed> for Signed { - fn eq(&self, other: &&Signed) -> bool { - (self.positive == other.positive) && (self.value == other.value) - } -} - -impl<'a,T: PartialEq> PartialEq> for &'a Signed { - fn eq(&self, other: &Signed) -> bool { - (self.positive == other.positive) && (self.value == other.value) - } -} - -impl PartialEq for Signed { - fn eq(&self, other: &Signed) -> bool { - (self.positive == other.positive) && (self.value == other.value) - } -} - -impl Eq for Signed {} - -impl Debug for Signed { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - if self.positive { - f.write_str("+")?; - } else { - f.write_str("-")?; - } - self.value.fmt(f) - } -} - -impl Ord for Signed { - fn cmp(&self, other: &Signed) -> Ordering { - match (self.positive, other.positive) { - (true, true) => self.value.cmp(&other.value), - (true, false) => Ordering::Greater, - (false, true) => Ordering::Less, - (false, false) => - self.value.cmp(&other.value).reverse() - } - } -} - -impl PartialOrd for Signed { - fn partial_cmp(&self, other: &Signed) -> Option{ - Some(self.cmp(other)) - } -} - -//------------------------------------------------------------------------------ - -impl Neg for Signed { - type Output = Signed; - - fn neg(self) -> Signed { - Signed { - positive: !self.positive, - value: self.value.clone() - } - } -} - -impl<'a,T: Clone> Neg for &'a Signed { - type Output = Signed; - - fn neg(self) -> Signed { - Signed { - positive: !self.positive, - value: self.value.clone() - } - } -} - -//------------------------------------------------------------------------------ - -impl AddAssign for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign, -{ - fn add_assign(&mut self, other: Signed) { - match (self.positive, other.positive, self.value.cmp(&other.value)) { - // if the signs are the same, we maintain the sign and just increase - // the magnitude - (x, y, _) if x == y => - self.value.add_assign(other.value), - // if the signs are different and the numbers are equal, we just set - // this to zero. However, we actually do the subtraction to make the - // timing roughly similar. - (_, _, Ordering::Equal) => { - self.positive = true; - self.value.sub_assign(other.value); - } - // if the signs are different and the first one is less than the - // second, then we flip the sign and subtract. - (_, _, Ordering::Less) => { - self.positive = !self.positive; - let temp = self.value.clone(); - self.value = other.value.clone(); - self.value.sub_assign(temp); - } - // if the signs are different and the first one is greater than the - // second, then we leave the sign and subtract. - (_, _, Ordering::Greater) => { - self.value.sub_assign(other.value); - } - } - } -} - -impl<'a,T> AddAssign<&'a Signed> for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign, - T: AddAssign<&'a T> + SubAssign<&'a T> -{ - fn add_assign(&mut self, other: &'a Signed) { - match (self.positive, other.positive, self.value.cmp(&other.value)) { - // if the signs are the same, we maintain the sign and just increase - // the magnitude - (x, y, _) if x == y => - self.value.add_assign(&other.value), - // if the signs are different and the numbers are equal, we just set - // this to zero. However, we actually do the subtraction to make the - // timing roughly similar. - (_, _, Ordering::Equal) => { - self.positive = true; - self.value.sub_assign(&other.value); - } - // if the signs are different and the first one is less than the - // second, then we flip the sign and subtract. - (_, _, Ordering::Less) => { - self.positive = !self.positive; - let temp = self.value.clone(); - self.value = other.value.clone(); - self.value.sub_assign(temp); - } - // if the signs are different and the first one is greater than the - // second, then we leave the sign and subtract. - (_, _, Ordering::Greater) => { - self.value.sub_assign(&other.value); - } - } - } -} - -math_operator!(Add,add,add_assign); - -//------------------------------------------------------------------------------ - -impl SubAssign for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign, -{ - fn sub_assign(&mut self, other: Signed) { - let mut other2 = other.clone(); - other2.positive = !other.positive; - self.add_assign(other2); - } -} - -impl<'a,T> SubAssign<&'a Signed> for Signed - where - T: Clone + Ord, - T: AddAssign + SubAssign, - T: AddAssign<&'a T> + SubAssign<&'a T> -{ - fn sub_assign(&mut self, other: &'a Signed) { - let mut other2 = other.clone(); - other2.positive = !other.positive; - self.add_assign(other2); - } -} - -math_operator!(Sub,sub,sub_assign); - -//------------------------------------------------------------------------------ - -impl MulAssign for Signed - where - T: MulAssign -{ - fn mul_assign(&mut self, other: Signed) { - self.positive = !(self.positive ^ other.positive); - self.value *= other.value; - } -} - -impl<'a,T> MulAssign<&'a Signed> for Signed - where - T: MulAssign + MulAssign<&'a T> -{ - fn mul_assign(&mut self, other: &'a Signed) { - self.positive = !(self.positive ^ other.positive); - self.value *= &other.value; - } -} - -math_operator!(Mul,mul,mul_assign); - -//------------------------------------------------------------------------------ - -impl DivAssign for Signed - where - T: DivAssign -{ - fn div_assign(&mut self, other: Signed) { - self.positive = !(self.positive ^ other.positive); - self.value /= other.value; - } -} - -impl<'a,T> DivAssign<&'a Signed> for Signed - where - T: DivAssign + DivAssign<&'a T> -{ - fn div_assign(&mut self, other: &'a Signed) { - self.positive = !(self.positive ^ other.positive); - self.value /= &other.value; - } -} - -math_operator!(Div,div,div_assign); - -//------------------------------------------------------------------------------ - -#[cfg(test)] -mod tests { - use cryptonum::unsigned::U512; - use quickcheck::{Arbitrary,Gen}; - use std::cmp::{max,min}; - use super::*; - - impl Arbitrary for Signed { - fn arbitrary(g: &mut G) -> Signed { - let value = T::arbitrary(g); - if value.is_zero() { - Signed { - positive: true, - value: value - } - } else { - Signed { - positive: g.gen_weighted_bool(2), - value: value - } - } - } - } - - quickcheck! { - fn double_negation(x: Signed) -> bool { - &x == (- (- &x)) - } - } - - quickcheck! { - fn add_associates(x: Signed, y: Signed, z: Signed) - -> bool - { - let mut a = x.clone(); - let mut b = y.clone(); - let mut c = z.clone(); - - // we shift these right because rollover makes for weird behavior - a.value >>= 2; - b.value >>= 2; - c.value >>= 2; - - (&a + (&b + &c)) == ((&a + &b) + &c) - } - fn add_commutes(x: Signed, y: Signed) -> bool { - (&x + &y) == (&y + &x) - } - fn add_identity(x: Signed) -> bool { - let zero = Signed{ positive: true, value: U512::zero() }; - (&x + &zero) == &x - } - } - - quickcheck! { - fn sub_is_add_negation(x: Signed, y: Signed) -> bool { - (&x - &y) == (&x + (- &y)) - } - } - - quickcheck! { - fn mul_associates(x: Signed, y: Signed, z: Signed) - -> bool - { - let mut a = x.clone(); - let mut b = y.clone(); - let mut c = z.clone(); - - // we shift these right because rollover makes for weird behavior - a.value >>= 258; - b.value >>= 258; - c.value >>= 258; - - (&a * (&b * &c)) == ((&a * &b) * &c) - } - fn mul_commutes(x: Signed, y: Signed) -> bool { - (&x * &y) == (&y * &x) - } - fn mul_identity(x: Signed) -> bool { - let one = Signed{ positive: true, value: U512::from_u8(1) }; - (&x * &one) == &x - } - } - - quickcheck! { - fn add_mul_distribution(x:Signed,y:Signed,z:Signed) - -> bool - { - let mut a = x.clone(); - let mut b = y.clone(); - let mut c = z.clone(); - - // we shift these right because rollover makes for weird behavior - a.value >>= 258; - b.value >>= 258; - c.value >>= 258; - - (&a * (&b + &c)) == ((&a * &b) + (&a * &c)) - } - } -} diff --git a/src/cryptonum/traits.rs b/src/cryptonum/traits.rs deleted file mode 100644 index 9a16888..0000000 --- a/src/cryptonum/traits.rs +++ /dev/null @@ -1,58 +0,0 @@ -pub trait CryptoNumBase { - /// Generate the zero value for this type. - fn zero() -> Self; - /// Generate the maximum possible value for this type. - fn max_value() -> Self; - /// Test if the number is zero. - fn is_zero(&self) -> bool; - /// Test if the number is odd (a.k.a., the low bit is set) - fn is_odd(&self) -> bool; - /// Test if the number is even (a.k.a., the low bit is clear) - fn is_even(&self) -> bool; - /// Translate a `u8` to this type. This must be safe. - fn from_u8(x: u8) -> Self; - /// Convert this back into a `u8`. This is the equivalent of masking off - /// the lowest 8 bits and then casting to a `u8`. - fn to_u8(&self) -> u8; - /// Translate a `u16` to this type. This must be safe. - fn from_u16(x: u16) -> Self; - /// Convert this back into a `u16`. This is the equivalent of masking off - /// the lowest 16 bits and then casting to a `u16`. - fn to_u16(&self) -> u16; - /// Translate a `u32` to this type. This must be safe. - fn from_u32(x: u32) -> Self; - /// Convert this back into a `u32`. This is the equivalent of masking off - /// the lowest 32 bits and then casting to a `u32`. - fn to_u32(&self) -> u32; - /// Translate a `u64` to this type. This must be safe. - fn from_u64(x: u64) -> Self; - /// Convert this back into a `u64`. This is the equivalent of masking off - /// the lowest 64 bits and then casting to a `u64`. - fn to_u64(&self) -> u64; -} - -pub trait CryptoNumSerialization { - /// The number of bits used when this number is serialized. - fn bit_size(&self) -> usize; - /// The number of bytes used when this number is serialized. - fn byte_size(&self) -> usize; - /// Convert a number to a series of bytes, in standard order (most to - /// least significant) - fn to_bytes(&self) -> Vec; - /// Convert a series of bytes into the number. The size of the given slice - /// must be greater than or equal to the size of the number, and must be - /// a multiple of 8 bytes long. Unused bytes should be ignored. - fn from_bytes(&[u8]) -> Self; -} - -pub trait CryptoNumFastMod { - /// A related type that can hold the constant required for Barrett - /// reduction. - type BarrettMu; - - /// Compute the Barett constant mu, using this as a modulus, which we can - /// use later to perform faster mod operations. - fn barrett_mu(&self) -> Option; - /// Faster modulo through the use of the Barrett constant, above. - fn fastmod(&self, &Self::BarrettMu) -> Self; -} diff --git a/src/cryptonum/unsigned.rs b/src/cryptonum/unsigned.rs deleted file mode 100644 index 066e096..0000000 --- a/src/cryptonum/unsigned.rs +++ /dev/null @@ -1,14 +0,0 @@ -use cryptonum::core::*; -use cryptonum::traits::*; -use std::cmp::Ordering; -use std::fmt::{Debug,Error,Formatter}; -use std::ops::*; - -construct_unsigned!(U512, BarretMu512, u512, 8); -construct_unsigned!(U1024, BarretMu1024, u1024, 16); -construct_unsigned!(U2048, BarretMu2048, u2048, 32); -construct_unsigned!(U3072, BarretMu3072, u3072, 48); -construct_unsigned!(U4096, BarretMu4096, u4096, 64); -construct_unsigned!(U7680, BarretMu7680, u7680, 120); -construct_unsigned!(U8192, BarretMu8192, u8192, 128); -construct_unsigned!(U15360, BarretMu15360, u15360, 240);