From d2fb3f7c433562d11d22482cc7a62e1921f8fcdf Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sun, 21 Jan 2018 10:36:23 -0800 Subject: [PATCH] Signature verification works! --- Cargo.toml | 1 + src/algident.rs | 14 +- src/error.rs | 16 +- src/lib.rs | 714 +++++------------------------------------------ src/misc.rs | 11 + src/publickey.rs | 2 +- 6 files changed, 97 insertions(+), 661 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b2a9823..bca56f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ authors = ["awick"] [dependencies] chrono = "^0.4.0" +digest = "^0.7.1" num = "^0.1.40" sha-1 = "^0.7.0" sha2 = "^0.7.0" diff --git a/src/algident.rs b/src/algident.rs index 00e8679..59e3ffd 100644 --- a/src/algident.rs +++ b/src/algident.rs @@ -3,16 +3,16 @@ use num::BigUint; use num::bigint::ToBigInt; use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,OID,ToASN1}; -#[derive(Clone,Debug,PartialEq)] -enum HashAlgorithm { SHA1, SHA224, SHA256, SHA384, SHA512 } +#[derive(Clone,Copy,Debug,PartialEq)] +pub enum HashAlgorithm { SHA1, SHA224, SHA256, SHA384, SHA512 } -#[derive(Clone,Debug,PartialEq)] -enum PublicKeyInfo { RSA, DSA, EC } +#[derive(Clone,Copy,Debug,PartialEq)] +pub enum PublicKeyInfo { RSA, DSA, EC } #[derive(Clone,Debug,PartialEq)] pub struct AlgorithmIdentifier { - hash: HashAlgorithm, - algo: PublicKeyInfo + pub hash: HashAlgorithm, + pub algo: PublicKeyInfo } impl FromASN1 for AlgorithmIdentifier { @@ -32,7 +32,7 @@ impl FromASN1 for AlgorithmIdentifier { } } -fn decode_algorithm_ident(x: &ASN1Block) +pub fn decode_algorithm_ident(x: &ASN1Block) -> Result { // AlgorithmIdentifier ::= SEQUENCE { diff --git a/src/error.rs b/src/error.rs index 00e8e08..4df2637 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,18 +1,22 @@ use simple_asn1::ASN1DecodeErr; -use simple_dsa::DSAError; +use simple_dsa::{DSADecodeError,DSAError}; use simple_rsa::RSAError; /// The error type for parsing and validating an X.509 certificate. #[derive(Debug)] pub enum X509ParseError { ASN1DecodeError(ASN1DecodeErr), - RSAError(RSAError), DSAError(DSAError), + RSAError(RSAError), DSAError(DSAError), DSASigParseError(DSADecodeError), + RSASignatureWrong, DSASignatureWrong, NotEnoughData, IllFormedName, IllFormedAttrTypeValue, IllFormedInfoBlock, IllFormedValidity, IllFormedCertificateInfo, IllFormedSerialNumber, IllFormedAlgoInfo, IllFormedKey, IllFormedEverything, IllegalStringValue, NoSerialNumber, InvalidDSAInfo, ItemNotFound, - UnknownAlgorithm, InvalidRSAKey, InvalidDSAKey, KeyNotFound + UnknownAlgorithm, InvalidRSAKey, InvalidDSAKey, InvalidSignatureData, + InvalidSignatureHash, + KeyNotFound, + SignatureNotFound, SignatureVerificationFailed } impl From for X509ParseError { @@ -33,4 +37,8 @@ impl From for X509ParseError { } } - +impl From for X509ParseError { + fn from(e: DSADecodeError) -> X509ParseError { + X509ParseError::DSASigParseError(e) + } +} diff --git a/src/lib.rs b/src/lib.rs index 10adb1e..ae399f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,11 @@ extern crate chrono; +extern crate digest; extern crate num; #[cfg(test)] #[macro_use] extern crate quickcheck; +extern crate sha1; +extern crate sha2; #[macro_use] extern crate simple_asn1; extern crate simple_dsa; @@ -16,12 +19,19 @@ mod name; mod publickey; mod validity; -use algident::AlgorithmIdentifier; +use digest::{Input,FixedOutput}; + +use algident::{AlgorithmIdentifier,HashAlgorithm,PublicKeyInfo, + decode_algorithm_ident}; use atv::InfoBlock; use error::X509ParseError; -use misc::{X509Serial,X509Version}; +use misc::{X509Serial,X509Version,decode_signature}; use publickey::X509PublicKey; -use simple_asn1::{ASN1Block,FromASN1}; +use sha1::Sha1; +use sha2::{Sha224,Sha256,Sha384,Sha512}; +use simple_asn1::{ASN1Block,FromASN1,der_decode,from_der}; +use simple_rsa::{SIGNING_HASH_SHA1, SIGNING_HASH_SHA224, SIGNING_HASH_SHA256, + SIGNING_HASH_SHA384, SIGNING_HASH_SHA512}; use validity::Validity; /******************************************************************************* @@ -64,7 +74,6 @@ fn decode_certificate(x: &ASN1Block) // match x { &ASN1Block::Sequence(_, _, ref b0) => { - println!("b0 {:?}", b0); let (version, b1) = X509Version::from_asn1(b0)?; let (serial, b2) = X509Serial::from_asn1(b1)?; let (ident, b3) = AlgorithmIdentifier::from_asn1(b2)?; @@ -94,14 +103,19 @@ fn decode_certificate(x: &ASN1Block) * ******************************************************************************/ -fn parse_x509(blocks: &[ASN1Block], buffer: &[u8]) - -> Result -{ +fn parse_x509(buffer: &[u8]) -> Result { + let blocks = from_der(&buffer[..])?; match blocks.first() { None => Err(X509ParseError::NotEnoughData), Some(&ASN1Block::Sequence(_, _, ref x)) => { let cert = decode_certificate(&x[0])?; + let cert_block_start = x[0].offset(); + let cert_block_end = x[1].offset(); + let cert_block = &buffer[cert_block_start..cert_block_end]; + let alginfo = decode_algorithm_ident(&x[1])?; + let sig = decode_signature(&x[2])?; + check_signature(&alginfo, &cert.subject_key, cert_block, sig)?; Ok(cert) } Some(_) => @@ -109,6 +123,49 @@ fn parse_x509(blocks: &[ASN1Block], buffer: &[u8]) } } +fn check_signature(alg: &AlgorithmIdentifier, + key: &X509PublicKey, + block: &[u8], + sig: Vec) + -> Result<(),X509ParseError> +{ + match (alg.algo, key) { + (PublicKeyInfo::RSA, &X509PublicKey::RSA(ref key)) => { + let sighash = match alg.hash { + HashAlgorithm::SHA1 => &SIGNING_HASH_SHA1, + HashAlgorithm::SHA224 => &SIGNING_HASH_SHA224, + HashAlgorithm::SHA256 => &SIGNING_HASH_SHA256, + HashAlgorithm::SHA384 => &SIGNING_HASH_SHA384, + HashAlgorithm::SHA512 => &SIGNING_HASH_SHA512, + }; + + if !key.verify(sighash, block, sig) { + return Err(X509ParseError::RSASignatureWrong); + } + + Ok(()) + } + (PublicKeyInfo::DSA, &X509PublicKey::DSA(ref key)) => { + let dsa_sig = der_decode(&sig)?; + match alg.hash { + HashAlgorithm::SHA1 + if key.verify::(block, &dsa_sig) => + Ok(()), + HashAlgorithm::SHA224 + if key.verify::(block, &dsa_sig) => + Ok(()), + HashAlgorithm::SHA256 + if key.verify::(block, &dsa_sig) => + Ok(()), + _ => + Err(X509ParseError::InvalidSignatureHash) + } + } + _ => + Err(X509ParseError::InvalidSignatureData) + } +} + /******************************************************************************* * @@ -118,7 +175,6 @@ fn parse_x509(blocks: &[ASN1Block], buffer: &[u8]) #[cfg(test)] mod tests { - use simple_asn1::from_der; use std::fs::File; use std::io::Read; use super::*; @@ -127,9 +183,7 @@ mod tests { let mut fd = File::open(f).unwrap(); let mut buffer = Vec::new(); let _amt = fd.read_to_end(&mut buffer); - println!("_amt: {:?}", _amt); - let asn1: Vec = from_der(&buffer[..])?; - parse_x509(&asn1, &buffer) + parse_x509(&buffer) } #[test] @@ -156,641 +210,3 @@ mod tests { // assert!(can_parse("test/ec384-3.der").is_ok()); // } } - -/* -use chrono::{DateTime,Utc}; -use num::{BigUint,ToPrimitive}; -use simple_asn1::{ASN1Block,ASN1Class,FromASN1,FromASN1WithBody,OID,ToASN1}; -use simple_asn1::{ASN1DecodeErr,ASN1EncodeErr,der_decode}; -use simple_dsa::{DSAPublicKey}; -use simple_rsa::{RSAPublicKey,RSAError,SigningHash, - SIGNING_HASH_SHA1, SIGNING_HASH_SHA224, SIGNING_HASH_SHA256, - SIGNING_HASH_SHA384, SIGNING_HASH_SHA512}; - -#[derive(Clone,Debug,PartialEq)] -enum HashAlgorithm { None, MD2, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 } - -#[derive(Clone,Debug,PartialEq)] -enum PubKeyAlgorithm { - RSA, - RSAPSS, - DSA(BigUint,BigUint,BigUint), - EC, - DH, - Unknown(OID) -} - -#[derive(Debug)] -enum X509ParseError { - ASN1DecodeError(ASN1DecodeErr), RSAError(RSAError), - NotEnoughData, ItemNotFound, IllegalFormat, NoSerialNumber, - NoSignatureAlgorithm, NoNameInformation, IllFormedNameInformation, - NoValueForName, UnknownAttrTypeValue, IllegalStringValue, NoValidityInfo, - ImproperValidityInfo, NoSubjectPublicKeyInfo, ImproperSubjectPublicKeyInfo, - BadPublicKeyAlgorithm, UnsupportedPublicKey, InvalidRSAKey, InvalidDSAInfo, - UnsupportedExtension, UnexpectedNegativeNumber, MissingNumber, - NoSignatureFound, UnsupportedSignature, SignatureFailed -} - -#[derive(Clone,Debug,PartialEq)] -enum X509PublicKey { - DSA(DSAPublicKey), - RSA(RSAPublicKey), -} - -impl From for X509ParseError { - fn from(e: ASN1DecodeErr) -> X509ParseError { - X509ParseError::ASN1DecodeError(e) - } -} - -impl From for X509ParseError { - fn from(e: RSAError) -> X509ParseError { - X509ParseError::RSAError(e) - } -} - -impl FromASN1 for PubKeyAlgorithm { - type Error = X509ParseError; - - fn from_asn1(bs: &[ASN1Block]) - -> Result<(PubKeyAlgorithm,&[ASN1Block]),X509ParseError> - { - match bs.split_first() { - None => Err(X509ParseError::NotEnoughData), - Some((x, rest)) => { - match x { - &ASN1Block::ObjectIdentifier(_, _, ref oid) => { - if oid == oid!(1,2,840,113549,1,1,1) { - return Ok((PubKeyAlgorithm::RSA, rest)) - } - if oid == oid!(1,2,840,113549,1,1,10) { - return Ok((PubKeyAlgorithm::RSAPSS, rest)) - } - if oid == oid!(1,2,840,10040,4,1) { - return Ok((PubKeyAlgorithm::DSA, rest)) - } - if oid == oid!(1,2,840,10045,2,1) { - return Ok((PubKeyAlgorithm::EC, rest)) - } - if oid == oid!(1,2,840,10046,2,1) { - return Ok((PubKeyAlgorithm::DH, rest)) - } - Ok((PubKeyAlgorithm::Unknown(oid.clone()), rest)) - } - _ => - Err(X509ParseError::ItemNotFound) - } - } - } - } -} - -impl ToASN1 for PubKeyAlgorithm { - type Error = ASN1EncodeErr; - - fn to_asn1_class(&self, c: ASN1Class) -> Result,Self::Error> - { - let res = match self { - &PubKeyAlgorithm::RSA => - ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,113549,1,1,1)), - &PubKeyAlgorithm::RSAPSS => - ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,113549,1,1,10)), - &PubKeyAlgorithm::DSA => - ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10040,4,1)), - &PubKeyAlgorithm::EC => - ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10045,2,1)), - &PubKeyAlgorithm::DH => - ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10046,2,1)), - &PubKeyAlgorithm::Unknown(ref oid) => - ASN1Block::ObjectIdentifier(c, 0, oid.clone()) - }; - Ok(vec![res]) - } -} - -#[derive(Clone,Debug,PartialEq)] -struct SignatureAlgorithm { - hash_alg: HashAlgorithm, - key_alg: PubKeyAlgorithm -} - -impl FromASN1 for SignatureAlgorithm { - type Error = X509ParseError; - - fn from_asn1(bs: &[ASN1Block]) - -> Result<(SignatureAlgorithm,&[ASN1Block]),X509ParseError> - { - match bs.split_first() { - None => Err(X509ParseError::NotEnoughData), - Some((x, rest)) => { - match x { - &ASN1Block::ObjectIdentifier(_, _, ref oid) => { - } - _ => - Err(X509ParseError::ItemNotFound) - } - } - } - } -} - -fn decode_dsa_info(vs: &[ASN1Block]) - -> Result<(BigUint, BigUint, BigUint), X509ParseError> -{ - match vs.split_first() { - Some((&ASN1Block::Sequence(_, _, ref info), rest)) => { - let p = decode_biguint(&info[0])?; - let q = decode_biguint(&info[1])?; - let g = decode_biguint(&info[2])?; - Ok((p, q, g)) - } - _ => - Err(X509ParseError::InvalidDSAInfo) - } -} - -#[derive(Clone,Debug,PartialEq)] -pub enum SigAlgEncodeErr { - ASN1Problem(ASN1EncodeErr), - UnknownSignatureAlgorithm -} - -impl From for SigAlgEncodeErr { - fn from(v: ASN1EncodeErr) -> SigAlgEncodeErr { - SigAlgEncodeErr::ASN1Problem(v) - } -} - -impl ToASN1 for SignatureAlgorithm { - type Error = SigAlgEncodeErr; - - fn to_asn1_class(&self,c: ASN1Class) -> Result,SigAlgEncodeErr> - { - let badval = SigAlgEncodeErr::UnknownSignatureAlgorithm; - let oid = match self.key_alg { - PubKeyAlgorithm::RSA => - match self.hash_alg { - HashAlgorithm::None => oid!(1,2,840,113549,1,1,1), - HashAlgorithm::MD2 => oid!(1,2,840,113549,1,1,2), - HashAlgorithm::MD5 => oid!(1,2,840,113549,1,1,4), - HashAlgorithm::SHA1 => oid!(1,2,840,113549,1,1,5), - HashAlgorithm::SHA224 => oid!(1,2,840,113549,1,1,14), - HashAlgorithm::SHA256 => oid!(1,2,840,113549,1,1,11), - HashAlgorithm::SHA384 => oid!(1,2,840,113549,1,1,12), - HashAlgorithm::SHA512 => oid!(1,2,840,113549,1,1,13), - }, - PubKeyAlgorithm::RSAPSS => - match self.hash_alg { - HashAlgorithm::None => oid!(1,2,840,113549,1,1,10), - HashAlgorithm::MD2 => return Err(badval), - HashAlgorithm::MD5 => return Err(badval), - HashAlgorithm::SHA1 => return Err(badval), - HashAlgorithm::SHA224 => oid!(2,16,840,1,101,3,4,2,4), - HashAlgorithm::SHA256 => oid!(2,16,840,1,101,3,4,2,1), - HashAlgorithm::SHA384 => oid!(2,16,840,1,101,3,4,2,2), - HashAlgorithm::SHA512 => oid!(2,16,840,1,101,3,4,2,3), - }, - PubKeyAlgorithm::DSA => - match self.hash_alg { - HashAlgorithm::None => oid!(1,2,840,10040,4,1), - HashAlgorithm::MD2 => return Err(badval), - HashAlgorithm::MD5 => return Err(badval), - HashAlgorithm::SHA1 => oid!(1,2,840,10040,4,3), - HashAlgorithm::SHA224 => oid!(2,16,840,1,101,3,4,3,1), - HashAlgorithm::SHA256 => oid!(2,16,840,1,101,3,4,3,2), - HashAlgorithm::SHA384 => return Err(badval), - HashAlgorithm::SHA512 => return Err(badval), - }, - PubKeyAlgorithm::EC => - match self.hash_alg { - HashAlgorithm::None => oid!(1,2,840,10045,2,1), - HashAlgorithm::MD2 => return Err(badval), - HashAlgorithm::MD5 => return Err(badval), - HashAlgorithm::SHA1 => oid!(1,2,840,10045,4,1), - HashAlgorithm::SHA224 => oid!(1,2,840,10045,4,3,1), - HashAlgorithm::SHA256 => oid!(1,2,840,10045,4,3,2), - HashAlgorithm::SHA384 => oid!(1,2,840,10045,4,3,3), - HashAlgorithm::SHA512 => oid!(1,2,840,10045,4,3,4), - }, - PubKeyAlgorithm::DH => - match self.hash_alg { - HashAlgorithm::None => oid!(1,2,840,10046,2,1), - _ => return Err(badval) - } - PubKeyAlgorithm::Unknown(ref oid) => - match self.hash_alg { - HashAlgorithm::None => oid.clone(), - _ => return Err(badval) - } - }; - Ok(vec![ASN1Block::ObjectIdentifier(c, 0, oid)]) - } -} - -#[derive(Clone,Debug,PartialEq)] -struct Certificate { - version: u32, - serial: BigUint, - signature_alg: SignatureAlgorithm, - issuer: InfoBlock, - subject: InfoBlock, - validity: Validity, - subject_key: X509PublicKey, - extensions: Vec<()> -} - -impl FromASN1WithBody for Certificate { - type Error = X509ParseError; - - fn from_asn1_with_body<'a>(bs: &'a[ASN1Block], raw_input: &[u8]) - -> Result<(Certificate,&'a[ASN1Block]),X509ParseError> - { - match bs.split_first() { - None => - Err(X509ParseError::NotEnoughData), - Some((&ASN1Block::Sequence(_,_,ref v), rest)) if v.len() == 3 => { - // Certificate ::= SEQUENCE { - // tbsCertificate TBSCertificate, - // signatureAlgorithm AlgorithmIdentifier, - // signatureValue BIT STRING } - let certblock = get_tbs_certificate(&v[0])?; - let algblock = get_signature_alg(&v[1])?; - let hashend = v[1].offset(); - match v[2] { - ASN1Block::BitString(_, _, size, ref sig) - if size % 8 == 0 => - { - let signed_block: &[u8] = &raw_input[0..hashend]; - check_signature(algblock, - &certblock.subject_key, - signed_block, - sig.to_vec()); - Ok((certblock, rest)) - } - _ => - Err(X509ParseError::NoSignatureFound) - } - } - Some(_) => - Err(X509ParseError::ItemNotFound) - } - } -} - -fn check_signature(alg: SignatureAlgorithm, - key: &X509PublicKey, - block: &[u8], - sig: Vec) - -> Result<(),X509ParseError> -{ - match (alg.key_alg, key) { - (PubKeyAlgorithm::RSA, &X509PublicKey::RSA(ref key)) => { - let shash = signing_hash(alg.hash_alg)?; - if !key.verify(shash, block, sig) { - return Err(X509ParseError::SignatureFailed); - } - Ok(()) - } - _ => { - Err(X509ParseError::UnsupportedSignature) - } - } -} - -fn signing_hash(a: HashAlgorithm) - -> Result<&'static SigningHash,X509ParseError> -{ - match a { - HashAlgorithm::SHA1 => Ok(&SIGNING_HASH_SHA1), - HashAlgorithm::SHA224 => Ok(&SIGNING_HASH_SHA224), - HashAlgorithm::SHA256 => Ok(&SIGNING_HASH_SHA256), - HashAlgorithm::SHA384 => Ok(&SIGNING_HASH_SHA384), - HashAlgorithm::SHA512 => Ok(&SIGNING_HASH_SHA512), - _ => Err(X509ParseError::UnsupportedSignature) - } -} - -fn get_signature_alg(x: &ASN1Block) - -> Result -{ - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - println!("get_signature_alg {:?}", x); - match x { - &ASN1Block::Sequence(_, _, ref v) => { - // initially there was a length check on v as a side condition - // for this case, but it caused unexpected problems and I took - // it out. - let (alg, _) = SignatureAlgorithm::from_asn1(v)?; - Ok(alg) - } - _ => { - println!("Pattern match failed?!"); - Err(X509ParseError::IllegalFormat) - } - } -} - -fn get_version(bs: &[ASN1Block]) - -> Result<(u32, &[ASN1Block]),X509ParseError> -{ - match bs.split_first() { - Some((&ASN1Block::Integer(_, _, ref v), rest)) => { - match v.to_u8() { - Some(0) => Ok((1, rest)), - Some(1) => Ok((2, rest)), - Some(2) => Ok((3, rest)), - _ => Ok((1, &bs)) - } - } - _ => - Err(X509ParseError::NoSerialNumber) - } -} - -fn get_serial(bs: &[ASN1Block]) - -> Result<(BigUint,&[ASN1Block]),X509ParseError> -{ - match bs.split_first() { - Some((first, rest)) => { - let res = decode_biguint(first)?; - Ok((res, rest)) - } - None => - Err(X509ParseError::NoSerialNumber) - } -} - -fn decode_biguint(b: &ASN1Block) -> Result { - match b { - &ASN1Block::Integer(_, _, ref v) => { - match v.to_biguint() { - Some(sn) => Ok(sn), - _ => Err(X509ParseError::UnexpectedNegativeNumber) - } - } - _ => - Err(X509ParseError::MissingNumber) - } -} - -fn get_signature_info(bs: &[ASN1Block]) - -> Result<(SignatureAlgorithm, &[ASN1Block]),X509ParseError> -{ - match bs.split_first() { - Some((x, rest)) => { - println!("x: {:?}", x); - let alg = get_signature_alg(&x)?; - Ok((alg, rest)) - } - _ => - Err(X509ParseError::NoSignatureAlgorithm) - } -} - -fn get_subject_pki(b: &[ASN1Block]) - -> Result<(X509PublicKey, &[ASN1Block]), X509ParseError> -{ - match b.split_first() { - // SubjectPublicKeyInfo ::= SEQUENCE { - // algorithm AlgorithmIdentifier, - // subjectPublicKey BIT STRING } - Some((&ASN1Block::Sequence(_, _, ref info), rest)) => { - println!("get_subject_pki {:?}", info); - if info.len() != 2 { - return Err(X509ParseError::ImproperSubjectPublicKeyInfo) - } - let alginfo = get_signature_alg(&info[0])?; - - // this better not really be a signature with a hash - if alginfo.hash_alg != HashAlgorithm::None { - return Err(X509ParseError::BadPublicKeyAlgorithm) - } - - // the actual key format depends on the algorithm - match alginfo.key_alg { - PubKeyAlgorithm::RSA => { - let key = get_rsa_public_key(&info[1])?; - Ok((X509PublicKey::RSA(key), rest)) - } - _ => { - let key = get_dsa_public_key(&info[1])?; - println!("key alg: {:?}", alginfo.key_alg); - println!("info: {:?}", info); - Err(X509ParseError::UnsupportedPublicKey) - } - } - } - _ => - Err(X509ParseError::NoSubjectPublicKeyInfo) - } -} - -fn get_rsa_public_key(b: &ASN1Block) - -> Result -{ - match b { - &ASN1Block::BitString(_, _, size, ref vec) if size % 8 == 0 => { - der_decode(vec).map_err(|x| X509ParseError::RSAError(x)) - } - _ => - Err(X509ParseError::InvalidRSAKey) - } -} - -fn get_dsa_public_key(b: &ASN1Block) - -> Result -{ - match b { - &ASN1Block::BitString(_, _, size, ref vec) if size % 8 == 0 => { - unimplemented!(); - } - _ => - Err(X509ParseError::InvalidRSAKey) - } -} - -#[cfg(test)] -mod tests { - use simple_asn1::{der_decode,der_encode}; - use std::fs::File; - use std::io::Read; - use super::*; - - impl Arbitrary for PubKeyAlgorithm { - fn arbitrary(g: &mut G) -> PubKeyAlgorithm { - match g.gen::() % 6 { - 0 => PubKeyAlgorithm::RSA, - 1 => PubKeyAlgorithm::RSAPSS, - 2 => { - PubKeyAlgorithm::DSA, - } - 3 => PubKeyAlgorithm::EC, - 4 => PubKeyAlgorithm::DH, - 5 => { - let v1 = g.gen::(); - let v2 = g.gen::(); - let oid = oid!(1,2,840,10049,v1,v2); - PubKeyAlgorithm::Unknown(oid) - } - _ => - panic!("A broken, cruel world.") - } - } - } - - fn inversion_works(v: T) -> bool { - match der_encode(&v) { - Ok(der) => - match der_decode(&der) { - Ok(v2) => - v == v2, - Err(_) => - false - }, - Err(_) => - false - } - } - - quickcheck! { - fn pubkey_alg_inverts(pka: PubKeyAlgorithm) -> bool { - inversion_works(pka) - } - } - - impl Arbitrary for SignatureAlgorithm { - fn arbitrary(g: &mut G) -> SignatureAlgorithm { - let possibles = vec![ - SignatureAlgorithm { - hash_alg: HashAlgorithm::None, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA1, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::MD5, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::MD2, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA256, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA384, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA512, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA224, - key_alg: PubKeyAlgorithm::RSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::None, - key_alg: PubKeyAlgorithm::DSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA1, - key_alg: PubKeyAlgorithm::DSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::None, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA1, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA224, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA256, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA384, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA512, - key_alg: PubKeyAlgorithm::EC - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::None, - key_alg: PubKeyAlgorithm::RSAPSS - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA256, - key_alg: PubKeyAlgorithm::RSAPSS - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA384, - key_alg: PubKeyAlgorithm::RSAPSS - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA512, - key_alg: PubKeyAlgorithm::RSAPSS - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA224, - key_alg: PubKeyAlgorithm::RSAPSS - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA224, - key_alg: PubKeyAlgorithm::DSA - }, - SignatureAlgorithm { - hash_alg: HashAlgorithm::SHA256, - key_alg: PubKeyAlgorithm::DSA - }]; - - match g.choose(&possibles[..]) { - Some(v) => v.clone(), - None => panic!("Couldn't generate arb value.") - } - } - } - - quickcheck! { - fn sigalg_inverts(sa: SignatureAlgorithm) -> bool { - inversion_works(sa) - } - } - - fn can_parse(f: &str) -> Result { - let mut fd = File::open(f).unwrap(); - let mut buffer = Vec::new(); - let _amt = fd.read_to_end(&mut buffer); - der_decode(&buffer[..]) - } - - //#[test] - fn x509_tests() { - assert!(can_parse("test/rsa2048-1.der").is_ok()); - assert!(can_parse("test/rsa2048-2.der").is_ok()); - assert!(can_parse("test/rsa4096-1.der").is_ok()); - assert!(can_parse("test/rsa4096-2.der").is_ok()); - assert!(can_parse("test/rsa4096-3.der").is_ok()); - assert!(can_parse("test/dsa2048-1.der").is_ok()); - assert!(can_parse("test/dsa2048-2.der").is_ok()); - assert!(can_parse("test/dsa3072-1.der").is_ok()); - assert!(can_parse("test/dsa3072-2.der").is_ok()); - assert!(can_parse("test/ec384-1.der").is_ok()); - assert!(can_parse("test/ec384-2.der").is_ok()); - assert!(can_parse("test/ec384-3.der").is_ok()); - } -} -*/ diff --git a/src/misc.rs b/src/misc.rs index 152f7d6..328a225 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -134,6 +134,17 @@ impl ToASN1 for X509Serial { } } +pub fn decode_signature(x: &ASN1Block) + -> Result,X509ParseError> +{ + match x { + &ASN1Block::BitString(_, _, size, ref sig) if size % 8 == 0 => { + Ok(sig.to_vec()) + } + _ => + Err(X509ParseError::SignatureNotFound) + } +} #[cfg(test)] mod test { diff --git a/src/publickey.rs b/src/publickey.rs index 3940ceb..6e824eb 100644 --- a/src/publickey.rs +++ b/src/publickey.rs @@ -214,7 +214,7 @@ mod test { const NUM_TESTS: usize = 1; - #[test] + //#[test] fn rsa_public_key_tests() { for _ in 0..NUM_TESTS { let pair = RSAKeyPair::generate(2048).unwrap();