Merge pull request #862 from bkchr/sign_verifier
Adds new functions for Verifier/Signer
This commit is contained in:
commit
eb5fda588f
|
|
@ -228,9 +228,24 @@ pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey;
|
|||
pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000;
|
||||
|
||||
pub const EVP_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1;
|
||||
pub const EVP_PKEY_CTRL_RSA_PSS_SALTLEN: c_int = EVP_PKEY_ALG_CTRL + 2;
|
||||
|
||||
pub const EVP_PKEY_CTRL_RSA_MGF1_MD: c_int = EVP_PKEY_ALG_CTRL + 5;
|
||||
pub const EVP_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6;
|
||||
|
||||
pub const EVP_PKEY_OP_SIGN: c_int = 1 << 3;
|
||||
pub const EVP_PKEY_OP_VERIFY: c_int = 1 << 4;
|
||||
pub const EVP_PKEY_OP_VERIFYRECOVER: c_int = 1 << 5;
|
||||
pub const EVP_PKEY_OP_SIGNCTX: c_int = 1 << 6;
|
||||
pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7;
|
||||
pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8;
|
||||
pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9;
|
||||
|
||||
pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY
|
||||
| EVP_PKEY_OP_VERIFYRECOVER | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX;
|
||||
|
||||
pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT;
|
||||
|
||||
pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9;
|
||||
pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10;
|
||||
pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11;
|
||||
|
|
@ -1200,6 +1215,7 @@ pub const RSA_SSLV23_PADDING: c_int = 2;
|
|||
pub const RSA_NO_PADDING: c_int = 3;
|
||||
pub const RSA_PKCS1_OAEP_PADDING: c_int = 4;
|
||||
pub const RSA_X931_PADDING: c_int = 5;
|
||||
pub const RSA_PKCS1_PSS_PADDING: c_int = 6;
|
||||
|
||||
pub const SHA_LBLOCK: c_int = 16;
|
||||
|
||||
|
|
@ -1477,6 +1493,28 @@ pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_
|
|||
)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx: *mut EVP_PKEY_CTX, len: c_int) -> c_int {
|
||||
EVP_PKEY_CTX_ctrl(
|
||||
ctx,
|
||||
EVP_PKEY_RSA,
|
||||
EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY,
|
||||
EVP_PKEY_CTRL_RSA_PSS_SALTLEN,
|
||||
len,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_CTX_set_rsa_mgf1_md(ctx: *mut EVP_PKEY_CTX, md: *mut EVP_MD) -> c_int {
|
||||
EVP_PKEY_CTX_ctrl(
|
||||
ctx,
|
||||
EVP_PKEY_RSA,
|
||||
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
|
||||
EVP_PKEY_CTRL_RSA_MGF1_MD,
|
||||
0,
|
||||
md as *mut c_void,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long {
|
||||
SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut())
|
||||
}
|
||||
|
|
@ -2023,6 +2061,7 @@ extern "C" {
|
|||
pub fn EVP_PKEY_get1_DH(k: *mut EVP_PKEY) -> *mut DH;
|
||||
pub fn EVP_PKEY_get1_EC_KEY(k: *mut EVP_PKEY) -> *mut EC_KEY;
|
||||
pub fn EVP_PKEY_cmp(a: *const EVP_PKEY, b: *const EVP_PKEY) -> c_int;
|
||||
pub fn EVP_PKEY_id(pkey: *const EVP_PKEY) -> c_int;
|
||||
pub fn EVP_PKEY_new_mac_key(
|
||||
type_: c_int,
|
||||
e: *mut ENGINE,
|
||||
|
|
|
|||
|
|
@ -70,6 +70,28 @@ pub enum Public {}
|
|||
/// A tag type indicating that a key has private components.
|
||||
pub enum Private {}
|
||||
|
||||
/// The Oids that identify the type of a key.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Oid(c_int);
|
||||
|
||||
impl Oid {
|
||||
/// Creates a `Oid` from an integer representation.
|
||||
pub fn from_raw(value: c_int) -> Oid {
|
||||
Oid(value)
|
||||
}
|
||||
|
||||
/// Returns the integer representation of `Oid`.
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const RSA: Oid = Oid(ffi::EVP_PKEY_RSA);
|
||||
pub const HMAC: Oid = Oid(ffi::EVP_PKEY_HMAC);
|
||||
pub const DSA: Oid = Oid(ffi::EVP_PKEY_DSA);
|
||||
pub const DH: Oid = Oid(ffi::EVP_PKEY_DH);
|
||||
pub const EC: Oid = Oid(ffi::EVP_PKEY_EC);
|
||||
}
|
||||
|
||||
/// A trait indicating that a key has parameters.
|
||||
pub unsafe trait HasParams {}
|
||||
|
||||
|
|
@ -155,6 +177,17 @@ impl<T> PKeyRef<T> {
|
|||
Ok(EcKey::from_ptr(ec_key))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the Oid that represents the type of this key.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_id`].
|
||||
///
|
||||
/// [`EVP_PKEY_id`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_id.html
|
||||
pub fn oid(&self) -> Oid {
|
||||
unsafe {
|
||||
Oid::from_raw(ffi::EVP_PKEY_id(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PKeyRef<T>
|
||||
|
|
@ -531,6 +564,7 @@ mod tests {
|
|||
let rsa = Rsa::generate(2048).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
pkey.rsa().unwrap();
|
||||
assert_eq!(pkey.oid(), Oid::RSA);
|
||||
assert!(pkey.dsa().is_err());
|
||||
}
|
||||
|
||||
|
|
@ -539,6 +573,7 @@ mod tests {
|
|||
let dsa = Dsa::generate(2048).unwrap();
|
||||
let pkey = PKey::from_dsa(dsa).unwrap();
|
||||
pkey.dsa().unwrap();
|
||||
assert_eq!(pkey.oid(), Oid::DSA);
|
||||
assert!(pkey.rsa().is_err());
|
||||
}
|
||||
|
||||
|
|
@ -548,6 +583,7 @@ mod tests {
|
|||
let dh = Dh::params_from_pem(dh).unwrap();
|
||||
let pkey = PKey::from_dh(dh).unwrap();
|
||||
pkey.dh().unwrap();
|
||||
assert_eq!(pkey.oid(), Oid::DH);
|
||||
assert!(pkey.rsa().is_err());
|
||||
}
|
||||
|
||||
|
|
@ -556,6 +592,7 @@ mod tests {
|
|||
let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
pkey.ec_key().unwrap();
|
||||
assert_eq!(pkey.oid(), Oid::EC);
|
||||
assert!(pkey.rsa().is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ impl Padding {
|
|||
pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
|
||||
pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
|
||||
pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
|
||||
pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ use foreign_types::ForeignTypeRef;
|
|||
use std::io::{self, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use libc::c_int;
|
||||
|
||||
use {cvt, cvt_p};
|
||||
use hash::MessageDigest;
|
||||
|
|
@ -78,6 +79,28 @@ use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
|||
#[cfg(any(ossl101, ossl102))]
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
|
||||
/// Salt lengths that must be used with `set_rsa_pss_saltlen`.
|
||||
pub struct RsaPssSaltlen(c_int);
|
||||
|
||||
impl RsaPssSaltlen {
|
||||
/// Returns the integer representation of `RsaPssSaltlen`.
|
||||
fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Sets the salt length to the given value.
|
||||
pub fn custom(val: c_int) -> RsaPssSaltlen {
|
||||
RsaPssSaltlen(val)
|
||||
}
|
||||
|
||||
/// The salt length is set to the digest length.
|
||||
/// Corresponds to the special value `-1`.
|
||||
pub const DIGEST_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-1);
|
||||
/// The salt length is set to the maximum permissible value.
|
||||
/// Corresponds to the special value `-2`.
|
||||
pub const MAXIMUM_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-2);
|
||||
}
|
||||
|
||||
/// A type which computes cryptographic signatures of data.
|
||||
pub struct Signer<'a> {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
|
|
@ -163,6 +186,38 @@ impl<'a> Signer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Signer`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestUpdate`].
|
||||
|
|
@ -326,6 +381,38 @@ impl<'a> Verifier<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_pss_saltlen`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_pss_saltlen`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_pss_saltlen.html
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Verifier`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_DigestUpdate`].
|
||||
|
|
@ -392,7 +479,7 @@ mod test {
|
|||
use std::iter;
|
||||
|
||||
use hash::MessageDigest;
|
||||
use sign::{Signer, Verifier};
|
||||
use sign::{Signer, Verifier, RsaPssSaltlen};
|
||||
use ec::{EcGroup, EcKey};
|
||||
use nid::Nid;
|
||||
use rsa::{Padding, Rsa};
|
||||
|
|
@ -565,4 +652,26 @@ mod test {
|
|||
verifier.update(b"hello world").unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rsa_sign_verify() {
|
||||
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();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1_PSS);
|
||||
signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH).unwrap();
|
||||
signer.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH).unwrap();
|
||||
verifier.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue