Rewrite against a newer cryptonum.

This commit is contained in:
2018-11-14 20:51:14 -05:00
parent ef54ed4cda
commit 9d87916cc5
19 changed files with 39432 additions and 29387 deletions

4
.gitignore vendored
View File

@@ -19,3 +19,7 @@ Cargo.lock
**/gen
**/.cabal-sandbox
**/cabal.sandbox.config
FlameGraph
*.user_stacks
**/.ghc.environment.*
tests/rsa/dist*

View File

@@ -10,6 +10,7 @@ repository = "https://github.com/acw/simple_crypto"
[dependencies]
byteorder = "^1.2.3"
cryptonum = { path = "../cryptonum" }
digest = "^0.7.1"
num = "^0.1.42"
rand = "^0.3"

View File

@@ -10,9 +10,9 @@
//! when they should use it, and examples. For now, it mostly just fowards
//! off to more detailed modules. Help requested!
extern crate byteorder;
extern crate cryptonum;
extern crate digest;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
extern crate num;
extern crate rand;
@@ -20,12 +20,10 @@ extern crate sha1;
extern crate sha2;
extern crate simple_asn1;
/// The `cryptonum` module provides support for large numbers at fixed,
/// cryptographically-relevant sizes.
pub mod cryptonum;
/// The `rsa` module provides bare-bones support for RSA signing, verification,
/// encryption, decryption, and key generation.
pub mod rsa;
#[cfg(test)]
mod testing;
mod utils;

View File

@@ -41,7 +41,8 @@ pub use self::public::{RSAPublic, RSAPublicKey,
RSA3072Public, RSA4096Public, RSA8192Public,
RSA15360Public};
use cryptonum::*;
use cryptonum::signed::{ModInv};
use cryptonum::unsigned::{U256,U512,U1024,U1536,U2048,U3072,U4096,U7680,U8192,U15360};
use rand::Rng;
macro_rules! generate_rsa_pair
@@ -64,10 +65,12 @@ macro_rules! generate_rsa_pair
loop {
let e = $uint::from(65537u32);
let (p, q) = $pair::generate_pq(rng, &e);
let one = $half::from(1u32);
let phi = &(&p - &one) * &(&q - &one);
let one: $half = $half::from(1u32);
let pminus1: $half = &p - &one;
let qminus1: $half = &q - &one;
let phi: $uint = pminus1 * qminus1;
let n = &p * &q;
if let Some(d) = e.modinv(phi) {
if let Some(d) = e.modinv(&phi) {
let public = $pub::new(n.clone(), e);
let private = $priv::new(n, d);
return $pair::new(public, private);

View File

@@ -1,4 +1,4 @@
use cryptonum::*;
use cryptonum::unsigned::*;
use digest::{FixedOutput,Input};
use rsa::core::{drop0s,pkcs1_pad,xor_vecs};
use rsa::errors::RSAError;
@@ -55,7 +55,7 @@ macro_rules! generate_rsa_private
impl RSAPrivateKey<$num> for $rsa {
fn new(n: $num, d: $num) -> $rsa {
let nu = $bar::new(&n);
let nu = $bar::new(n.clone());
$rsa { nu: nu, d: d }
}
@@ -157,12 +157,12 @@ generate_rsa_private!(RSA8192Private, U8192, BarrettU8192, 8192);
generate_rsa_private!(RSA15360Private, U15360, BarrettU15360, 15360);
macro_rules! generate_tests {
( $( ($mod: ident, $rsa: ident, $num: ident, $size: expr) ),* ) => {
( $( ($mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) ),* ) => {
$(
#[cfg(test)]
#[allow(non_snake_case)]
mod $mod {
use cryptonum::Decoder;
use cryptonum::unsigned::Decoder;
use super::*;
use testing::run_test;
use rsa::signing_hashes::*;
@@ -172,17 +172,22 @@ macro_rules! generate_tests {
#[test]
fn sign() {
let fname = format!("tests/rsa/rsa{}.test", $size);
run_test(fname.to_string(), 6, |case| {
run_test(fname.to_string(), 8, |case| {
let (neg0, dbytes) = case.get("d").unwrap();
let (neg1, nbytes) = case.get("n").unwrap();
let (neg2, hbytes) = case.get("h").unwrap();
let (neg3, mbytes) = case.get("m").unwrap();
let (neg4, sbytes) = case.get("s").unwrap();
let (neg5, ubytes) = case.get("u").unwrap();
let (neg6, kbytes) = case.get("k").unwrap();
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4);
let n = $num::from_bytes(nbytes);
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5&&!neg6);
let n = $num64::from_bytes(nbytes);
let nu = $num64::from_bytes(ubytes);
let bigk = $num::from_bytes(kbytes);
let k = usize::from(bigk);
let d = $num::from_bytes(dbytes);
let privkey = $rsa::new(n, d);
let privkey = $rsa{ nu: $bar::from_components(k, n, nu), d: d };
let hashnum = ((hbytes[0] as u16)<<8) + (hbytes[1] as u16);
let sighash = match hashnum {
0x160 => &SIGNING_HASH_SHA1,
@@ -200,17 +205,22 @@ macro_rules! generate_tests {
#[test]
fn decrypt() {
let fname = format!("tests/rsa/rsa{}.test", $size);
run_test(fname.to_string(), 6, |case| {
run_test(fname.to_string(), 8, |case| {
let (neg0, dbytes) = case.get("d").unwrap();
let (neg1, nbytes) = case.get("n").unwrap();
let (neg2, hbytes) = case.get("h").unwrap();
let (neg3, mbytes) = case.get("m").unwrap();
let (neg4, cbytes) = case.get("c").unwrap();
let (neg5, ubytes) = case.get("u").unwrap();
let (neg6, kbytes) = case.get("k").unwrap();
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4);
let n = $num::from_bytes(nbytes);
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5&&!neg6);
let n = $num64::from_bytes(nbytes);
let nu = $num64::from_bytes(ubytes);
let bigk = $num::from_bytes(kbytes);
let k = usize::from(bigk);
let d = $num::from_bytes(dbytes);
let privkey = $rsa::new(n, d);
let privkey = $rsa{ nu: $bar::from_components(k, n, nu), d: d };
let hashnum = ((hbytes[0] as u16)<<8) + (hbytes[1] as u16);
let empty = "".to_string();
match hashnum {
@@ -253,11 +263,11 @@ macro_rules! generate_tests {
}
}
generate_tests!( (RSA512, RSA512Private, U512, 512),
(RSA1024, RSA1024Private, U1024, 1024),
(RSA2048, RSA2048Private, U2048, 2048),
(RSA3072, RSA3072Private, U3072, 3072),
(RSA4096, RSA4096Private, U4096, 4096),
(RSA8192, RSA8192Private, U8192, 8192),
(RSA15360, RSA15360Private, U15360, 15360)
generate_tests!( (RSA512, RSA512Private, U512, BarrettU512, U576, 512),
(RSA1024, RSA1024Private, U1024, BarrettU1024, U1088, 1024),
(RSA2048, RSA2048Private, U2048, BarrettU2048, U2112, 2048),
(RSA3072, RSA3072Private, U3072, BarrettU3072, U3136, 3072),
(RSA4096, RSA4096Private, U4096, BarrettU4096, U4160, 4096),
(RSA8192, RSA8192Private, U8192, BarrettU8192, U8256, 8192),
(RSA15360, RSA15360Private, U15360, BarrettU15360, U15424, 15360)
);

View File

@@ -1,6 +1,6 @@
use cryptonum::*;
use cryptonum::unsigned::*;
use digest::{FixedOutput,Input};
use num::{BigInt,BigUint};
use num::BigInt;
use rand::{OsRng,Rng};
use rsa::core::{decode_biguint,pkcs1_pad,xor_vecs};
use rsa::errors::RSAError;
@@ -8,6 +8,9 @@ use rsa::oaep::OAEPParams;
use rsa::signing_hashes::SigningHash;
use simple_asn1::{ASN1Block,ASN1DecodeErr,ASN1EncodeErr,
ASN1Class,FromASN1,ToASN1};
#[cfg(test)]
use std::fmt;
use utils::TranslateNums;
pub trait RSAPublicKey<N> {
/// Generate a new public key pair for the given modulus and
@@ -84,49 +87,51 @@ impl FromASN1 for RSAPublic {
let nsize = n.bits();
let mut rsa_size = 512;
println!("n': {:X}", n);
println!("nsize: {}", nsize);
while rsa_size < nsize {
rsa_size = rsa_size + 256;
}
match rsa_size {
512 => {
let n2 = U512::from(n);
let e2 = U512::from(e);
let n2 = U512::from_num(n);
let e2 = U512::from_num(e);
let res = RSA512Public::new(n2, e2);
Ok((RSAPublic::Key512(res), rest))
}
1024 => {
let n2 = U1024::from(n);
let e2 = U1024::from(e);
let n2 = U1024::from_num(n);
let e2 = U1024::from_num(e);
let res = RSA1024Public::new(n2, e2);
Ok((RSAPublic::Key1024(res), rest))
}
2048 => {
let n2 = U2048::from(n);
let e2 = U2048::from(e);
let n2 = U2048::from_num(n);
let e2 = U2048::from_num(e);
let res = RSA2048Public::new(n2, e2);
Ok((RSAPublic::Key2048(res), rest))
}
3072 => {
let n2 = U3072::from(n);
let e2 = U3072::from(e);
let n2 = U3072::from_num(n);
let e2 = U3072::from_num(e);
let res = RSA3072Public::new(n2, e2);
Ok((RSAPublic::Key3072(res), rest))
}
4096 => {
let n2 = U4096::from(n);
let e2 = U4096::from(e);
let n2 = U4096::from_num(n);
let e2 = U4096::from_num(e);
let res = RSA4096Public::new(n2, e2);
Ok((RSAPublic::Key4096(res), rest))
}
8192 => {
let n2 = U8192::from(n);
let e2 = U8192::from(e);
let n2 = U8192::from_num(n);
let e2 = U8192::from_num(e);
let res = RSA8192Public::new(n2, e2);
Ok((RSAPublic::Key8192(res), rest))
}
15360 => {
let n2 = U15360::from(n);
let e2 = U15360::from(e);
let n2 = U15360::from_num(n);
let e2 = U15360::from_num(e);
let res = RSA15360Public::new(n2, e2);
Ok((RSAPublic::Key15360(res), rest))
}
@@ -170,16 +175,17 @@ impl ToASN1 for RSAPublic {
macro_rules! generate_rsa_public
{
($rsa: ident, $num: ident, $bar: ident, $var: ident, $size: expr) => {
#[derive(Debug,PartialEq)]
#[derive(PartialEq)]
pub struct $rsa {
n: $num,
nu: $bar,
e: $num
}
impl RSAPublicKey<$num> for $rsa {
fn new(n: $num, e: $num) -> $rsa {
let nu = $bar::new(&n);
$rsa { nu: nu, e: e }
let nu = $bar::new(n.clone());
$rsa { n: n, nu: nu, e: e }
}
fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8])
@@ -292,14 +298,25 @@ macro_rules! generate_rsa_public
fn to_asn1_class(&self, c: ASN1Class)
-> Result<Vec<ASN1Block>,Self::Error>
{
let n = BigInt::from(BigUint::from(self.nu.m.clone()));
let e = BigInt::from(BigUint::from(self.e.clone()));
let n = BigInt::from(self.n.to_num());
let e = BigInt::from(self.e.to_num());
let enc_n = ASN1Block::Integer(c, 0, n);
let enc_e = ASN1Block::Integer(c, 0, e);
let seq = ASN1Block::Sequence(c, 0, vec![enc_n, enc_e]);
Ok(vec![seq])
}
}
#[cfg(test)]
impl fmt::Debug for $rsa {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct(stringify!($rsa))
.field("n", &self.n)
.field("nu", &self.nu)
.field("e", &self.e)
.finish()
}
}
}
}
@@ -312,12 +329,12 @@ generate_rsa_public!(RSA8192Public, U8192, BarrettU8192, Key8192, 8192);
generate_rsa_public!(RSA15360Public, U15360, BarrettU15360, Key15360, 15360);
macro_rules! generate_tests {
( $( ($mod: ident, $rsa: ident, $num: ident, $size: expr) ),* ) => {
( $( ($mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) ),* ) => {
$(
#[cfg(test)]
#[allow(non_snake_case)]
mod $mod {
use cryptonum::Decoder;
use cryptonum::unsigned::Decoder;
use super::*;
use testing::run_test;
use rsa::signing_hashes::*;
@@ -325,13 +342,20 @@ macro_rules! generate_tests {
#[test]
fn encode() {
let fname = format!("tests/rsa/rsa{}.test", $size);
run_test(fname.to_string(), 6, |case| {
run_test(fname.to_string(), 8, |case| {
let (neg0, nbytes) = case.get("n").unwrap();
let (neg1, ubytes) = case.get("u").unwrap();
let (neg2, kbytes) = case.get("k").unwrap();
assert!(!neg0);
assert!(!neg0&&!neg1&&!neg2);
let n = $num::from_bytes(nbytes);
println!("n: {:X}", n);
let n64 = $num64::from(&n);
let nu = $num64::from_bytes(ubytes);
let bigk = $num::from_bytes(kbytes);
let k = usize::from(bigk);
let e = $num::from(65537u64);
let pubkey = $rsa::new(n, e);
let pubkey = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
let asn1 = pubkey.to_asn1().unwrap();
let (pubkey2, _) = $rsa::from_asn1(&asn1).unwrap();
assert_eq!(pubkey, pubkey2);
@@ -341,16 +365,22 @@ macro_rules! generate_tests {
#[test]
fn verify() {
let fname = format!("tests/rsa/rsa{}.test", $size);
run_test(fname.to_string(), 6, |case| {
run_test(fname.to_string(), 8, |case| {
let (neg0, nbytes) = case.get("n").unwrap();
let (neg1, hbytes) = case.get("h").unwrap();
let (neg2, mbytes) = case.get("m").unwrap();
let (neg3, sbytes) = case.get("s").unwrap();
let (neg4, ubytes) = case.get("u").unwrap();
let (neg5, kbytes) = case.get("k").unwrap();
assert!(!neg0 && !neg1 && !neg2 && !neg3);
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
let n = $num::from_bytes(nbytes);
let n64 = $num64::from(&n);
let nu = $num64::from_bytes(ubytes);
let bigk = $num::from_bytes(kbytes);
let k = usize::from(bigk);
let e = $num::from(65537u64);
let pubkey = $rsa::new(n, e);
let pubkey = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
let hashnum = ((hbytes[0] as u16)<<8) + (hbytes[1] as u16);
let sighash = match hashnum {
0x160 => &SIGNING_HASH_SHA1,
@@ -367,16 +397,22 @@ macro_rules! generate_tests {
#[test]
fn encrypt() {
let fname = format!("tests/rsa/rsa{}.test", $size);
run_test(fname.to_string(), 6, |case| {
run_test(fname.to_string(), 8, |case| {
let (neg0, nbytes) = case.get("n").unwrap();
let (neg1, hbytes) = case.get("h").unwrap();
let (neg2, mbytes) = case.get("m").unwrap();
let (neg3, sbytes) = case.get("s").unwrap();
let (neg4, ubytes) = case.get("u").unwrap();
let (neg5, kbytes) = case.get("k").unwrap();
assert!(!neg0 && !neg1 && !neg2 && !neg3);
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
let n = $num::from_bytes(nbytes);
let n64 = $num64::from(&n);
let nu = $num64::from_bytes(ubytes);
let bigk = $num::from_bytes(kbytes);
let k = usize::from(bigk);
let e = $num::from(65537u64);
let pubkey = $rsa::new(n, e);
let pubkey = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
let hashnum = ((hbytes[0] as u16)<<8) + (hbytes[1] as u16);
let sighash = match hashnum {
0x160 => &SIGNING_HASH_SHA1,
@@ -394,11 +430,11 @@ macro_rules! generate_tests {
}
}
generate_tests!( (RSA512, RSA512Public, U512, 512),
(RSA1024, RSA1024Public, U1024, 1024),
(RSA2048, RSA2048Public, U2048, 2048),
(RSA3072, RSA3072Public, U3072, 3072),
(RSA4096, RSA4096Public, U4096, 4096),
(RSA8192, RSA8192Public, U8192, 8192),
(RSA15360, RSA15360Public, U15360, 15360)
generate_tests!( (RSA512, RSA512Public, U512, BarrettU512, U576, 512),
(RSA1024, RSA1024Public, U1024, BarrettU1024, U1088, 1024),
(RSA2048, RSA2048Public, U2048, BarrettU2048, U2112, 2048),
(RSA3072, RSA3072Public, U3072, BarrettU3072, U3136, 3072),
(RSA4096, RSA4096Public, U4096, BarrettU4096, U4160, 4096),
(RSA8192, RSA8192Public, U8192, BarrettU8192, U8256, 8192),
(RSA15360, RSA15360Public, U15360, BarrettU15360, U15424, 15360)
);

41
src/utils.rs Normal file
View File

@@ -0,0 +1,41 @@
use cryptonum::unsigned::*;
use num::BigUint;
pub trait TranslateNums {
fn from_num(x: BigUint) -> Self;
fn to_num(&self) -> BigUint;
}
macro_rules! from_biguint {
($uname: ident, $size: expr) => {
impl TranslateNums for $uname {
fn from_num(x: BigUint) -> $uname {
let mut base_vec = x.to_bytes_be();
let target_bytes = $size / 8;
while target_bytes > base_vec.len() {
base_vec.insert(0,0);
}
while base_vec.len() > target_bytes {
base_vec.remove(0);
}
$uname::from_bytes(&base_vec)
}
fn to_num(&self) -> BigUint {
let bytes = self.to_bytes();
BigUint::from_bytes_be(&bytes)
}
}
};
}
from_biguint!(U512, 512);
from_biguint!(U1024, 1024);
from_biguint!(U2048, 2048);
from_biguint!(U3072, 3072);
from_biguint!(U4096, 4096);
from_biguint!(U8192, 8192);
from_biguint!(U15360, 15360);

5
tests/rsa/CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
# Revision history for genrsa
## 0.1.0.0 -- YYYY-mm-dd
* First version. Released on an unsuspecting world.

13
tests/rsa/LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Copyright (c) 2018 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
tests/rsa/Setup.hs Normal file
View File

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

21
tests/rsa/genrsa.cabal Normal file
View File

@@ -0,0 +1,21 @@
name: genrsa
version: 0.1.0.0
-- synopsis:
-- description:
license: ISC
license-file: LICENSE
author: Adam Wick
maintainer: awick@uhsure.com
-- copyright:
category: Math
build-type: Simple
extra-source-files: CHANGELOG.md
cabal-version: >=1.10
executable genrsa
main-is: genrsa.hs
-- other-modules:
-- other-extensions:
build-depends: base >=4.11 && <4.12, RSA >=2.3 && <2.4, crypto-api >=0.13 && <0.14, bytestring >=0.10 && <0.11, containers >=0.5 && <0.6
-- hs-source-dirs:
default-language: Haskell2010

View File

@@ -63,6 +63,8 @@ genCase g0 size =
(Right sig, Right (cipher, g4)) ->
(Map.fromList [("d", Numeric.showHex d ""),
("n", Numeric.showHex n ""),
("k", Numeric.showHex (computeK n) ""),
("u", Numeric.showHex (barrett n) "" ),
("h", show hashlen),
("m", showBytes msg),
("s", showBytes sig),
@@ -72,6 +74,20 @@ genCase g0 size =
(_, _) ->
genCase g3 size
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)
go :: CryptoRandomGen g => g -> Handle -> Int -> Int -> IO ()
go _ _ _ 0 = return ()
go g hndl size count =

File diff suppressed because one or more lines are too long

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 one or more lines are too long

File diff suppressed because it is too large Load Diff