Merge branch 'ssh' of github.com:acw/simple_crypto into ssh
This commit is contained in:
@@ -17,16 +17,16 @@ use super::KeyPair;
|
||||
|
||||
pub struct DSAKeyPair<P: DSAParameters>
|
||||
{
|
||||
pub private: DSAPrivKey<P>,
|
||||
pub public: DSAPubKey<P>
|
||||
pub private: DSAPrivateKey<P>,
|
||||
pub public: DSAPublicKey<P>
|
||||
}
|
||||
|
||||
impl<P: DSAParameters> KeyPair for DSAKeyPair<P>
|
||||
{
|
||||
type Private = DSAPrivKey<P>;
|
||||
type Public = DSAPubKey<P>;
|
||||
type Private = DSAPrivateKey<P>;
|
||||
type Public = DSAPublicKey<P>;
|
||||
|
||||
fn new(public: DSAPubKey<P>, private: DSAPrivKey<P>) -> DSAKeyPair<P>
|
||||
fn new(public: DSAPublicKey<P>, private: DSAPrivateKey<P>) -> DSAKeyPair<P>
|
||||
{
|
||||
DSAKeyPair{ private, public }
|
||||
}
|
||||
@@ -67,8 +67,8 @@ macro_rules! generate_dsa_pair {
|
||||
// 7. y = g^x mod p
|
||||
let y = params.g.modexp(&$ltype::from(&x), ¶ms.p);
|
||||
// 8. Return SUCCESS, x, and y.
|
||||
let private = DSAPrivKey::new(params.clone(), x);
|
||||
let public = DSAPubKey::new(params.clone(), y);
|
||||
let private = DSAPrivateKey::<$ptype>::new(params.clone(), x);
|
||||
let public = DSAPublicKey::<$ptype>::new(params.clone(), y);
|
||||
DSAKeyPair { private, public }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,49 +5,29 @@ use dsa::params::*;
|
||||
use dsa::rfc6979::*;
|
||||
use hmac::{Hmac,Mac};
|
||||
|
||||
pub trait DSAPrivateKey {
|
||||
type Params;
|
||||
type L;
|
||||
type N;
|
||||
|
||||
/// Generate a new private key using the given DSA parameters and private
|
||||
/// key value.
|
||||
fn new(params: Self::Params, x: Self::N) -> Self;
|
||||
/// Generate a DSA signature for the given message, using the appropriate
|
||||
/// hash included in the type invocation.
|
||||
fn sign<Hash>(&self, m: &[u8]) -> DSASignature<Self::N>
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac;
|
||||
}
|
||||
|
||||
pub struct DSAPrivKey<Params: DSAParameters>
|
||||
pub struct DSAPrivateKey<Params: DSAParameters>
|
||||
{
|
||||
pub(crate) params: Params,
|
||||
pub(crate) x: Params::N
|
||||
}
|
||||
|
||||
pub enum DSAPrivate {
|
||||
DSA1024Private(DSAPrivKey<L1024N160>),
|
||||
DSA2048SmallPrivate(DSAPrivKey<L2048N224>),
|
||||
DSA2048Private(DSAPrivKey<L2048N256>),
|
||||
DSA3072Private(DSAPrivKey<L3072N256>)
|
||||
DSA1024Private(DSAPrivateKey<L1024N160>),
|
||||
DSA2048SmallPrivate(DSAPrivateKey<L2048N224>),
|
||||
DSA2048Private(DSAPrivateKey<L2048N256>),
|
||||
DSA3072Private(DSAPrivateKey<L3072N256>)
|
||||
}
|
||||
|
||||
macro_rules! privkey_impls {
|
||||
($ptype: ident, $ltype: ident, $ntype: ident, $big: ident, $bigger: ident, $biggest: ident) => {
|
||||
impl DSAPrivateKey for DSAPrivKey<$ptype>
|
||||
impl DSAPrivateKey<$ptype>
|
||||
{
|
||||
type Params = $ptype;
|
||||
type L = $ltype;
|
||||
type N = $ntype;
|
||||
|
||||
fn new(params: $ptype, x: $ntype) -> DSAPrivKey<$ptype>
|
||||
pub fn new(params: $ptype, x: $ntype) -> DSAPrivateKey<$ptype>
|
||||
{
|
||||
DSAPrivKey{ params, x }
|
||||
DSAPrivateKey{ params, x }
|
||||
}
|
||||
|
||||
fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$ntype>
|
||||
pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$ntype>
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac
|
||||
@@ -155,7 +135,7 @@ macro_rules! generate_tests {
|
||||
let s = $nt::from_bytes(sbytes);
|
||||
|
||||
let params = $params::new(p,g,q);
|
||||
let private = DSAPrivKey::<$params>::new(params, x);
|
||||
let private = DSAPrivateKey::<$params>::new(params, x);
|
||||
let sig = match h {
|
||||
224 => private.sign::<Sha224>(mbytes),
|
||||
256 => private.sign::<Sha256>(mbytes),
|
||||
|
||||
@@ -7,45 +7,28 @@ use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,ToASN1};
|
||||
use std::cmp::min;
|
||||
use utils::TranslateNums;
|
||||
|
||||
pub trait DSAPublicKey {
|
||||
type Params : DSAParameters;
|
||||
type L;
|
||||
type N;
|
||||
|
||||
/// Generate a new public key given the parameters and public value.
|
||||
fn new(params: Self::Params, y: Self::L) -> Self;
|
||||
/// Verify the given signature against the given message, using the
|
||||
/// appropriate hash function.
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<Self::N>) -> bool
|
||||
where Hash: Digest;
|
||||
}
|
||||
|
||||
pub struct DSAPubKey<Params: DSAParameters> {
|
||||
pub struct DSAPublicKey<Params: DSAParameters> {
|
||||
pub(crate) params: Params,
|
||||
pub(crate) y: Params::L
|
||||
}
|
||||
|
||||
pub enum DSAPublic {
|
||||
DSAPublicL1024N160(DSAPubKey<L1024N160>),
|
||||
DSAPublicL2048N224(DSAPubKey<L2048N224>),
|
||||
DSAPublicL2048N256(DSAPubKey<L2048N256>),
|
||||
DSAPublicL3072N256(DSAPubKey<L3072N256>)
|
||||
DSAPublicL1024N160(DSAPublicKey<L1024N160>),
|
||||
DSAPublicL2048N224(DSAPublicKey<L2048N224>),
|
||||
DSAPublicL2048N256(DSAPublicKey<L2048N256>),
|
||||
DSAPublicL3072N256(DSAPublicKey<L3072N256>)
|
||||
}
|
||||
|
||||
macro_rules! pubkey_impls {
|
||||
($ptype: ident, $ltype: ident, $ntype: ident, $dbl: ident, $bdbl: ident) => {
|
||||
impl DSAPublicKey for DSAPubKey<$ptype>
|
||||
impl DSAPublicKey<$ptype>
|
||||
{
|
||||
type Params = $ptype;
|
||||
type L = $ltype;
|
||||
type N = $ntype;
|
||||
|
||||
fn new(params: $ptype, y: $ltype) -> DSAPubKey<$ptype>
|
||||
pub fn new(params: $ptype, y: $ltype) -> DSAPublicKey<$ptype>
|
||||
{
|
||||
DSAPubKey{ params, y }
|
||||
DSAPublicKey{ params, y }
|
||||
}
|
||||
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
||||
pub fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
||||
where Hash: Digest
|
||||
{
|
||||
if sig.r >= self.params.q {
|
||||
@@ -80,7 +63,7 @@ macro_rules! pubkey_impls {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToASN1 for DSAPubKey<$ptype> {
|
||||
impl ToASN1 for DSAPublicKey<$ptype> {
|
||||
type Error = ASN1EncodeErr;
|
||||
|
||||
fn to_asn1_class(&self, c: ASN1Class)
|
||||
@@ -136,7 +119,7 @@ macro_rules! generate_tests {
|
||||
let s = $nt::from_bytes(sbytes);
|
||||
|
||||
let params = $params::new(p,g,q);
|
||||
let public = DSAPubKey::<$params>::new(params, y);
|
||||
let public = DSAPublicKey::<$params>::new(params, y);
|
||||
let sig = DSASignature::<$nt>::new(r, s);
|
||||
match h {
|
||||
224 => assert!(public.verify::<Sha224>(mbytes, &sig)),
|
||||
|
||||
@@ -4,8 +4,8 @@ use sha1::Sha1;
|
||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||
use simple_asn1::{der_decode,der_encode};
|
||||
use dsa::params::{DSAParameters,L1024N160,L2048N256};
|
||||
use dsa::private::{DSAPrivateKey,DSAPrivKey};
|
||||
use dsa::public::{DSAPublicKey,DSAPubKey};
|
||||
use dsa::private::DSAPrivateKey;
|
||||
use dsa::public::DSAPublicKey;
|
||||
use dsa::rfc6979::KIterator;
|
||||
|
||||
macro_rules! run_rfc6979_test {
|
||||
@@ -99,8 +99,8 @@ fn appendix_a21() {
|
||||
let params = L1024N160::new(p, g, q);
|
||||
let x = U192::from_bytes(&xbytes);
|
||||
let y = U1024::from_bytes(&ybytes);
|
||||
let private = DSAPrivKey::<L1024N160>::new(params.clone(), x);
|
||||
let public = DSAPubKey::<L1024N160>::new(params.clone(), y);
|
||||
let private = DSAPrivateKey::<L1024N160>::new(params.clone(), x);
|
||||
let public = DSAPublicKey::<L1024N160>::new(params.clone(), y);
|
||||
//
|
||||
let sample: [u8; 6] = [115, 97, 109, 112, 108, 101]; // "sample", ASCII
|
||||
let test: [u8; 4] = [116, 101, 115, 116]; // "test", ASCII
|
||||
@@ -359,8 +359,8 @@ fn appendix_a22() {
|
||||
let params = L2048N256::new(p, g, q);
|
||||
let x = U256::from_bytes(&xbytes);
|
||||
let y = U2048::from_bytes(&ybytes);
|
||||
let private = DSAPrivKey::<L2048N256>::new(params.clone(), x);
|
||||
let public = DSAPubKey::<L2048N256>::new(params.clone(), y);
|
||||
let private = DSAPrivateKey::<L2048N256>::new(params.clone(), x);
|
||||
let public = DSAPublicKey::<L2048N256>::new(params.clone(), y);
|
||||
//
|
||||
let sample: [u8; 6] = [115, 97, 109, 112, 108, 101]; // "sample", ASCII
|
||||
let test: [u8; 4] = [116, 101, 115, 116]; // "test", ASCII
|
||||
|
||||
@@ -10,18 +10,29 @@ use rand::Rng;
|
||||
use rand::distributions::Standard;
|
||||
use self::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||
use self::point::{ECCPoint,Point};
|
||||
pub use self::private::{ECCPrivateKey,ECCPrivate};
|
||||
pub use self::public::{ECCPublicKey,ECDSAPublic,ECCPubKey};
|
||||
pub use self::private::ECCPrivateKey;
|
||||
pub use self::public::{ECDSAPublic,ECCPublicKey};
|
||||
pub use self::public::{ECDSADecodeErr,ECDSAEncodeErr};
|
||||
use super::KeyPair;
|
||||
|
||||
pub trait ECDSAKeyPair<Public,Private> {
|
||||
fn generate<G: Rng>(g: &mut G) -> (Public, Private);
|
||||
pub struct ECDSAKeyPair<Curve: EllipticCurve> {
|
||||
pub public: ECCPublicKey<Curve>,
|
||||
pub private: ECCPrivateKey<Curve>
|
||||
}
|
||||
|
||||
macro_rules! generate_impl {
|
||||
($curve: ident, $un: ident, $si: ident) => {
|
||||
impl ECDSAKeyPair<ECCPubKey<$curve>,ECCPrivate<$curve>> for $curve {
|
||||
fn generate<G: Rng>(rng: &mut G) -> (ECCPubKey<$curve>, ECCPrivate<$curve>)
|
||||
impl KeyPair for ECDSAKeyPair<$curve> {
|
||||
type Public = ECCPublicKey<$curve>;
|
||||
type Private = ECCPrivateKey<$curve>;
|
||||
|
||||
fn new(public: ECCPublicKey<$curve>, private: ECCPrivateKey<$curve>) -> ECDSAKeyPair<$curve>
|
||||
{
|
||||
ECDSAKeyPair{ public, private }
|
||||
}
|
||||
}
|
||||
impl ECDSAKeyPair<$curve> {
|
||||
pub fn generate<G: Rng>(rng: &mut G) -> ECDSAKeyPair<$curve>
|
||||
{
|
||||
loop {
|
||||
let size = ($curve::size() + 7) / 8;
|
||||
@@ -38,9 +49,10 @@ macro_rules! generate_impl {
|
||||
|
||||
let d = $si::from(&proposed_d);
|
||||
let public_point = Point::<$curve>::default().scale(&d);
|
||||
let public = ECCPubKey::<$curve>::new(public_point);
|
||||
let private = ECCPrivate::<$curve>::new(proposed_d);
|
||||
return (public, private);
|
||||
let public = ECCPublicKey::<$curve>::new(public_point);
|
||||
let private = ECCPrivateKey::<$curve>::new(proposed_d);
|
||||
|
||||
return ECDSAKeyPair{ public, private };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,33 +6,21 @@ use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||
use ecdsa::point::{ECCPoint,Point};
|
||||
use hmac::{Hmac,Mac};
|
||||
|
||||
pub struct ECCPrivate<Curve: EllipticCurve> {
|
||||
pub struct ECCPrivateKey<Curve: EllipticCurve> {
|
||||
d: Curve::Unsigned
|
||||
}
|
||||
|
||||
pub trait ECCPrivateKey {
|
||||
type Unsigned;
|
||||
|
||||
fn new(d: Self::Unsigned) -> Self;
|
||||
fn sign<Hash>(&self, m: &[u8]) -> DSASignature<Self::Unsigned>
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac;
|
||||
}
|
||||
|
||||
macro_rules! generate_privates
|
||||
{
|
||||
($curve: ident, $base: ident, $sig: ident, $dbl: ident, $quad: ident) => {
|
||||
impl ECCPrivateKey for ECCPrivate<$curve>
|
||||
impl ECCPrivateKey<$curve>
|
||||
{
|
||||
type Unsigned = $base;
|
||||
|
||||
fn new(d: $base) -> ECCPrivate<$curve>
|
||||
pub fn new(d: $base) -> ECCPrivateKey<$curve>
|
||||
{
|
||||
ECCPrivate{ d }
|
||||
ECCPrivateKey{ d }
|
||||
}
|
||||
|
||||
fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$base>
|
||||
pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$base>
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac
|
||||
@@ -136,7 +124,7 @@ macro_rules! sign_test_body
|
||||
let r = $base::from_bytes(rbytes);
|
||||
let s = $base::from_bytes(sbytes);
|
||||
|
||||
let private = ECCPrivate::<$curve>::new(d);
|
||||
let private = ECCPrivateKey::<$curve>::new(d);
|
||||
let sig = match usize::from(h) {
|
||||
224 => private.sign::<Sha224>(mbytes),
|
||||
256 => private.sign::<Sha256>(mbytes),
|
||||
|
||||
@@ -8,27 +8,16 @@ use hmac::{Hmac,Mac};
|
||||
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr,FromASN1,ToASN1};
|
||||
use std::cmp::min;
|
||||
|
||||
pub struct ECCPubKey<Curve: EllipticCurve> {
|
||||
pub struct ECCPublicKey<Curve: EllipticCurve> {
|
||||
q: Point<Curve>
|
||||
}
|
||||
|
||||
pub enum ECDSAPublic {
|
||||
ECCPublicP192(ECCPubKey<P192>),
|
||||
ECCPublicP224(ECCPubKey<P224>),
|
||||
ECCPublicP256(ECCPubKey<P256>),
|
||||
ECCPublicP384(ECCPubKey<P384>),
|
||||
ECCPublicP521(ECCPubKey<P521>),
|
||||
}
|
||||
|
||||
pub trait ECCPublicKey {
|
||||
type Curve : EllipticCurve;
|
||||
type Unsigned;
|
||||
|
||||
fn new(d: Point<Self::Curve>) -> Self;
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<Self::Unsigned>) -> bool
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac;
|
||||
ECCPublicP192(ECCPublicKey<P192>),
|
||||
ECCPublicP224(ECCPublicKey<P224>),
|
||||
ECCPublicP256(ECCPublicKey<P256>),
|
||||
ECCPublicP384(ECCPublicKey<P384>),
|
||||
ECCPublicP521(ECCPublicKey<P521>),
|
||||
}
|
||||
|
||||
pub enum ECDSAEncodeErr {
|
||||
@@ -58,17 +47,14 @@ impl From<ASN1DecodeErr> for ECDSADecodeErr {
|
||||
|
||||
macro_rules! public_impl {
|
||||
($curve: ident, $un: ident, $si: ident) => {
|
||||
impl ECCPublicKey for ECCPubKey<$curve>
|
||||
impl ECCPublicKey<$curve>
|
||||
{
|
||||
type Curve = $curve;
|
||||
type Unsigned = $un;
|
||||
|
||||
fn new(q: Point<$curve>) -> ECCPubKey<$curve>
|
||||
pub fn new(q: Point<$curve>) -> ECCPublicKey<$curve>
|
||||
{
|
||||
ECCPubKey{ q }
|
||||
ECCPublicKey{ q }
|
||||
}
|
||||
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<Self::Unsigned>) -> bool
|
||||
pub fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$un>) -> bool
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac
|
||||
@@ -103,7 +89,7 @@ macro_rules! public_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToASN1 for ECCPubKey<$curve> {
|
||||
impl ToASN1 for ECCPublicKey<$curve> {
|
||||
type Error = ECDSAEncodeErr;
|
||||
|
||||
fn to_asn1_class(&self, c: ASN1Class) -> Result<Vec<ASN1Block>,ECDSAEncodeErr>
|
||||
@@ -136,10 +122,10 @@ macro_rules! public_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromASN1 for ECCPubKey<$curve> {
|
||||
impl FromASN1 for ECCPublicKey<$curve> {
|
||||
type Error = ECDSADecodeErr;
|
||||
|
||||
fn from_asn1(bs: &[ASN1Block]) -> Result<(ECCPubKey<$curve>,&[ASN1Block]),ECDSADecodeErr>
|
||||
fn from_asn1(bs: &[ASN1Block]) -> Result<(ECCPublicKey<$curve>,&[ASN1Block]),ECDSADecodeErr>
|
||||
{
|
||||
let (x, rest) = bs.split_first().ok_or(ECDSADecodeErr::NoKeyFound)?;
|
||||
if let ASN1Block::BitString(_, _, _, target) = x {
|
||||
@@ -155,7 +141,7 @@ macro_rules! public_impl {
|
||||
let x = $un::from_bytes(xbstr);
|
||||
let y = $un::from_bytes(ybstr);
|
||||
let point = Point::<$curve>{ x: $si::from(x), y: $si::from(y) };
|
||||
let res = ECCPubKey::<$curve>::new(point);
|
||||
let res = ECCPublicKey::<$curve>::new(point);
|
||||
Ok((res, rest))
|
||||
} else {
|
||||
Err(ECDSADecodeErr::InvalidKeyFormat)
|
||||
@@ -201,7 +187,7 @@ macro_rules! verify_test_body
|
||||
let s = $un::from_bytes(sbytes);
|
||||
|
||||
let point = Point::<$curve>{ x: $si::from(x), y: $si::from(y) };
|
||||
let public = ECCPubKey::<$curve>::new(point);
|
||||
let public = ECCPublicKey::<$curve>::new(point);
|
||||
let sig = DSASignature::new(r, s);
|
||||
match usize::from(h) {
|
||||
224 => assert!(public.verify::<Sha224>(mbytes, &sig)),
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use num::bigint::BigUint;
|
||||
use rsa::errors::RSAError;
|
||||
use simple_asn1::{ASN1Block,ASN1DecodeErr};
|
||||
|
||||
pub trait RSAMode {
|
||||
type Barrett;
|
||||
}
|
||||
|
||||
impl RSAMode for U512 { type Barrett = BarrettU512; }
|
||||
impl RSAMode for U1024 { type Barrett = BarrettU1024; }
|
||||
impl RSAMode for U2048 { type Barrett = BarrettU2048; }
|
||||
impl RSAMode for U3072 { type Barrett = BarrettU3072; }
|
||||
impl RSAMode for U4096 { type Barrett = BarrettU4096; }
|
||||
impl RSAMode for U8192 { type Barrett = BarrettU8192; }
|
||||
impl RSAMode for U15360 { type Barrett = BarrettU15360; }
|
||||
|
||||
|
||||
pub fn pkcs1_pad(ident: &[u8], hash: &[u8], keylen: usize) -> Vec<u8>
|
||||
{
|
||||
let mut idhash = Vec::new();
|
||||
|
||||
@@ -24,6 +24,7 @@ mod private;
|
||||
mod public;
|
||||
mod signing_hashes;
|
||||
|
||||
pub use self::core::RSAMode;
|
||||
pub use self::errors::RSAError;
|
||||
pub use self::signing_hashes::{SigningHash,
|
||||
SIGNING_HASH_NULL,
|
||||
@@ -33,20 +34,14 @@ pub use self::signing_hashes::{SigningHash,
|
||||
SIGNING_HASH_SHA384,
|
||||
SIGNING_HASH_SHA512};
|
||||
pub use self::oaep::OAEPParams;
|
||||
pub use self::private::{RSAPrivate, RSAPrivateKey,
|
||||
RSA512Private, RSA1024Private, RSA2048Private,
|
||||
RSA3072Private, RSA4096Private, RSA8192Private,
|
||||
RSA15360Private};
|
||||
pub use self::public::{RSAPublic, RSAPublicKey,
|
||||
RSA512Public, RSA1024Public, RSA2048Public,
|
||||
RSA3072Public, RSA4096Public, RSA8192Public,
|
||||
RSA15360Public};
|
||||
|
||||
pub use self::private::{RSAPrivate, RSAPrivateKey};
|
||||
pub use self::public::{RSAPublic, RSAPublicKey};
|
||||
use cryptonum::signed::{EGCD,ModInv};
|
||||
use cryptonum::unsigned::{CryptoNum,PrimeGen};
|
||||
use cryptonum::unsigned::{U256,U512,U1024,U1536,U2048,U3072,U4096,U7680,U8192,U15360};
|
||||
use rand::RngCore;
|
||||
use std::ops::Sub;
|
||||
use super::KeyPair;
|
||||
|
||||
fn diff<T>(a: &T, b: &T) -> T
|
||||
where
|
||||
@@ -60,38 +55,43 @@ fn diff<T>(a: &T, b: &T) -> T
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RSAKeyPair<R: RSAMode> {
|
||||
pub public: RSAPublicKey<R>,
|
||||
pub private: RSAPrivateKey<R>
|
||||
}
|
||||
|
||||
macro_rules! generate_rsa_pair
|
||||
{
|
||||
($pair: ident, $pub: ident, $priv: ident, $uint: ident, $half: ident, $iterations: expr) => {
|
||||
pub struct $pair {
|
||||
pub public: $pub,
|
||||
pub private: $priv
|
||||
}
|
||||
($uint: ident, $half: ident, $iterations: expr) => {
|
||||
impl KeyPair for RSAKeyPair<$uint> {
|
||||
type Public = RSAPublicKey<$uint>;
|
||||
type Private = RSAPrivateKey<$uint>;
|
||||
|
||||
impl $pair {
|
||||
pub fn new(pu: $pub, pr: $priv) -> $pair {
|
||||
$pair {
|
||||
fn new(pu: RSAPublicKey<$uint>, pr: RSAPrivateKey<$uint>) -> RSAKeyPair<$uint> {
|
||||
RSAKeyPair {
|
||||
public: pu,
|
||||
private: pr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate<G>(rng: &mut G) -> $pair
|
||||
impl RSAKeyPair<$uint> {
|
||||
pub fn generate<G>(rng: &mut G) -> RSAKeyPair<$uint>
|
||||
where G: RngCore
|
||||
{
|
||||
loop {
|
||||
let ebase = 65537u32;
|
||||
let e = $uint::from(ebase);
|
||||
let (p, q) = $pair::generate_pq(rng, &$half::from(ebase));
|
||||
let (p, q) = RSAKeyPair::<$uint>::generate_pq(rng, &$half::from(ebase));
|
||||
let one = $half::from(1u32);
|
||||
let pminus1 = &p - &one;
|
||||
let qminus1 = &q - &one;
|
||||
let phi = pminus1 * qminus1;
|
||||
let n = &p * &q;
|
||||
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);
|
||||
let public = RSAPublicKey::<$uint>::new(n.clone(), e);
|
||||
let private = RSAPrivateKey::<$uint>::new(n, d);
|
||||
return RSAKeyPair::<$uint>::new(public, private);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,13 +129,13 @@ macro_rules! generate_rsa_pair
|
||||
}
|
||||
}
|
||||
|
||||
generate_rsa_pair!(RSA512KeyPair, RSA512Public, RSA512Private, U512, U256, 7);
|
||||
generate_rsa_pair!(RSA1024KeyPair, RSA1024Public, RSA1024Private, U1024, U512, 7);
|
||||
generate_rsa_pair!(RSA2048KeyPair, RSA2048Public, RSA2048Private, U2048, U1024, 4);
|
||||
generate_rsa_pair!(RSA3072KeyPair, RSA3072Public, RSA3072Private, U3072, U1536, 3);
|
||||
generate_rsa_pair!(RSA4096KeyPair, RSA4096Public, RSA4096Private, U4096, U2048, 3);
|
||||
generate_rsa_pair!(RSA8192KeyPair, RSA8192Public, RSA8192Private, U8192, U4096, 3);
|
||||
generate_rsa_pair!(RSA15360KeyPair, RSA15360Public, RSA15360Private, U15360, U7680, 3);
|
||||
generate_rsa_pair!(U512, U256, 7);
|
||||
generate_rsa_pair!(U1024, U512, 7);
|
||||
generate_rsa_pair!(U2048, U1024, 4);
|
||||
generate_rsa_pair!(U3072, U1536, 3);
|
||||
generate_rsa_pair!(U4096, U2048, 3);
|
||||
generate_rsa_pair!(U8192, U4096, 3);
|
||||
generate_rsa_pair!(U15360, U7680, 3);
|
||||
|
||||
#[cfg(test)]
|
||||
mod generation {
|
||||
@@ -143,15 +143,15 @@ mod generation {
|
||||
use std::fmt;
|
||||
use super::*;
|
||||
|
||||
impl Clone for RSA512KeyPair {
|
||||
fn clone(&self) -> RSA512KeyPair {
|
||||
RSA512KeyPair{
|
||||
public: RSA512Public {
|
||||
impl Clone for RSAKeyPair<U512> {
|
||||
fn clone(&self) -> RSAKeyPair<U512> {
|
||||
RSAKeyPair {
|
||||
public: RSAPublicKey {
|
||||
n: self.public.n.clone(),
|
||||
nu: self.public.nu.clone(),
|
||||
e: self.public.e.clone(),
|
||||
},
|
||||
private: RSA512Private {
|
||||
private: RSAPrivateKey {
|
||||
nu: self.private.nu.clone(),
|
||||
d: self.private.d.clone()
|
||||
}
|
||||
@@ -159,7 +159,7 @@ mod generation {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RSA512KeyPair {
|
||||
impl fmt::Debug for RSAKeyPair<U512> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("RSA512KeyPair")
|
||||
.field("n", &self.public.n)
|
||||
@@ -169,14 +169,14 @@ mod generation {
|
||||
}
|
||||
}
|
||||
|
||||
impl Arbitrary for RSA512KeyPair {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> RSA512KeyPair {
|
||||
RSA512KeyPair::generate(g)
|
||||
impl Arbitrary for RSAKeyPair<U512> {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> RSAKeyPair<U512> {
|
||||
RSAKeyPair::<U512>::generate(g)
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn generate_and_sign(keypair: RSA512KeyPair, msg: Vec<u8>) -> bool {
|
||||
fn generate_and_sign(keypair: RSAKeyPair<U512>, msg: Vec<u8>) -> bool {
|
||||
let sig = keypair.private.sign(&SIGNING_HASH_SHA256, &msg);
|
||||
keypair.public.verify(&SIGNING_HASH_SHA256, &msg, &sig)
|
||||
}
|
||||
|
||||
@@ -1,56 +1,36 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use digest::{Digest,FixedOutput};
|
||||
use rsa::core::{drop0s,pkcs1_pad,xor_vecs};
|
||||
use rsa::core::{RSAMode,drop0s,pkcs1_pad,xor_vecs};
|
||||
use rsa::errors::RSAError;
|
||||
use rsa::oaep::OAEPParams;
|
||||
use rsa::signing_hashes::SigningHash;
|
||||
|
||||
pub trait RSAPrivateKey<N> {
|
||||
/// Generate a new private key using the given modulus and private
|
||||
/// exponent. You probably don't want to use this function directly
|
||||
/// unless you're writing your own key generation routine or key
|
||||
/// parsing library.
|
||||
fn new(n: N, d: N) -> Self;
|
||||
|
||||
/// Sign the given message with the given private key.
|
||||
fn sign(&self, signhash: &SigningHash, msg: &[u8]) -> Vec<u8>;
|
||||
|
||||
/// Decrypt the provided message using the given OAEP parameters. As
|
||||
/// mentioned in the comment for encryption, RSA decryption is really,
|
||||
/// really slow. So if your plaintext is larger than about half the
|
||||
/// bit size of the key, it's almost certainly a better idea to generate
|
||||
/// a fresh symmetric encryption key, encrypt only the key with RSA, and
|
||||
/// then encrypt the message with that key.
|
||||
fn decrypt<H>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where H: Default + Digest + FixedOutput;
|
||||
pub struct RSAPrivateKey<R: RSAMode>
|
||||
{
|
||||
pub(crate) nu: R::Barrett,
|
||||
pub(crate) d: R
|
||||
}
|
||||
|
||||
pub enum RSAPrivate {
|
||||
Key512(RSA512Private),
|
||||
Key1024(RSA1024Private),
|
||||
Key2048(RSA2048Private),
|
||||
Key3072(RSA3072Private),
|
||||
Key4096(RSA4096Private),
|
||||
Key8192(RSA8192Private),
|
||||
Key15360(RSA15360Private)
|
||||
Key512(RSAPrivateKey<U512>),
|
||||
Key1024(RSAPrivateKey<U1024>),
|
||||
Key2048(RSAPrivateKey<U2048>),
|
||||
Key3072(RSAPrivateKey<U3072>),
|
||||
Key4096(RSAPrivateKey<U4096>),
|
||||
Key8192(RSAPrivateKey<U8192>),
|
||||
Key15360(RSAPrivateKey<U15360>)
|
||||
}
|
||||
|
||||
macro_rules! generate_rsa_private
|
||||
{
|
||||
($rsa: ident, $num: ident, $bar: ident, $size: expr) => {
|
||||
pub struct $rsa {
|
||||
pub(crate) nu: $bar,
|
||||
pub(crate) d: $num
|
||||
}
|
||||
|
||||
impl RSAPrivateKey<$num> for $rsa {
|
||||
fn new(n: $num, d: $num) -> $rsa {
|
||||
($num: ident, $bar: ident, $size: expr) => {
|
||||
impl RSAPrivateKey<$num> {
|
||||
pub fn new(n: $num, d: $num) -> RSAPrivateKey<$num> {
|
||||
let nu = $bar::new(n.clone());
|
||||
$rsa { nu: nu, d: d }
|
||||
RSAPrivateKey{ nu: nu, d: d }
|
||||
}
|
||||
|
||||
fn sign(&self, signhash: &SigningHash, msg: &[u8])
|
||||
pub fn sign(&self, signhash: &SigningHash, msg: &[u8])
|
||||
-> Vec<u8>
|
||||
{
|
||||
let hash = (signhash.run)(msg);
|
||||
@@ -61,7 +41,7 @@ macro_rules! generate_rsa_private
|
||||
sig
|
||||
}
|
||||
|
||||
fn decrypt<H>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
||||
pub fn decrypt<H>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where H: Default + Digest + FixedOutput
|
||||
{
|
||||
@@ -74,9 +54,7 @@ macro_rules! generate_rsa_private
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl $rsa {
|
||||
fn sp1(&self, m: &$num) -> $num {
|
||||
m.modexp(&self.d, &self.nu)
|
||||
}
|
||||
@@ -139,17 +117,17 @@ macro_rules! generate_rsa_private
|
||||
}
|
||||
}
|
||||
|
||||
generate_rsa_private!(RSA512Private, U512, BarrettU512, 512);
|
||||
generate_rsa_private!(RSA1024Private, U1024, BarrettU1024, 1024);
|
||||
generate_rsa_private!(RSA2048Private, U2048, BarrettU2048, 2048);
|
||||
generate_rsa_private!(RSA3072Private, U3072, BarrettU3072, 3072);
|
||||
generate_rsa_private!(RSA4096Private, U4096, BarrettU4096, 4096);
|
||||
generate_rsa_private!(RSA8192Private, U8192, BarrettU8192, 8192);
|
||||
generate_rsa_private!(RSA15360Private, U15360, BarrettU15360, 15360);
|
||||
generate_rsa_private!(U512, BarrettU512, 512);
|
||||
generate_rsa_private!(U1024, BarrettU1024, 1024);
|
||||
generate_rsa_private!(U2048, BarrettU2048, 2048);
|
||||
generate_rsa_private!(U3072, BarrettU3072, 3072);
|
||||
generate_rsa_private!(U4096, BarrettU4096, 4096);
|
||||
generate_rsa_private!(U8192, BarrettU8192, 8192);
|
||||
generate_rsa_private!(U15360, BarrettU15360, 15360);
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! sign_test_body {
|
||||
($mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||
run_test(fname.to_string(), 7, |case| {
|
||||
let (neg0, dbytes) = case.get("d").unwrap();
|
||||
@@ -173,7 +151,7 @@ macro_rules! sign_test_body {
|
||||
512 => &SIGNING_HASH_SHA512,
|
||||
x => panic!("Bad signing hash: {}", x)
|
||||
};
|
||||
let privkey = $rsa{ nu: $bar::from_components(k, n.clone(), nu), d: d };
|
||||
let privkey = RSAPrivateKey{ nu: $bar::from_components(k, n.clone(), nu), d: d };
|
||||
let sig = privkey.sign(sighash, &mbytes);
|
||||
assert_eq!(*sbytes, sig);
|
||||
});
|
||||
@@ -182,7 +160,7 @@ macro_rules! sign_test_body {
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! decrypt_test_body {
|
||||
($mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/encrypt{}.test", $size);
|
||||
run_test(fname.to_string(), 9, |case| {
|
||||
let (neg0, nbytes) = case.get("n").unwrap();
|
||||
@@ -203,7 +181,7 @@ macro_rules! decrypt_test_body {
|
||||
let k = usize::from(bigk);
|
||||
let d = $num::from_bytes(dbytes);
|
||||
let nu = $bar::from_components(k, n64, nu);
|
||||
let privkey = $rsa{ nu: nu, d: d };
|
||||
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||
let message = match usize::from($num::from_bytes(hbytes)) {
|
||||
224 => privkey.decrypt(&OAEPParams::<Sha224>::new(lstr), &cbytes),
|
||||
@@ -219,7 +197,7 @@ macro_rules! decrypt_test_body {
|
||||
}
|
||||
|
||||
macro_rules! generate_tests {
|
||||
($mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
#[cfg(test)]
|
||||
#[allow(non_snake_case)]
|
||||
mod $mod {
|
||||
@@ -231,16 +209,16 @@ macro_rules! generate_tests {
|
||||
|
||||
#[test]
|
||||
fn sign() {
|
||||
sign_test_body!($mod, $rsa, $num, $bar, $num64, $size);
|
||||
sign_test_body!($mod, $num, $bar, $num64, $size);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt() {
|
||||
decrypt_test_body!($mod, $rsa, $num, $bar, $num64, $size);
|
||||
decrypt_test_body!($mod, $num, $bar, $num64, $size);
|
||||
}
|
||||
}
|
||||
};
|
||||
(ignore $mod: ident, $rsa: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
(ignore $mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
#[cfg(test)]
|
||||
#[allow(non_snake_case)]
|
||||
mod $mod {
|
||||
@@ -253,22 +231,22 @@ macro_rules! generate_tests {
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn sign() {
|
||||
sign_test_body!($mod, $rsa, $num, $bar, $num64, $size);
|
||||
sign_test_body!($mod, $num, $bar, $num64, $size);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn decrypt() {
|
||||
decrypt_test_body!($mod, $rsa, $num, $bar, $num64, $size);
|
||||
decrypt_test_body!($mod, $num, $bar, $num64, $size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generate_tests!(RSA512, RSA512Private, U512, BarrettU512, U576, 512);
|
||||
generate_tests!(RSA1024, RSA1024Private, U1024, BarrettU1024, U1088, 1024);
|
||||
generate_tests!(RSA2048, RSA2048Private, U2048, BarrettU2048, U2112, 2048);
|
||||
generate_tests!(RSA3072, RSA3072Private, U3072, BarrettU3072, U3136, 3072);
|
||||
generate_tests!(RSA4096, RSA4096Private, U4096, BarrettU4096, U4160, 4096);
|
||||
generate_tests!(ignore RSA8192, RSA8192Private, U8192, BarrettU8192, U8256, 8192);
|
||||
generate_tests!(ignore RSA15360, RSA15360Private, U15360, BarrettU15360, U15424, 15360);
|
||||
generate_tests!( RSA512, U512, BarrettU512, U576, 512);
|
||||
generate_tests!( RSA1024, U1024, BarrettU1024, U1088, 1024);
|
||||
generate_tests!( RSA2048, U2048, BarrettU2048, U2112, 2048);
|
||||
generate_tests!( RSA3072, U3072, BarrettU3072, U3136, 3072);
|
||||
generate_tests!( RSA4096, U4096, BarrettU4096, U4160, 4096);
|
||||
generate_tests!(ignore RSA8192, U8192, BarrettU8192, U8256, 8192);
|
||||
generate_tests!(ignore RSA15360, U15360, BarrettU15360, U15424, 15360);
|
||||
@@ -2,7 +2,7 @@ use cryptonum::unsigned::*;
|
||||
use digest::{Digest,FixedOutput};
|
||||
use rand::Rng;
|
||||
use rand::rngs::OsRng;
|
||||
use rsa::core::{decode_biguint,pkcs1_pad,xor_vecs};
|
||||
use rsa::core::{RSAMode,decode_biguint,pkcs1_pad,xor_vecs};
|
||||
use rsa::errors::RSAError;
|
||||
use rsa::oaep::OAEPParams;
|
||||
use rsa::signing_hashes::SigningHash;
|
||||
@@ -12,62 +12,21 @@ use simple_asn1::{ASN1Block,ASN1DecodeErr,ASN1EncodeErr,
|
||||
use std::fmt;
|
||||
use utils::TranslateNums;
|
||||
|
||||
pub trait RSAPublicKey<N> {
|
||||
/// Generate a new public key pair for the given modulus and
|
||||
/// exponent. You should probably not call this directly unless
|
||||
/// you're writing a key generation function or writing your own
|
||||
/// public key parser.
|
||||
fn new(n: N, e: N) -> Self;
|
||||
|
||||
/// Verify that the provided signature is valid; that the private
|
||||
/// key associated with this public key sent exactly this message.
|
||||
/// The hash used here must exactly match the hash used to sign
|
||||
/// the message, including its ASN.1 metadata.
|
||||
fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8]) -> bool;
|
||||
|
||||
/// Encrypt the message with a hash function, given the appropriate
|
||||
/// label. Please note that RSA encryption is not particularly fast,
|
||||
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||
/// that key with RSA encryption, and then encrypt the actual message
|
||||
/// with that symmetric key.
|
||||
///
|
||||
/// In this variant of the function, we use an explicit random number
|
||||
/// generator, just in case you have one you really like. It better be
|
||||
/// cryptographically strong, though, as some of the padding protections
|
||||
/// are relying on it.
|
||||
fn encrypt_rng<G,H>(&self, g: &mut G, oaep: &OAEPParams<H>, msg: &[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where
|
||||
G: Rng,
|
||||
H: Default + Digest + FixedOutput;
|
||||
|
||||
/// Encrypt the message with a hash function, given the appropriate
|
||||
/// label. Please note that RSA encryption is not particularly fast,
|
||||
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||
/// that key with RSA encryption, and then encrypt the actual message
|
||||
/// with that symmetric key.
|
||||
///
|
||||
/// This variant will just use the system RNG for its randomness.
|
||||
fn encrypt<H>(&self,oaep:&OAEPParams<H>,msg:&[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where
|
||||
H: Default + Digest + FixedOutput
|
||||
{
|
||||
let mut g = OsRng::new()?;
|
||||
self.encrypt_rng(&mut g, oaep, msg)
|
||||
}
|
||||
#[derive(PartialEq)]
|
||||
pub struct RSAPublicKey<R: RSAMode> {
|
||||
pub(crate) n: R,
|
||||
pub(crate) nu: R::Barrett,
|
||||
pub(crate) e: R
|
||||
}
|
||||
|
||||
pub enum RSAPublic {
|
||||
Key512(RSA512Public),
|
||||
Key1024(RSA1024Public),
|
||||
Key2048(RSA2048Public),
|
||||
Key3072(RSA3072Public),
|
||||
Key4096(RSA4096Public),
|
||||
Key8192(RSA8192Public),
|
||||
Key15360(RSA15360Public)
|
||||
Key512( RSAPublicKey<U512>),
|
||||
Key1024( RSAPublicKey<U1024>),
|
||||
Key2048( RSAPublicKey<U2048>),
|
||||
Key3072( RSAPublicKey<U3072>),
|
||||
Key4096( RSAPublicKey<U4096>),
|
||||
Key8192( RSAPublicKey<U8192>),
|
||||
Key15360(RSAPublicKey<U15360>)
|
||||
}
|
||||
|
||||
impl RSAPublic {
|
||||
@@ -109,43 +68,43 @@ impl FromASN1 for RSAPublic {
|
||||
512 => {
|
||||
let n2 = U512::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U512::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA512Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U512>::new(n2, e2);
|
||||
Ok((RSAPublic::Key512(res), rest))
|
||||
}
|
||||
1024 => {
|
||||
let n2 = U1024::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U1024::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA1024Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U1024>::new(n2, e2);
|
||||
Ok((RSAPublic::Key1024(res), rest))
|
||||
}
|
||||
2048 => {
|
||||
let n2 = U2048::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U2048::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA2048Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U2048>::new(n2, e2);
|
||||
Ok((RSAPublic::Key2048(res), rest))
|
||||
}
|
||||
3072 => {
|
||||
let n2 = U3072::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U3072::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA3072Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U3072>::new(n2, e2);
|
||||
Ok((RSAPublic::Key3072(res), rest))
|
||||
}
|
||||
4096 => {
|
||||
let n2 = U4096::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U4096::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA4096Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U4096>::new(n2, e2);
|
||||
Ok((RSAPublic::Key4096(res), rest))
|
||||
}
|
||||
8192 => {
|
||||
let n2 = U8192::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U8192::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA8192Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U8192>::new(n2, e2);
|
||||
Ok((RSAPublic::Key8192(res), rest))
|
||||
}
|
||||
15360 => {
|
||||
let n2 = U15360::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U15360::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA15360Public::new(n2, e2);
|
||||
let res = RSAPublicKey::<U15360>::new(n2, e2);
|
||||
Ok((RSAPublic::Key15360(res), rest))
|
||||
}
|
||||
_ =>
|
||||
@@ -178,21 +137,22 @@ impl ToASN1 for RSAPublic {
|
||||
|
||||
macro_rules! generate_rsa_public
|
||||
{
|
||||
($rsa: ident, $num: ident, $bar: ident, $var: ident, $size: expr) => {
|
||||
#[derive(PartialEq)]
|
||||
pub struct $rsa {
|
||||
pub(crate) n: $num,
|
||||
pub(crate) nu: $bar,
|
||||
pub(crate) e: $num
|
||||
}
|
||||
|
||||
impl RSAPublicKey<$num> for $rsa {
|
||||
fn new(n: $num, e: $num) -> $rsa {
|
||||
($num: ident, $bar: ident, $var: ident, $size: expr) => {
|
||||
impl RSAPublicKey<$num> {
|
||||
/// Generate a new public key pair for the given modulus and
|
||||
/// exponent. You should probably not call this directly unless
|
||||
/// you're writing a key generation function or writing your own
|
||||
/// public key parser.
|
||||
pub fn new(n: $num, e: $num) -> RSAPublicKey<$num> {
|
||||
let nu = $bar::new(n.clone());
|
||||
$rsa { n: n, nu: nu, e: e }
|
||||
RSAPublicKey{ n: n, nu: nu, e: e }
|
||||
}
|
||||
|
||||
fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8])
|
||||
/// Verify that the provided signature is valid; that the private
|
||||
/// key associated with this public key sent exactly this message.
|
||||
/// The hash used here must exactly match the hash used to sign
|
||||
/// the message, including its ASN.1 metadata.
|
||||
pub fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8])
|
||||
-> bool
|
||||
{
|
||||
let hash: Vec<u8> = (signhash.run)(msg);
|
||||
@@ -203,7 +163,18 @@ macro_rules! generate_rsa_public
|
||||
em == em_
|
||||
}
|
||||
|
||||
fn encrypt_rng<G,H>(&self,g: &mut G,oaep: &OAEPParams<H>,msg: &[u8])
|
||||
/// Encrypt the message with a hash function, given the appropriate
|
||||
/// label. Please note that RSA encryption is not particularly fast,
|
||||
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||
/// that key with RSA encryption, and then encrypt the actual message
|
||||
/// with that symmetric key.
|
||||
///
|
||||
/// In this variant of the function, we use an explicit random number
|
||||
/// generator, just in case you have one you really like. It better be
|
||||
/// cryptographically strong, though, as some of the padding protections
|
||||
/// are relying on it.
|
||||
pub fn encrypt_rng<G,H>(&self,g: &mut G,oaep: &OAEPParams<H>,msg: &[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where
|
||||
G: Rng,
|
||||
@@ -222,9 +193,24 @@ macro_rules! generate_rsa_public
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Encrypt the message with a hash function, given the appropriate
|
||||
/// label. Please note that RSA encryption is not particularly fast,
|
||||
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||
/// that key with RSA encryption, and then encrypt the actual message
|
||||
/// with that symmetric key.
|
||||
///
|
||||
/// This variant will just use the system RNG for its randomness.
|
||||
pub fn encrypt<H>(&self,oaep:&OAEPParams<H>,msg:&[u8])
|
||||
-> Result<Vec<u8>,RSAError>
|
||||
where
|
||||
H: Default + Digest + FixedOutput
|
||||
{
|
||||
let mut g = OsRng::new()?;
|
||||
self.encrypt_rng(&mut g, oaep, msg)
|
||||
}
|
||||
|
||||
impl $rsa {
|
||||
fn vp1(&self, s: &$num) -> $num {
|
||||
s.modexp(&self.e, &self.nu)
|
||||
}
|
||||
@@ -283,11 +269,11 @@ macro_rules! generate_rsa_public
|
||||
}
|
||||
}
|
||||
|
||||
impl FromASN1 for $rsa {
|
||||
impl FromASN1 for RSAPublicKey<$num> {
|
||||
type Error = RSAError;
|
||||
|
||||
fn from_asn1(bs: &[ASN1Block])
|
||||
-> Result<($rsa,&[ASN1Block]),RSAError>
|
||||
-> Result<(RSAPublicKey<$num>,&[ASN1Block]),RSAError>
|
||||
{
|
||||
let (core, rest) = RSAPublic::from_asn1(bs)?;
|
||||
|
||||
@@ -298,7 +284,7 @@ macro_rules! generate_rsa_public
|
||||
}
|
||||
}
|
||||
|
||||
impl ToASN1 for $rsa {
|
||||
impl ToASN1 for RSAPublicKey<$num> {
|
||||
type Error = ASN1EncodeErr;
|
||||
|
||||
fn to_asn1_class(&self, c: ASN1Class)
|
||||
@@ -314,7 +300,7 @@ macro_rules! generate_rsa_public
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl fmt::Debug for $rsa {
|
||||
impl fmt::Debug for RSAPublicKey<$num> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct(stringify!($rsa))
|
||||
.field("n", &self.n)
|
||||
@@ -326,17 +312,17 @@ macro_rules! generate_rsa_public
|
||||
}
|
||||
}
|
||||
|
||||
generate_rsa_public!(RSA512Public, U512, BarrettU512, Key512, 512);
|
||||
generate_rsa_public!(RSA1024Public, U1024, BarrettU1024, Key1024, 1024);
|
||||
generate_rsa_public!(RSA2048Public, U2048, BarrettU2048, Key2048, 2048);
|
||||
generate_rsa_public!(RSA3072Public, U3072, BarrettU3072, Key3072, 3072);
|
||||
generate_rsa_public!(RSA4096Public, U4096, BarrettU4096, Key4096, 4096);
|
||||
generate_rsa_public!(RSA8192Public, U8192, BarrettU8192, Key8192, 8192);
|
||||
generate_rsa_public!(RSA15360Public, U15360, BarrettU15360, Key15360, 15360);
|
||||
generate_rsa_public!(U512, BarrettU512, Key512, 512);
|
||||
generate_rsa_public!(U1024, BarrettU1024, Key1024, 1024);
|
||||
generate_rsa_public!(U2048, BarrettU2048, Key2048, 2048);
|
||||
generate_rsa_public!(U3072, BarrettU3072, Key3072, 3072);
|
||||
generate_rsa_public!(U4096, BarrettU4096, Key4096, 4096);
|
||||
generate_rsa_public!(U8192, BarrettU8192, Key8192, 8192);
|
||||
generate_rsa_public!(U15360, BarrettU15360, Key15360, 15360);
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! new_test_body {
|
||||
($mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||
run_test(fname.to_string(), 7, |case| {
|
||||
let (neg0, nbytes) = case.get("n").unwrap();
|
||||
@@ -350,8 +336,8 @@ macro_rules! new_test_body {
|
||||
let bigk = $num::from_bytes(kbytes);
|
||||
let k = usize::from(bigk);
|
||||
let e = $num::from(65537u64);
|
||||
let pubkey2 = $rsa::new(n.clone(), e.clone());
|
||||
let pubkey1 = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
let pubkey2 = RSAPublicKey::<$num>::new(n.clone(), e.clone());
|
||||
let pubkey1 = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
assert_eq!(pubkey1, pubkey2);
|
||||
});
|
||||
};
|
||||
@@ -359,7 +345,7 @@ macro_rules! new_test_body {
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! encode_test_body {
|
||||
($mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||
run_test(fname.to_string(), 7, |case| {
|
||||
let (neg0, nbytes) = case.get("n").unwrap();
|
||||
@@ -373,9 +359,9 @@ macro_rules! encode_test_body {
|
||||
let bigk = $num::from_bytes(kbytes);
|
||||
let k = usize::from(bigk);
|
||||
let e = $num::from(65537u64);
|
||||
let pubkey = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
let pubkey = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
let asn1 = pubkey.to_asn1().unwrap();
|
||||
let (pubkey2, _) = $rsa::from_asn1(&asn1).unwrap();
|
||||
let (pubkey2, _) = RSAPublicKey::from_asn1(&asn1).unwrap();
|
||||
assert_eq!(pubkey, pubkey2);
|
||||
});
|
||||
};
|
||||
@@ -383,7 +369,7 @@ macro_rules! encode_test_body {
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! verify_test_body {
|
||||
($mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||
run_test(fname.to_string(), 7, |case| {
|
||||
let (neg0, nbytes) = case.get("n").unwrap();
|
||||
@@ -400,7 +386,7 @@ macro_rules! verify_test_body {
|
||||
let bigk = $num::from_bytes(kbytes);
|
||||
let k = usize::from(bigk);
|
||||
let e = $num::from(65537u64);
|
||||
let pubkey = $rsa{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
let pubkey = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||
let hashnum = u64::from($num::from_bytes(hbytes));
|
||||
let sighash = match hashnum {
|
||||
160 => &SIGNING_HASH_SHA1,
|
||||
@@ -417,7 +403,7 @@ macro_rules! verify_test_body {
|
||||
|
||||
#[cfg(test)]
|
||||
macro_rules! encrypt_test_body {
|
||||
($mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
let fname = format!("testdata/rsa/encrypt{}.test", $size);
|
||||
run_test(fname.to_string(), 9, |case| {
|
||||
let (neg0, nbytes) = case.get("n").unwrap();
|
||||
@@ -438,8 +424,8 @@ macro_rules! encrypt_test_body {
|
||||
let e = $num::from(65537u64);
|
||||
let d = $num::from_bytes(dbytes);
|
||||
let nu = $bar::from_components(k, n64, nu);
|
||||
let pubkey = $rsa{ n: n.clone(), nu: nu.clone(), e: e };
|
||||
let privkey = $priv{ nu: nu, d: d };
|
||||
let pubkey = RSAPublicKey{ n: n.clone(), nu: nu.clone(), e: e };
|
||||
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||
let cipher = match usize::from($num::from_bytes(hbytes)) {
|
||||
224 => pubkey.encrypt(&OAEPParams::<Sha224>::new(lstr.clone()), mbytes),
|
||||
@@ -463,7 +449,7 @@ macro_rules! encrypt_test_body {
|
||||
}
|
||||
|
||||
macro_rules! generate_tests {
|
||||
($mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
#[cfg(test)]
|
||||
#[allow(non_snake_case)]
|
||||
mod $mod {
|
||||
@@ -475,16 +461,16 @@ macro_rules! generate_tests {
|
||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||
|
||||
#[test]
|
||||
fn new() { new_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[test]
|
||||
fn encode() { encode_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn encode() { encode_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[test]
|
||||
fn verify() { verify_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn verify() { verify_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[test]
|
||||
fn encrypt() { encrypt_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn encrypt() { encrypt_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
}
|
||||
};
|
||||
(ignore $mod: ident, $rsa: ident, $priv: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
(ignore $mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||
#[cfg(test)]
|
||||
#[allow(non_snake_case)]
|
||||
mod $mod {
|
||||
@@ -497,24 +483,24 @@ macro_rules! generate_tests {
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn new() { new_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn encode() { encode_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn encode() { encode_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn verify() { verify_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn verify() { verify_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn encrypt() { encrypt_test_body!($mod, $rsa, $priv, $num, $bar, $num64, $size); }
|
||||
fn encrypt() { encrypt_test_body!($mod, $num, $bar, $num64, $size); }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
generate_tests!(RSA512, RSA512Public, RSA512Private, U512, BarrettU512, U576, 512);
|
||||
generate_tests!(RSA1024, RSA1024Public, RSA1024Private, U1024, BarrettU1024, U1088, 1024);
|
||||
generate_tests!(RSA2048, RSA2048Public, RSA2048Private, U2048, BarrettU2048, U2112, 2048);
|
||||
generate_tests!(RSA3072, RSA3072Public, RSA3072Private, U3072, BarrettU3072, U3136, 3072);
|
||||
generate_tests!(RSA4096, RSA4096Public, RSA4096Private, U4096, BarrettU4096, U4160, 4096);
|
||||
generate_tests!(ignore RSA8192, RSA8192Public, RSA8192Private, U8192, BarrettU8192, U8256, 8192);
|
||||
generate_tests!(ignore RSA15360, RSA15360Public, RSA15360Private, U15360, BarrettU15360, U15424, 15360);
|
||||
generate_tests!( RSA512, U512, BarrettU512, U576, 512);
|
||||
generate_tests!( RSA1024, U1024, BarrettU1024, U1088, 1024);
|
||||
generate_tests!( RSA2048, U2048, BarrettU2048, U2112, 2048);
|
||||
generate_tests!( RSA3072, U3072, BarrettU3072, U3136, 3072);
|
||||
generate_tests!( RSA4096, U4096, BarrettU4096, U4160, 4096);
|
||||
generate_tests!(ignore RSA8192, U8192, BarrettU8192, U8256, 8192);
|
||||
generate_tests!(ignore RSA15360, U15360, BarrettU15360, U15424, 15360);
|
||||
@@ -1,5 +1,5 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use dsa::{DSAKeyPair,DSAParameters,DSAPubKey,DSAPublicKey,DSAPrivKey,DSAPrivateKey,L1024N160};
|
||||
use dsa::{DSAKeyPair,DSAParameters,DSAPublicKey,DSAPrivateKey,L1024N160};
|
||||
use std::io::{Read,Write};
|
||||
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||
use ssh::frame::*;
|
||||
@@ -22,7 +22,7 @@ impl SSHKey for DSAKeyPair<L1024N160> {
|
||||
let pubparams = L1024N160::new(pubp, pubg, pubq);
|
||||
let puby: U1024 = parse_openssh_number(inp)?;
|
||||
for _ in inp.bytes() { return Err(SSHKeyParseError::UnknownTrailingData); }
|
||||
Ok(DSAPubKey::<L1024N160>::new(pubparams.clone(), puby.clone()))
|
||||
Ok(DSAPublicKey::<L1024N160>::new(pubparams.clone(), puby.clone()))
|
||||
}
|
||||
|
||||
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||
@@ -43,7 +43,7 @@ impl SSHKey for DSAKeyPair<L1024N160> {
|
||||
let _ = parse_openssh_buffer(inp)?; // a copy of y we don't need
|
||||
let privx = parse_openssh_number(inp)?;
|
||||
|
||||
let privkey = DSAPrivKey::<L1024N160>::new(privparams, privx);
|
||||
let privkey = DSAPrivateKey::<L1024N160>::new(privparams, privx);
|
||||
let comment = parse_openssh_string(inp)?;
|
||||
for (idx,byte) in inp.bytes().enumerate() {
|
||||
if ((idx+1) as u8) != byte? {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
mod dsa;
|
||||
mod errors;
|
||||
mod frame;
|
||||
mod rsa;
|
||||
|
||||
pub use self::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||
|
||||
@@ -142,7 +143,11 @@ pub fn write_ssh_keyfile<KP,P>(path: P, x: &KP, comment: &str) -> Result<(),SSHK
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
use dsa::{DSAKeyPair,DSAPublicKey,DSAPrivateKey,DSAPubKey,L1024N160};
|
||||
use cryptonum::unsigned::{U1024};
|
||||
#[cfg(test)]
|
||||
use dsa::{DSAKeyPair,DSAPublicKey,L1024N160};
|
||||
#[cfg(test)]
|
||||
use rsa::{RSAKeyPair,RSAPublicKey,SIGNING_HASH_SHA256};
|
||||
#[cfg(test)]
|
||||
use sha2::Sha256;
|
||||
|
||||
@@ -183,7 +188,7 @@ fn read_dsa_examples() {
|
||||
match load_ssh_pubkeys::<DSAKeyPair<L1024N160>,String>(ppath) {
|
||||
Err(e4) => assert!(false, format!("pubkey error: {:?}", e4)),
|
||||
Ok(pubkeys) => {
|
||||
let _ : Vec<(DSAPubKey<L1024N160>,String)> = pubkeys;
|
||||
let _ : Vec<(DSAPublicKey<L1024N160>,String)> = pubkeys;
|
||||
for (pubkey, comment3) in pubkeys {
|
||||
assert_eq!(pubkey.params.p, keypair.public.params.p, "public key check (p)");
|
||||
assert_eq!(pubkey.params.q, keypair.public.params.q, "public key check (q)");
|
||||
@@ -201,3 +206,53 @@ fn read_dsa_examples() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn read_rsa_examples() {
|
||||
let test_files = ["rsa1024-1", "rsa1024-2", "rsa1024-3"];
|
||||
|
||||
for file in test_files.iter() {
|
||||
let path = format!("testdata/ssh/{}",file);
|
||||
let mkeypair = load_ssh_keyfile(path);
|
||||
match mkeypair {
|
||||
Err(e) => assert!(false, format!("reading error: {:?}", e)),
|
||||
Ok((keypair, comment)) => {
|
||||
let buffer = [0,1,2,3,4,6,2];
|
||||
let _ : RSAKeyPair<U1024> = keypair;
|
||||
let sig = keypair.private.sign(&SIGNING_HASH_SHA256, &buffer);
|
||||
assert!(keypair.public.verify(&SIGNING_HASH_SHA256, &buffer, &sig));
|
||||
let buffer2 = [0,1,2,3,4,6,5];
|
||||
assert!(!keypair.public.verify(&SIGNING_HASH_SHA256, &buffer2, &sig));
|
||||
match encode_ssh(&keypair, &comment) {
|
||||
Err(e2) => assert!(false, format!("render error: {:?}", e2)),
|
||||
Ok(encodedstr) => {
|
||||
match decode_ssh(&encodedstr) {
|
||||
Err(e3) => assert!(false, format!("reparse error: {:?}", e3)),
|
||||
Ok((keypair2,comment2)) => {
|
||||
let _ : RSAKeyPair<U1024> = keypair2;
|
||||
assert_eq!(keypair.public.n,keypair2.public.n,"failed to reparse key pair (n)");
|
||||
assert_eq!(keypair.public.e,keypair2.public.e,"failed to reparse key pair (e)");
|
||||
assert_eq!(keypair.private.nu,keypair2.private.nu,"failed to reparse key pair (n)");
|
||||
assert_eq!(keypair.private.d,keypair2.private.d,"failed to reparse key pair (d)");
|
||||
assert_eq!(comment,comment2,"failed to reparse comment");
|
||||
let ppath = format!("testdata/ssh/{}.pub",file);
|
||||
match load_ssh_pubkeys::<RSAKeyPair<U1024>,String>(ppath) {
|
||||
Err(e4) => assert!(false, format!("pubkey error: {:?}", e4)),
|
||||
Ok(pubkeys) => {
|
||||
let _ : Vec<(RSAPublicKey<U1024>,String)> = pubkeys;
|
||||
for (pubkey, comment3) in pubkeys {
|
||||
assert_eq!(pubkey.n, keypair.public.n, "public key check (n)");
|
||||
assert_eq!(pubkey.e, keypair.public.e, "public key check (e)");
|
||||
assert_eq!(comment, comment3, "public key check comment")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src/ssh/rsa.rs
Normal file
79
src/ssh/rsa.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use rsa::{RSAKeyPair,RSAPublicKey,RSAPrivateKey};
|
||||
use std::io::{Read,Write};
|
||||
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||
use ssh::frame::*;
|
||||
use ssh::SSHKey;
|
||||
|
||||
impl SSHKey for RSAKeyPair<U1024> {
|
||||
fn valid_keytype(s: &str) -> bool {
|
||||
(s == "ssh-rsa") || (s == "rsa")
|
||||
}
|
||||
|
||||
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||
{
|
||||
let pubkey_type = parse_openssh_string(inp)?;
|
||||
if !Self::valid_keytype(&pubkey_type) {
|
||||
return Err(SSHKeyParseError::UnknownKeyType(pubkey_type));
|
||||
}
|
||||
let e = parse_openssh_number(inp)?;
|
||||
let n = parse_openssh_number(inp)?;
|
||||
Ok(RSAPublicKey::<U1024>::new(n, e))
|
||||
}
|
||||
|
||||
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||
{
|
||||
let check1 = parse_openssh_u32(inp)?;
|
||||
let check2 = parse_openssh_u32(inp)?;
|
||||
if check1 != check2 {
|
||||
return Err(SSHKeyParseError::PrivateKeyCorruption);
|
||||
}
|
||||
let privkey_type = parse_openssh_string(inp)?;
|
||||
if !Self::valid_keytype(&privkey_type) {
|
||||
return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-rsa".to_string(), privkey_type));
|
||||
}
|
||||
let n = parse_openssh_number(inp)?;
|
||||
let _e: U1024 = parse_openssh_number(inp)?;
|
||||
let d = parse_openssh_number(inp)?;
|
||||
let _iqmp: U1024 = parse_openssh_number(inp)?;
|
||||
let _p: U1024 = parse_openssh_number(inp)?;
|
||||
let _q: U1024 = parse_openssh_number(inp)?;
|
||||
let comment = parse_openssh_string(inp)?;
|
||||
for (idx,byte) in inp.bytes().enumerate() {
|
||||
if ((idx+1) as u8) != byte? {
|
||||
return Err(SSHKeyParseError::InvalidPadding);
|
||||
}
|
||||
}
|
||||
|
||||
Ok((RSAPrivateKey::<U1024>::new(n, d), comment))
|
||||
}
|
||||
|
||||
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||
{
|
||||
render_openssh_string(out, "ssh-rsa")?;
|
||||
render_openssh_number(out, &self.public.e)?;
|
||||
render_openssh_number(out, &self.public.n)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_ssh_private_info<O: Write>(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError>
|
||||
{
|
||||
render_openssh_u32(out, 0xDEADBEEF)?; // FIXME: Any reason for this to be random?
|
||||
render_openssh_u32(out, 0xDEADBEEF)?; // ditto
|
||||
render_openssh_string(out, "ssh-rsa")?;
|
||||
render_openssh_number(out, &self.public.n)?;
|
||||
render_openssh_number(out, &self.public.e)?;
|
||||
render_openssh_number(out, &self.private.d)?;
|
||||
render_openssh_number(out, &self.private.d)?;
|
||||
render_openssh_number(out, &self.private.d)?;
|
||||
render_openssh_number(out, &self.private.d)?;
|
||||
render_openssh_string(out, comment)?;
|
||||
// add some padding (not quite sure why)
|
||||
let mut i = comment.len();
|
||||
while (i % 16) != 0 {
|
||||
out.write(&[(i - comment.len() + 1) as u8])?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ mod name;
|
||||
mod publickey;
|
||||
mod validity;
|
||||
|
||||
use dsa::{DSAPublic,DSAPublicKey};
|
||||
use ecdsa::{ECDSAPublic,ECCPublicKey};
|
||||
use dsa::DSAPublic;
|
||||
use ecdsa::ECDSAPublic;
|
||||
use rsa::{SIGNING_HASH_SHA1,SIGNING_HASH_SHA224,SIGNING_HASH_SHA256,SIGNING_HASH_SHA384,SIGNING_HASH_SHA512};
|
||||
use sha1::Sha1;
|
||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use cryptonum::unsigned::{U3072,U2048,U1024,U256,U192};
|
||||
use dsa::{DSAPublic,DSAPublicKey,DSAPubKey,DSAParameters};
|
||||
use dsa::{DSAPublic,DSAPublicKey,DSAParameters};
|
||||
use dsa::{L3072N256,L2048N256,L2048N224,L1024N160};
|
||||
use ecdsa::{ECDSAEncodeErr,ECDSAPublic,ECCPubKey};
|
||||
use ecdsa::{ECDSAEncodeErr,ECDSAPublic,ECCPublicKey};
|
||||
use ecdsa::curve::{P192,P224,P256,P384,P521};
|
||||
use num::BigUint;
|
||||
use rsa::RSAPublic;
|
||||
@@ -174,7 +174,7 @@ fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result<DSAPublic,X509Pars
|
||||
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||
let y = U3072::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
let key = DSAPubKey::<L3072N256>::new(params, y);
|
||||
let key = DSAPublicKey::<L3072N256>::new(params, y);
|
||||
let reskey = DSAPublic::DSAPublicL3072N256(key);
|
||||
return Ok(reskey);
|
||||
}
|
||||
@@ -195,7 +195,7 @@ fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result<DSAPublic,X509Pars
|
||||
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||
let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
let key = DSAPubKey::<L2048N256>::new(params, y);
|
||||
let key = DSAPublicKey::<L2048N256>::new(params, y);
|
||||
let reskey = DSAPublic::DSAPublicL2048N256(key);
|
||||
return Ok(reskey);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result<DSAPublic,X509Pars
|
||||
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||
let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
let key = DSAPubKey::<L2048N224>::new(params, y);
|
||||
let key = DSAPublicKey::<L2048N224>::new(params, y);
|
||||
let reskey = DSAPublic::DSAPublicL2048N224(key);
|
||||
return Ok(reskey);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result<DSAPublic,X509Pars
|
||||
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||
let y = U1024::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||
let key = DSAPubKey::<L1024N160>::new(params, y);
|
||||
let key = DSAPublicKey::<L1024N160>::new(params, y);
|
||||
let reskey = DSAPublic::DSAPublicL1024N160(key);
|
||||
return Ok(reskey);
|
||||
}
|
||||
@@ -271,27 +271,27 @@ fn decode_ecdsa_key(info: ASN1Block, keybls: &[ASN1Block]) -> Result<ECDSAPublic
|
||||
{
|
||||
if let ASN1Block::ObjectIdentifier(_, _, oid) = info {
|
||||
if oid == oid!(1,2,840,10045,3,1,1) {
|
||||
let (res, _) = ECCPubKey::<P192>::from_asn1(keybls)?;
|
||||
let (res, _) = ECCPublicKey::<P192>::from_asn1(keybls)?;
|
||||
return Ok(ECDSAPublic::ECCPublicP192(res));
|
||||
}
|
||||
|
||||
if oid == oid!(1,3,132,0,33) {
|
||||
let (res, _) = ECCPubKey::<P224>::from_asn1(keybls)?;
|
||||
let (res, _) = ECCPublicKey::<P224>::from_asn1(keybls)?;
|
||||
return Ok(ECDSAPublic::ECCPublicP224(res));
|
||||
}
|
||||
|
||||
if oid == oid!(1,2,840,10045,3,1,7) {
|
||||
let (res, _) = ECCPubKey::<P256>::from_asn1(keybls)?;
|
||||
let (res, _) = ECCPublicKey::<P256>::from_asn1(keybls)?;
|
||||
return Ok(ECDSAPublic::ECCPublicP256(res));
|
||||
}
|
||||
|
||||
if oid == oid!(1,3,132,0,34) {
|
||||
let (res, _) = ECCPubKey::<P384>::from_asn1(keybls)?;
|
||||
let (res, _) = ECCPublicKey::<P384>::from_asn1(keybls)?;
|
||||
return Ok(ECDSAPublic::ECCPublicP384(res));
|
||||
}
|
||||
|
||||
if oid == oid!(1,3,132,0,35) {
|
||||
let (res, _) = ECCPubKey::<P521>::from_asn1(keybls)?;
|
||||
let (res, _) = ECCPublicKey::<P521>::from_asn1(keybls)?;
|
||||
return Ok(ECDSAPublic::ECCPublicP521(res));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user