Migrate DSA sign/verify to EVP APIs
This commit is contained in:
parent
228b8fbc5b
commit
6609a81685
|
|
@ -110,6 +110,7 @@ pub const CRYPTO_LOCK: c_int = 1;
|
|||
pub const EVP_MAX_MD_SIZE: c_uint = 64;
|
||||
pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption;
|
||||
pub const EVP_PKEY_HMAC: c_int = NID_hmac;
|
||||
pub const EVP_PKEY_DSA: c_int = NID_dsa;
|
||||
|
||||
pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1;
|
||||
pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2;
|
||||
|
|
@ -120,6 +121,7 @@ pub const MBSTRING_UTF8: c_int = MBSTRING_FLAG;
|
|||
pub const NID_rsaEncryption: c_int = 6;
|
||||
pub const NID_ext_key_usage: c_int = 126;
|
||||
pub const NID_key_usage: c_int = 83;
|
||||
pub const NID_dsa: c_int = 116;
|
||||
pub const NID_hmac: c_int = 855;
|
||||
|
||||
pub const PKCS5_SALT_LEN: c_int = 8;
|
||||
|
|
|
|||
|
|
@ -2,16 +2,14 @@ use ffi;
|
|||
use std::fmt;
|
||||
use error::ErrorStack;
|
||||
use std::ptr;
|
||||
use libc::{c_uint, c_int, c_char, c_void};
|
||||
use libc::{c_int, c_char, c_void};
|
||||
|
||||
use bn::BigNumRef;
|
||||
use bio::{MemBio, MemBioSlice};
|
||||
use crypto::hash;
|
||||
use HashTypeInternals;
|
||||
use crypto::util::{CallbackState, invoke_passwd_cb};
|
||||
|
||||
|
||||
/// Builder for upfront DSA parameter generateration
|
||||
/// Builder for upfront DSA parameter generation
|
||||
pub struct DSAParams(*mut ffi::DSA);
|
||||
|
||||
impl DSAParams {
|
||||
|
|
@ -156,39 +154,6 @@ impl DSA {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
||||
let k_len = self.size().expect("DSA missing a q") as c_uint;
|
||||
let mut sig = vec![0; k_len as usize];
|
||||
let mut sig_len = k_len;
|
||||
assert!(self.has_private_key());
|
||||
|
||||
unsafe {
|
||||
try_ssl!(ffi::DSA_sign(hash.as_nid() as c_int,
|
||||
message.as_ptr(),
|
||||
message.len() as c_int,
|
||||
sig.as_mut_ptr(),
|
||||
&mut sig_len,
|
||||
self.0));
|
||||
sig.set_len(sig_len as usize);
|
||||
sig.shrink_to_fit();
|
||||
Ok(sig)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let result = ffi::DSA_verify(hash.as_nid() as c_int,
|
||||
message.as_ptr(),
|
||||
message.len() as c_int,
|
||||
sig.as_ptr(),
|
||||
sig.len() as c_int,
|
||||
self.0);
|
||||
|
||||
try_ssl_if!(result == -1);
|
||||
Ok(result == 1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::DSA {
|
||||
self.0
|
||||
}
|
||||
|
|
@ -282,76 +247,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
pub fn test_generate() {
|
||||
let key = DSA::generate(1024).unwrap();
|
||||
|
||||
key.public_key_to_pem().unwrap();
|
||||
key.private_key_to_pem().unwrap();
|
||||
|
||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||
|
||||
let digest = {
|
||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
||||
sha.write_all(&input).unwrap();
|
||||
sha.finish().unwrap()
|
||||
};
|
||||
|
||||
let sig = key.sign(Type::SHA1, &digest).unwrap();
|
||||
let verified = key.verify(Type::SHA1, &digest, &sig).unwrap();
|
||||
assert!(verified);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sign_verify() {
|
||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||
|
||||
let private_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem");
|
||||
DSA::private_key_from_pem(key).unwrap()
|
||||
};
|
||||
|
||||
let public_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||
DSA::public_key_from_pem(key).unwrap()
|
||||
};
|
||||
|
||||
let digest = {
|
||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
||||
sha.write_all(&input).unwrap();
|
||||
sha.finish().unwrap()
|
||||
};
|
||||
|
||||
let sig = private_key.sign(Type::SHA1, &digest).unwrap();
|
||||
let verified = public_key.verify(Type::SHA1, &digest, &sig).unwrap();
|
||||
assert!(verified);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sign_verify_fail() {
|
||||
let input: Vec<u8> = (0..25).cycle().take(128).collect();
|
||||
let private_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem");
|
||||
DSA::private_key_from_pem(key).unwrap()
|
||||
};
|
||||
|
||||
let public_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||
DSA::public_key_from_pem(key).unwrap()
|
||||
};
|
||||
|
||||
let digest = {
|
||||
let mut sha = Hasher::new(Type::SHA1).unwrap();
|
||||
sha.write_all(&input).unwrap();
|
||||
sha.finish().unwrap()
|
||||
};
|
||||
|
||||
let mut sig = private_key.sign(Type::SHA1, &digest).unwrap();
|
||||
// tamper with the sig this should cause a failure
|
||||
let len = sig.len();
|
||||
sig[len / 2] = 0;
|
||||
sig[len - 1] = 0;
|
||||
if let Ok(true) = public_key.verify(Type::SHA1, &digest, &sig) {
|
||||
panic!("Tampered with signatures should not verify!");
|
||||
}
|
||||
DSA::generate(1024).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::mem;
|
|||
use ffi;
|
||||
|
||||
use bio::{MemBio, MemBioSlice};
|
||||
use crypto::dsa::DSA;
|
||||
use crypto::rsa::RSA;
|
||||
use error::ErrorStack;
|
||||
use crypto::util::{CallbackState, invoke_passwd_cb};
|
||||
|
|
@ -26,6 +27,17 @@ impl PKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new `PKey` containing a DSA key.
|
||||
pub fn from_dsa(dsa: DSA) -> Result<PKey, ErrorStack> {
|
||||
unsafe {
|
||||
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
||||
let pkey = PKey(evp);
|
||||
try_ssl!(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DSA, dsa.as_ptr() as *mut _));
|
||||
mem::forget(dsa);
|
||||
Ok(pkey)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new `PKey` containing an HMAC key.
|
||||
pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ impl<'a> Signer<'a> {
|
|||
let mut buf = vec![0; len];
|
||||
try_ssl_if!(ffi::EVP_DigestSignFinal(self.0, buf.as_mut_ptr() as *mut _, &mut len)
|
||||
!= 1);
|
||||
// The advertised length is not always equal to the real length for things like DSA
|
||||
buf.truncate(len);
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
|
@ -213,6 +215,7 @@ mod test {
|
|||
use crypto::hash::Type;
|
||||
use crypto::sign::{Signer, Verifier};
|
||||
use crypto::rsa::RSA;
|
||||
use crypto::dsa::DSA;
|
||||
use crypto::pkey::PKey;
|
||||
|
||||
static INPUT: &'static [u8] =
|
||||
|
|
@ -240,7 +243,7 @@ mod test {
|
|||
112, 223, 200, 163, 42, 70, 149, 67, 208, 25, 238, 251, 71];
|
||||
|
||||
#[test]
|
||||
fn test_sign() {
|
||||
fn rsa_sign() {
|
||||
let key = include_bytes!("../../test/rsa.pem");
|
||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
|
@ -253,7 +256,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_ok() {
|
||||
fn rsa_verify_ok() {
|
||||
let key = include_bytes!("../../test/rsa.pem");
|
||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
|
@ -264,7 +267,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_invalid() {
|
||||
fn rsa_verify_invalid() {
|
||||
let key = include_bytes!("../../test/rsa.pem");
|
||||
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(private_key).unwrap();
|
||||
|
|
@ -275,6 +278,56 @@ mod test {
|
|||
assert!(!verifier.finish(SIGNATURE).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn dsa_sign_verify() {
|
||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||
|
||||
let private_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem");
|
||||
PKey::from_dsa(DSA::private_key_from_pem(key).unwrap()).unwrap()
|
||||
};
|
||||
|
||||
let public_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||
PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
|
||||
};
|
||||
|
||||
let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
|
||||
signer.update(&input).unwrap();
|
||||
let sig = signer.finish().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
|
||||
verifier.update(&input).unwrap();
|
||||
assert!(verifier.finish(&sig).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn dsa_sign_verify_fail() {
|
||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||
|
||||
let private_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem");
|
||||
PKey::from_dsa(DSA::private_key_from_pem(key).unwrap()).unwrap()
|
||||
};
|
||||
|
||||
let public_key = {
|
||||
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||
PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
|
||||
};
|
||||
|
||||
let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
|
||||
signer.update(&input).unwrap();
|
||||
let mut sig = signer.finish().unwrap();
|
||||
sig[0] -= 1;
|
||||
|
||||
let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
|
||||
verifier.update(&input).unwrap();
|
||||
match verifier.finish(&sig) {
|
||||
Ok(true) => panic!("unexpected success"),
|
||||
Ok(false) | Err(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
|
||||
for &(ref key, ref data, ref res) in tests.iter() {
|
||||
let pkey = PKey::hmac(key).unwrap();
|
||||
|
|
|
|||
Loading…
Reference in New Issue