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

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);