Start experimenting with full generation of all of the numeric types.

Previously, we used a little bit of generation to drive a lot of Rust
macros. This works, but it's a little confusing to read and write. In
addition, we used a lot of implementations with variable timings based
on their input, which isn't great for crypto. This is the start of an
attempt to just generate all of the relevant Rust code directly, and to
use timing-channel resistant implementations for most of the routines.
This commit is contained in:
2019-07-15 17:39:06 -07:00
parent 666378b14b
commit fa872c951a
46 changed files with 696 additions and 203 deletions

View File

@@ -2,7 +2,8 @@
name = "cryptonum" name = "cryptonum"
version = "0.1.0" version = "0.1.0"
authors = ["awick"] authors = ["awick"]
edition = "2018"
[dependencies] [dependencies]
quickcheck = "^0.7.2" # quickcheck = "^0.7.2"
rand = "^0.6.0" # rand = "^0.6.0"

13
generation/LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Copyright (c) 2019 Adam Wick
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

2
generation/Setup.hs Normal file
View File

@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

View File

@@ -0,0 +1,29 @@
cabal-version: 2.0
-- Initial package description 'generation.cabal' generated by 'cabal
-- init'. For further documentation, see
-- http://haskell.org/cabal/users-guide/
name: generation
version: 0.1.0.0
synopsis: Generates the cryptonum Rust library, based on requirements.
homepage: http://github.com/acw/cryptonum
license: ISC
license-file: LICENSE
author: Adam Wick
maintainer: awick@uhsure.com
copyright: 2019
category: Math
build-type: Simple
extra-source-files: CHANGELOG.md
executable generation
main-is: Main.hs
other-modules: Gen, Requirements, UnsignedBase
-- other-extensions:
build-depends: base ^>=4.12.0.0,
containers,
directory,
filepath,
mtl
hs-source-dirs: src
default-language: Haskell2010

73
generation/src/Gen.hs Normal file
View File

@@ -0,0 +1,73 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Gen(
Gen(Gen),
runGen,
gensym,
indent,
blank,
out,
wrapIndent,
)
where
import Control.Monad.RWS.Strict(RWS,evalRWS)
import Control.Monad.State.Class(MonadState,get,put)
import Control.Monad.Writer.Class(MonadWriter,tell)
import Data.List(replicate)
import Data.Word(Word)
newtype Gen a = Gen { unGen :: RWS () String GenState a}
deriving (Applicative, Functor, Monad, MonadState GenState, MonadWriter String)
tabAmount :: Word
tabAmount = 4
data GenState = GenState {
indentAmount :: Word,
gensymIndex :: Word
}
initGenState :: GenState
initGenState = GenState { indentAmount = 0, gensymIndex = 0 }
runGen :: FilePath -> Gen a -> IO a
runGen path action =
do let (res, contents) = evalRWS (unGen action) () initGenState
writeFile path contents
return res
gensym :: String -> Gen String
gensym prefix =
do gs <- get
let gs' = gs{ gensymIndex = gensymIndex gs + 1 }
put gs'
return (prefix ++ show (gensymIndex gs))
indent :: Gen a -> Gen a
indent action =
do gs <- get
put gs{ indentAmount = indentAmount gs + tabAmount }
res <- action
put gs
return res
blank :: Gen ()
blank = tell "\n"
out :: String -> Gen ()
out val =
do gs <- get
tell (replicate (fromIntegral (indentAmount gs)) ' ')
tell val
tell "\n"
wrapIndent :: String -> Gen a -> Gen a
wrapIndent val middle =
do gs <- get
tell (replicate (fromIntegral (indentAmount gs)) ' ')
tell val
tell " {\n"
res <- indent middle
tell (replicate (fromIntegral (indentAmount gs)) ' ')
tell "}\n"
return res

32
generation/src/Main.hs Normal file
View File

@@ -0,0 +1,32 @@
module Main
where
import Control.Monad(forM_,unless)
import Data.List(sort)
import Data.Map.Strict(Map)
import qualified Data.Map.Strict as Map
import Gen(runGen)
import Requirements(Requirement(..), Operation(..), requirements)
import System.Directory(createDirectoryIfMissing)
import System.Environment(getArgs)
import System.Exit(die)
import System.FilePath((</>))
import UnsignedBase(declareBaseStructure)
gatherRequirements :: [Requirement] -> Map Int [Operation]
gatherRequirements = foldr process Map.empty
where process (Req x val) = Map.insertWith (++) x [val]
main :: IO ()
main =
do args <- getArgs
unless (length args == 1) $
die ("generation takes exactly one argument, the target directory")
let reqs = sort (Map.toList (gatherRequirements requirements))
target = head args
forM_ reqs $ \ (size, opes) ->
do let basedir = target </> "unsigned" </> ("u" ++ show size)
createDirectoryIfMissing True basedir
forM_ reqs $ \ (x, ops) ->
do runGen (basedir </> "mod.rs") (declareBaseStructure size ops)

View File

@@ -0,0 +1,278 @@
module Requirements(
Operation(..),
Requirement(..),
requirements
)
where
import Data.List(sort)
data Operation = Add
| BaseOps
| Barretts
| Div
| ModDiv
| ModExp
| ModMul
| ModSq
| Mul
| Scale
| Shifts
| Square
| Sub
| Convert Int
| SignedAdd
| SignedBase
| SignedCmp
| SignedShift
| SignedSub
| SignedMul
| SignedDiv
| SignedModInv
| SignedScale
| SigConvert Int
| SquareRoot
| EGCD
| ModInv
| PrimeGen
| RSA
| DSA
| ECDSA
deriving (Eq, Ord, Show)
data Requirement = Req Int Operation
deriving (Eq, Ord, Show)
data Need = Need Operation (Int -> [Requirement])
needs :: [Need]
needs = [ Need RSA (\ size -> [Req (size `div` 2) Sub,
Req (size `div` 2) Mul,
Req (size `div` 2) PrimeGen,
Req size BaseOps,
Req size ModInv,
Req size ModExp
])
, Need DSA (\ size -> [Req size BaseOps,
Req size Shifts,
Req size Add,
Req size SquareRoot,
Req size PrimeGen,
Req size ModInv,
Req size Mul,
Req (size * 2) Add,
Req (((size * 2) + 64) * 2) Div,
Req size (Convert 512),
Req size (Convert (size + 128)),
Req size (Convert ((size * 2) + 64)),
Req size (Convert (((size * 2) + 64) * 2))
])
, Need ECDSA (\ size -> [Req size SignedSub,
Req size SignedMul,
Req size ModMul,
Req size ModDiv,
Req (size * 2) BaseOps,
Req (size * 2) SignedBase,
Req (size * 2) SignedShift,
Req (size * 2) SignedSub,
Req (size * 2) SignedMul,
Req (size * 2) SignedDiv,
Req ((size * 2) + 64) SignedBase,
Req ((size * 2) + 64) BaseOps,
Req ((size * 2) + 64) SignedAdd,
Req ((size * 2) + 64) SignedShift,
Req ((size * 2) + 64) ModDiv,
Req size (Convert (size * 2)),
Req size (SigConvert (size * 2)),
Req size (Convert ((size * 2) + 64)),
Req size (SigConvert ((size * 2) + 64)),
Req (size * 2) (Convert ((size * 2) + 64)),
Req (size * 2) (SigConvert ((size * 2) + 64)),
Req size (Convert (size * 4)),
Req (size * 4) Div
])
, Need PrimeGen (\ size -> [Req size Div,
Req size Shifts,
Req size ModExp,
Req size EGCD])
, Need Add (\ size -> [Req size BaseOps,
Req (size + 64) BaseOps,
Req size (Convert (size + 64))
])
, Need Barretts (\ size -> [Req size BaseOps,
Req (size + 64) BaseOps,
Req (size * 2) BaseOps,
Req ((size * 2) + 64) BaseOps,
Req size (Convert ((size * 2) + 64)),
Req (size + 64) Mul,
Req ((size * 2) + 64) Add,
Req ((size * 2) + 64) Sub,
Req (size + 64) (Convert ((size * 2) + 64)),
Req ((size * 2) + 64) (Convert ((size + 64) * 2)),
Req (size * 2) (Convert ((size * 2) + 64)),
Req (size + 64) (Convert ((size + 64) * 2)),
Req (size + 64) (Convert (size * 2)),
Req (size * 2) Shifts,
Req ((size + 64) * 2) Shifts,
Req ((size * 2) + 64) Div
])
, Need Div (\ size -> [Req size BaseOps,
Req (size * 2) BaseOps,
Req size (Convert (size * 2)),
Req (size * 2) Sub,
Req size Mul,
Req 192 BaseOps,
Req 192 Mul,
Req 384 BaseOps
])
, Need ModExp (\ size -> [Req size BaseOps,
Req size Barretts,
Req size ModSq,
Req size ModMul,
Req size (Convert (size + 64))
])
, Need ModMul (\ size -> [Req size BaseOps,
Req (size * 2) BaseOps,
Req size Barretts,
Req size Mul,
Req size (Convert (size + 64))
])
, Need ModDiv (\ size -> [Req size ModInv,
Req size SignedModInv,
Req size SignedMul,
Req size SignedDiv,
Req (size * 2) SignedDiv,
Req size (SigConvert (size * 2))
])
, Need ModSq (\ size -> [Req size BaseOps,
Req (size * 2) BaseOps,
Req size Barretts,
Req size Square,
Req (size * 2) Div,
Req size (Convert (size * 2)),
Req size (Convert (size + 64))
])
, Need Mul (\ size -> [Req size BaseOps,
Req size Scale,
Req (size * 2) BaseOps,
Req size (Convert (size * 2))
])
, Need Scale (\ size -> [Req (size + 64) BaseOps])
, Need Shifts (\ size -> [Req size BaseOps
])
, Need Square (\ size -> [Req size BaseOps,
Req (size * 2) BaseOps
])
, Need Sub (\ size -> [Req size BaseOps
])
, Need SignedAdd (\ size -> [Req size SignedBase,
Req size Add,
Req size Sub,
Req (size + 64) SignedBase,
Req (size + 64) BaseOps
])
, Need SignedBase (\ size -> [Req size BaseOps])
, Need SignedCmp (\ size -> [Req size BaseOps])
, Need SignedShift (\ size -> [Req size SignedBase,
Req size BaseOps,
Req size Shifts,
Req size Add
])
, Need SignedSub (\ size -> [Req size SignedBase,
Req (size + 64) SignedBase,
Req (size + 64) BaseOps,
Req size Add,
Req size Sub,
Req (size + 64) Sub,
Req size (Convert (size + 64)),
Req size (SigConvert (size + 64))
])
, Need SignedMul (\ size -> [Req size Mul,
Req size SignedScale,
Req (size * 2) SignedBase,
Req size (SigConvert (size * 2)),
Req size Square
])
, Need SignedDiv (\ size -> [Req size Div,
Req size Add
])
, Need EGCD (\ size -> [Req size SignedBase,
Req size BaseOps,
Req size Shifts,
Req (size + 64) SignedBase,
Req ((size + 64) * 2) SignedBase,
Req size (SigConvert (size + 64)),
Req (size + 64) SignedShift,
Req (size + 64) SignedAdd,
Req (size + 64) SignedSub,
Req (size + 64) SignedCmp,
Req (size + 64) SignedDiv,
Req (size + 64) SignedMul,
Req ((size + 64) * 2) SignedSub,
Req (size + 64) (Convert (((size + 64) * 2) + 64)),
Req (size + 64) (SigConvert (((size + 64) * 2) + 64))
])
, Need ModInv (\ size -> [Req size BaseOps,
Req (size + 64) SignedBase,
Req (size + 64) BaseOps,
Req size (Convert (size + 64)),
Req size EGCD,
Req (size + 64) SignedAdd,
Req size Barretts
])
, Need SignedModInv (\ size -> [
Req size EGCD,
Req size SignedModInv
])
, Need SquareRoot (\ size -> [Req size BaseOps,
Req size Shifts,
Req size Add,
Req size Sub
])
]
newRequirements :: Requirement -> [Requirement]
newRequirements (Req size op) = concatMap go needs ++ [Req size BaseOps]
where
go (Need op2 generator) | op == op2 = generator size
| otherwise = []
rsaSizes :: [Int]
rsaSizes = [512,1024,2048,3072,4096,8192,15360]
dsaSizes :: [Int]
dsaSizes = [192,256,1024,2048,3072]
ecdsaSizes :: [Int]
ecdsaSizes = [192,256,384,576]
baseRequirements :: [Requirement]
baseRequirements = concatMap (\ x -> [Req x RSA]) rsaSizes
++ concatMap (\ x -> [Req x DSA]) dsaSizes
++ concatMap (\ x -> [Req x ECDSA]) ecdsaSizes
++ [Req 192 (Convert 1024), Req 256 (Convert 2048), Req 256 (Convert 3072)] -- used in DSA
++ [Req 384 (Convert 1024), Req 512 (Convert 2048), Req 512 (Convert 3072)] -- used in DSA
++ [Req 192 Add, Req 256 Add, Req 384 Add] -- used for testing
++ [Req 192 Mul, Req 384 Mul] -- used for testing
++ [Req 448 (Convert 512)] -- used for testing
requirements :: [Requirement]
requirements = go baseRequirements
where
step ls = let news = concatMap newRequirements ls
ls' = concatMap sanitizeConverts (news ++ ls)
ls'' = removeDups (sort ls')
in ls''
--
go ls = let ls' = step ls
in if ls == ls' then ls else go ls'
--
removeDups [] = []
removeDups (x:xs) | x `elem` xs = removeDups xs
| otherwise = x : removeDups xs
--
sanitizeConverts (Req x (Convert y))
| x == y = []
| x < y = [Req x (Convert y), Req y BaseOps]
| otherwise = [Req y (Convert x), Req x BaseOps]
sanitizeConverts x = [x]

View File

@@ -0,0 +1,89 @@
module UnsignedBase(
declareBaseStructure
)
where
import Control.Monad(forM_)
import Gen
import Requirements(Operation)
declareBaseStructure :: Int -> [Operation] -> Gen ()
declareBaseStructure bitsize ops =
do let name = "U" ++ show bitsize
entries = bitsize `div` 64
top = entries - 1
out "use core::cmp::{Eq,Ordering,PartialEq,min};"
out "use core::fmt;"
out "use super::super::CryptoNum;"
blank
out "mod binary_ops;"
blank
wrapIndent ("pub struct " ++ name) $
out ("value: [u64; " ++ show entries ++ "]")
blank
wrapIndent ("impl CryptoNum for " ++ name) $
do wrapIndent ("fn zero() -> Self") $
out (name ++ "{ value: [0; " ++ show entries ++ "] }")
blank
wrapIndent ("fn is_zero(&self) -> bool") $
do forM_ (reverse [1..top]) $ \ i ->
out ("self.value[" ++ show i ++ "] == 0 &&")
out "self.value[0] == 0"
blank
wrapIndent ("fn is_even(&self) -> bool") $
out "self.value[0] & 0x1 == 0"
blank
wrapIndent ("fn is_odd(&self) -> bool") $
out "self.value[0] & 0x1 == 0"
blank
wrapIndent ("fn bit_length() -> usize") $
out (show bitsize)
blank
wrapIndent ("fn mask(&mut self, len: usize)") $
do out ("let dellen = min(len, " ++ show entries ++ ");")
wrapIndent ("for i in dellen.." ++ show entries) $
out ("self.value[i] = 0;")
blank
wrapIndent ("fn testbit(&self, bit: usize) -> bool") $
do out "let idx = bit / 64;"
out "let offset = bit % 64;"
wrapIndent ("if idx >= " ++ show entries) $
out "return false;"
out "(self.value[idx] & (1u64 << offset)) != 0"
blank
wrapIndent ("impl PartialEq for " ++ name) $
wrapIndent "fn eq(&self, other: &Self) -> bool" $
do forM_ (reverse [1..top]) $ \ i ->
out ("self.value[" ++ show i ++ "] == other.value[" ++ show i ++ "] && ")
out "self.value[0] == other.value[0]"
blank
out ("impl Eq for " ++ name ++ " {}")
blank
wrapIndent ("impl Ord for " ++ name) $
wrapIndent "fn cmp(&self, other: &Self) -> Ordering" $
do out ("self.value[" ++ show top ++ "].cmp(&other.value[" ++ show top ++ "])")
forM_ (reverse [0..top-1]) $ \ i ->
out (" .then(self.value[" ++ show i ++ "].cmp(&other.value[" ++ show i ++ "]))")
blank
wrapIndent ("impl PartialOrd for " ++ name) $
wrapIndent "fn partial_cmp(&self, other: &Self) -> Option<Ordering>" $
out "Some(self.cmp(other))"
blank
wrapIndent ("impl fmt::Debug for " ++ name) $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do out ("f.debug_tuple(" ++ show name ++ ")")
forM_ [0..top] $ \ i ->
out (" .field(&self.value[" ++ show i ++ "])")
out " .finish()"
blank
wrapIndent ("impl fmt::UpperHex for " ++ name) $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do forM_ (reverse [1..top]) $ \ i ->
out ("write!(f, \"{:X}\", self.value[" ++ show i ++ "])?;")
out "write!(f, \"{:X}\", self.value[0])"
blank
wrapIndent ("impl fmt::LowerHex for " ++ name) $
wrapIndent "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result" $
do forM_ (reverse [1..top]) $ \ i ->
out ("write!(f, \"{:x}\", self.value[" ++ show i ++ "])?;")
out "write!(f, \"{:x}\", self.value[0])"

52
old/signed/mod.rs Normal file
View File

@@ -0,0 +1,52 @@
//! This module includes a large number of signed integer types for very
//! large integers, designed to try to match good performance with a high
//! assurance threshold.
//!
//! The types provided in this module, and the functions available for each
//! of those types, is derived from standard bit widths for RSA, DSA, and
//! Elliptic Curve encryption schemes. If this library does not include a
//! function you would like for another cryptographic scheme, please reach
//! out to the authors; in many cases, the relevant code can be automatically
//! generated.
//!
#[macro_use]
mod add;
#[macro_use]
mod base;
#[macro_use]
mod compare;
#[macro_use]
mod conversion;
#[macro_use]
mod div;
#[macro_use]
mod egcd;
#[macro_use]
mod moddiv;
#[macro_use]
mod modinv;
#[macro_use]
mod mul;
#[macro_use]
mod scale;
#[macro_use]
mod shift;
#[macro_use]
mod subtraction;
use quickcheck::{Arbitrary,Gen};
use std::cmp::{Ord,Ordering,PartialOrd};
use std::fmt;
use std::ops::{Add,AddAssign};
use std::ops::{Div,DivAssign};
use std::ops::{Mul,MulAssign};
use std::ops::{Rem,RemAssign};
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
use std::ops::{Sub,SubAssign};
use unsigned::*;
pub use self::egcd::EGCD;
pub use self::moddiv::ModDiv;
pub use self::modinv::ModInv;
include!("invoc.rs");

104
old/unsigned/mod.rs Normal file
View File

@@ -0,0 +1,104 @@
//! This module includes a large number of unsigned integer types for very
//! large integers, designed to try to match good performance with a high
//! assurance threshold.
//!
//! The types provided in this module, and the functions available for each
//! of those types, is derived from standard bit widths for RSA, DSA, and
//! Elliptic Curve encryption schemes. If this library does not include a
//! function you would like for another cryptographic scheme, please reach
//! out to the authors; in many cases, the relevant code can be automatically
//! generated.
//!
//! For performance reasons, we also include support for Barrett reduction,
//! which should improve the speed of modular reduction of large numbers for
//! those cases in which you will be frequently performing modulo operations
//! using the same modulus.
#[macro_use]
mod add;
#[macro_use]
mod barrett;
#[macro_use]
mod base;
#[macro_use]
mod cmp;
#[macro_use]
mod codec;
#[macro_use]
mod conversion;
#[macro_use]
mod div;
#[macro_use]
mod formatter;
#[macro_use]
mod modexp;
#[macro_use]
mod modmul;
#[macro_use]
mod modsq;
#[macro_use]
mod mul;
#[macro_use]
mod primes;
#[macro_use]
mod rand;
#[macro_use]
mod scale;
#[macro_use]
mod shifts;
#[macro_use]
mod sqrt;
#[macro_use]
mod square;
#[macro_use]
mod sub;
pub use self::base::CryptoNum;
pub use self::codec::{Encoder,Decoder};
pub use self::div::DivMod;
pub use self::modexp::ModExp;
pub use self::modmul::ModMul;
pub use self::modsq::ModSquare;
pub use self::primes::PrimeGen;
pub use self::square::Square;
pub use self::sqrt::SquareRoot;
pub(crate) use self::add::unsafe_addition;
pub(crate) use self::scale::scale;
use rand::{Rng,RngCore};
use rand::distributions::{Distribution,Standard};
use rand::distributions::uniform::*;
use self::add::addition;
use self::cmp::compare;
use self::codec::raw_decoder;
use self::div::get_number_size;
use self::formatter::tochar;
use self::mul::{multiply,multiply_small};
use self::primes::SMALL_PRIMES;
use self::shifts::{shiftl,shiftr};
use self::sub::subtract;
use std::cmp::{Ordering,min};
use std::fmt;
use std::fmt::Write;
use std::ops::{Add,AddAssign};
use std::ops::{Mul,MulAssign};
use std::ops::{Div,DivAssign};
use std::ops::{Rem,RemAssign};
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
use std::ops::{Sub,SubAssign};
use std::ops::{BitAnd,BitOr};
use quickcheck::{Arbitrary,Gen};
macro_rules! base_impls
{
($name: ident, $size: expr) => {
generate_base!($name, $size);
generate_base_conversions!($name);
generate_codec!($name);
generate_formatter!($name);
cmp_impls!($name);
}
}
include!("invoc.rs");

View File

@@ -1,49 +1,24 @@
extern crate quickcheck; #![no_std]
extern crate rand;
pub mod signed; pub mod signed;
pub mod unsigned; pub mod unsigned;
#[cfg(test)]
pub mod testing;
#[cfg(test)] /// A trait definition for large numbers.
mod arithmetic { pub trait CryptoNum {
use super::signed::*; /// Generate a new value of the given type.
use super::unsigned::*; fn zero() -> Self;
/// Test if the number is zero.
fn is_zero(&self) -> bool;
/// Test if the number is even.
fn is_even(&self) -> bool;
/// Test if the number is odd.
fn is_odd(&self) -> bool;
/// The size of this number in bits.
fn bit_length() -> usize;
/// Mask off the high parts of the number. In particular, it
/// zeros the bits above (len * 64).
fn mask(&mut self, len: usize);
/// Test if the given bit is zero, where bits are numbered in
/// least-significant order (0 is the LSB, etc.).
fn testbit(&self, bit: usize) -> bool;
}
quickcheck! {
fn commutivity_signed_add(x: I576, y: I576) -> bool {
(&x + &y) == (&y + &x)
}
fn commutivity_unsigned_add(x: U576, y: U576) -> bool {
(&x + &y) == (&y + &x)
}
fn commutivity_unsigned_mul(x: U192, y: U192) -> bool {
(&x * &y) == (&y * &x)
}
fn associativity_unsigned_add(x: U192, y: U192, z: U192) -> bool {
(U256::from(&x) + (&y + &z)) == ((&x + &y) + U256::from(&z))
}
fn associativity_unsigned_mul(x: U192, y: U192, z: U192) -> bool {
(U384::from(&x) * (&y * &z)) == ((&x * &y) * U384::from(&z))
}
fn identity_signed_add(x: I576) -> bool {
(&x + I576::zero()) == I640::from(&x)
}
fn identity_unsigned_add(x: U576) -> bool {
(&x + U576::zero()) == U640::from(&x)
}
fn identity_unsigned_mul(x: U192) -> bool {
(&x * U192::from(1u64)) == U384::from(&x)
}
fn additive_inverse(x: I576) -> bool {
(&x + x.negate()) == I640::zero()
}
fn distribution(x: U192, y: U192, z: U192) -> bool {
(U256::from(&x) * (&y + &z)) == U512::from((&x * &y) + (&x * &z))
}
}
}

View File

@@ -1,52 +0,0 @@
//! This module includes a large number of signed integer types for very
//! large integers, designed to try to match good performance with a high
//! assurance threshold.
//!
//! The types provided in this module, and the functions available for each
//! of those types, is derived from standard bit widths for RSA, DSA, and
//! Elliptic Curve encryption schemes. If this library does not include a
//! function you would like for another cryptographic scheme, please reach
//! out to the authors; in many cases, the relevant code can be automatically
//! generated.
//!
#[macro_use]
mod add;
#[macro_use]
mod base;
#[macro_use]
mod compare;
#[macro_use]
mod conversion;
#[macro_use]
mod div;
#[macro_use]
mod egcd;
#[macro_use]
mod moddiv;
#[macro_use]
mod modinv;
#[macro_use]
mod mul;
#[macro_use]
mod scale;
#[macro_use]
mod shift;
#[macro_use]
mod subtraction;
use quickcheck::{Arbitrary,Gen};
use std::cmp::{Ord,Ordering,PartialOrd};
use std::fmt;
use std::ops::{Add,AddAssign};
use std::ops::{Div,DivAssign};
use std::ops::{Mul,MulAssign};
use std::ops::{Rem,RemAssign};
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
use std::ops::{Sub,SubAssign};
use unsigned::*;
pub use self::egcd::EGCD;
pub use self::moddiv::ModDiv;
pub use self::modinv::ModInv;
include!("invoc.rs");

View File

@@ -1,104 +1 @@
//! This module includes a large number of unsigned integer types for very mod u192;
//! large integers, designed to try to match good performance with a high
//! assurance threshold.
//!
//! The types provided in this module, and the functions available for each
//! of those types, is derived from standard bit widths for RSA, DSA, and
//! Elliptic Curve encryption schemes. If this library does not include a
//! function you would like for another cryptographic scheme, please reach
//! out to the authors; in many cases, the relevant code can be automatically
//! generated.
//!
//! For performance reasons, we also include support for Barrett reduction,
//! which should improve the speed of modular reduction of large numbers for
//! those cases in which you will be frequently performing modulo operations
//! using the same modulus.
#[macro_use]
mod add;
#[macro_use]
mod barrett;
#[macro_use]
mod base;
#[macro_use]
mod cmp;
#[macro_use]
mod codec;
#[macro_use]
mod conversion;
#[macro_use]
mod div;
#[macro_use]
mod formatter;
#[macro_use]
mod modexp;
#[macro_use]
mod modmul;
#[macro_use]
mod modsq;
#[macro_use]
mod mul;
#[macro_use]
mod primes;
#[macro_use]
mod rand;
#[macro_use]
mod scale;
#[macro_use]
mod shifts;
#[macro_use]
mod sqrt;
#[macro_use]
mod square;
#[macro_use]
mod sub;
pub use self::base::CryptoNum;
pub use self::codec::{Encoder,Decoder};
pub use self::div::DivMod;
pub use self::modexp::ModExp;
pub use self::modmul::ModMul;
pub use self::modsq::ModSquare;
pub use self::primes::PrimeGen;
pub use self::square::Square;
pub use self::sqrt::SquareRoot;
pub(crate) use self::add::unsafe_addition;
pub(crate) use self::scale::scale;
use rand::{Rng,RngCore};
use rand::distributions::{Distribution,Standard};
use rand::distributions::uniform::*;
use self::add::addition;
use self::cmp::compare;
use self::codec::raw_decoder;
use self::div::get_number_size;
use self::formatter::tochar;
use self::mul::{multiply,multiply_small};
use self::primes::SMALL_PRIMES;
use self::shifts::{shiftl,shiftr};
use self::sub::subtract;
use std::cmp::{Ordering,min};
use std::fmt;
use std::fmt::Write;
use std::ops::{Add,AddAssign};
use std::ops::{Mul,MulAssign};
use std::ops::{Div,DivAssign};
use std::ops::{Rem,RemAssign};
use std::ops::{Shl,ShlAssign,Shr,ShrAssign};
use std::ops::{Sub,SubAssign};
use std::ops::{BitAnd,BitOr};
use quickcheck::{Arbitrary,Gen};
macro_rules! base_impls
{
($name: ident, $size: expr) => {
generate_base!($name, $size);
generate_base_conversions!($name);
generate_codec!($name);
generate_formatter!($name);
cmp_impls!($name);
}
}
include!("invoc.rs");