Loading openssl-sys/src/evp.rs +16 −0 Original line number Diff line number Diff line Loading @@ -649,6 +649,22 @@ extern "C" { pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; pub fn EVP_PKEY_sign_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_sign( ctx: *mut EVP_PKEY_CTX, sig: *mut c_uchar, siglen: *mut size_t, tbs: *const c_uchar, tbslen: size_t, ) -> c_int; pub fn EVP_PKEY_verify_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_verify( ctx: *mut EVP_PKEY_CTX, sig: *const c_uchar, siglen: size_t, tbs: *const c_uchar, tbslen: size_t, ) -> c_int; pub fn EVP_PKEY_encrypt_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_encrypt( ctx: *mut EVP_PKEY_CTX, Loading openssl/src/md_ctx.rs +32 −2 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPrivate, PKeyRef}; use crate::pkey_ctx::PkeyCtxRef; use crate::{cvt, cvt_p}; use crate::{cvt, cvt_n, cvt_p}; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; use openssl_macros::corresponds; Loading Loading @@ -303,7 +303,7 @@ impl MdCtxRef { #[inline] pub fn digest_verify_final(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> { unsafe { let r = cvt(ffi::EVP_DigestVerifyFinal( let r = cvt_n(ffi::EVP_DigestVerifyFinal( self.as_ptr(), signature.as_ptr() as *mut _, signature.len(), Loading Loading @@ -374,3 +374,33 @@ impl MdCtxRef { } } } #[cfg(test)] mod test { use super::*; use crate::md::Md; use crate::pkey::PKey; use crate::rsa::Rsa; #[test] fn verify_fail() { let key1 = Rsa::generate(4096).unwrap(); let key1 = PKey::from_rsa(key1).unwrap(); let md = Md::sha256(); let data = b"Some Crypto Text"; let mut ctx = MdCtx::new().unwrap(); ctx.digest_sign_init(Some(md), &key1).unwrap(); ctx.digest_sign_update(data).unwrap(); let mut signature = vec![]; ctx.digest_sign_final_to_vec(&mut signature).unwrap(); let bad_data = b"Some Crypto text"; ctx.digest_verify_init(Some(md), &key1).unwrap(); ctx.digest_verify_update(bad_data).unwrap(); let valid = ctx.digest_verify_final(&signature).unwrap(); assert!(!valid); } } openssl/src/pkey_ctx.rs +129 −1 Original line number Diff line number Diff line Loading @@ -33,12 +33,38 @@ //! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); //! let cmac_key = ctx.keygen().unwrap(); //! ``` //! //! Sign and verify data with RSA //! //! ``` //! use openssl::pkey_ctx::PkeyCtx; //! use openssl::pkey::PKey; //! use openssl::rsa::Rsa; //! //! // Generate a random RSA key. //! let key = Rsa::generate(4096).unwrap(); //! let key = PKey::from_rsa(key).unwrap(); //! //! let text = b"Some Crypto Text"; //! //! // Create the signature. //! let mut ctx = PkeyCtx::new(&key).unwrap(); //! ctx.sign_init().unwrap(); //! let mut signature = vec![]; //! ctx.sign_to_vec(text, &mut signature).unwrap(); //! //! // Verify the signature. //! let mut ctx = PkeyCtx::new(&key).unwrap(); //! ctx.verify_init().unwrap(); //! let valid = ctx.verify(text, &signature).unwrap(); //! assert!(valid); //! ``` use crate::cipher::CipherRef; use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; use crate::rsa::Padding; use crate::{cvt, cvt_p}; use crate::{cvt, cvt_n, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use openssl_macros::corresponds; Loading Loading @@ -105,6 +131,17 @@ where Ok(()) } /// Prepares the context for signature verification using the public key. #[corresponds(EVP_PKEY_verify_init)] #[inline] pub fn verify_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?; } Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be Loading Loading @@ -135,6 +172,31 @@ where out.truncate(base + len); Ok(len) } /// Verifies the signature of data using the public key. /// /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error /// occurred. /// /// # Note /// /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do /// that. #[corresponds(EVP_PKEY_verify)] #[inline] pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> { unsafe { let r = cvt_n(ffi::EVP_PKEY_verify( self.as_ptr(), sig.as_ptr(), sig.len(), data.as_ptr(), data.len(), ))?; Ok(r == 1) } } } impl<T> PkeyCtxRef<T> Loading @@ -152,6 +214,17 @@ where Ok(()) } /// Prepares the context for signing using the private key. #[corresponds(EVP_PKEY_sign_init)] #[inline] pub fn sign_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?; } Ok(()) } /// Sets the peer key used for secret derivation. #[corresponds(EVP_PKEY_derive_set_peer)] pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> Loading Loading @@ -195,6 +268,42 @@ where out.truncate(base + len); Ok(len) } /// Signs the contents of `data`. /// /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffere will be /// returned. /// /// # Note /// /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that. #[corresponds(EVP_PKEY_sign)] #[inline] pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = sig.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_sign( self.as_ptr(), sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, data.as_ptr(), data.len(), ))?; } Ok(written) } /// Like [`Self::sign`] but appends the signature to a [`Vec`]. pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = sig.len(); let len = self.sign(data, None)?; sig.resize(base + len, 0); let len = self.sign(data, Some(&mut sig[base..]))?; sig.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> { Loading Loading @@ -629,4 +738,23 @@ mod test { .unwrap() ); } #[test] fn verify_fail() { let key1 = Rsa::generate(4096).unwrap(); let key1 = PKey::from_rsa(key1).unwrap(); let data = b"Some Crypto Text"; let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); let mut signature = vec![]; ctx.sign_to_vec(data, &mut signature).unwrap(); let bad_data = b"Some Crypto text"; ctx.verify_init().unwrap(); let valid = ctx.verify(bad_data, &signature).unwrap(); assert!(!valid); } } Loading
openssl-sys/src/evp.rs +16 −0 Original line number Diff line number Diff line Loading @@ -649,6 +649,22 @@ extern "C" { pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; pub fn EVP_PKEY_sign_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_sign( ctx: *mut EVP_PKEY_CTX, sig: *mut c_uchar, siglen: *mut size_t, tbs: *const c_uchar, tbslen: size_t, ) -> c_int; pub fn EVP_PKEY_verify_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_verify( ctx: *mut EVP_PKEY_CTX, sig: *const c_uchar, siglen: size_t, tbs: *const c_uchar, tbslen: size_t, ) -> c_int; pub fn EVP_PKEY_encrypt_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_encrypt( ctx: *mut EVP_PKEY_CTX, Loading
openssl/src/md_ctx.rs +32 −2 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPrivate, PKeyRef}; use crate::pkey_ctx::PkeyCtxRef; use crate::{cvt, cvt_p}; use crate::{cvt, cvt_n, cvt_p}; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; use openssl_macros::corresponds; Loading Loading @@ -303,7 +303,7 @@ impl MdCtxRef { #[inline] pub fn digest_verify_final(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> { unsafe { let r = cvt(ffi::EVP_DigestVerifyFinal( let r = cvt_n(ffi::EVP_DigestVerifyFinal( self.as_ptr(), signature.as_ptr() as *mut _, signature.len(), Loading Loading @@ -374,3 +374,33 @@ impl MdCtxRef { } } } #[cfg(test)] mod test { use super::*; use crate::md::Md; use crate::pkey::PKey; use crate::rsa::Rsa; #[test] fn verify_fail() { let key1 = Rsa::generate(4096).unwrap(); let key1 = PKey::from_rsa(key1).unwrap(); let md = Md::sha256(); let data = b"Some Crypto Text"; let mut ctx = MdCtx::new().unwrap(); ctx.digest_sign_init(Some(md), &key1).unwrap(); ctx.digest_sign_update(data).unwrap(); let mut signature = vec![]; ctx.digest_sign_final_to_vec(&mut signature).unwrap(); let bad_data = b"Some Crypto text"; ctx.digest_verify_init(Some(md), &key1).unwrap(); ctx.digest_verify_update(bad_data).unwrap(); let valid = ctx.digest_verify_final(&signature).unwrap(); assert!(!valid); } }
openssl/src/pkey_ctx.rs +129 −1 Original line number Diff line number Diff line Loading @@ -33,12 +33,38 @@ //! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); //! let cmac_key = ctx.keygen().unwrap(); //! ``` //! //! Sign and verify data with RSA //! //! ``` //! use openssl::pkey_ctx::PkeyCtx; //! use openssl::pkey::PKey; //! use openssl::rsa::Rsa; //! //! // Generate a random RSA key. //! let key = Rsa::generate(4096).unwrap(); //! let key = PKey::from_rsa(key).unwrap(); //! //! let text = b"Some Crypto Text"; //! //! // Create the signature. //! let mut ctx = PkeyCtx::new(&key).unwrap(); //! ctx.sign_init().unwrap(); //! let mut signature = vec![]; //! ctx.sign_to_vec(text, &mut signature).unwrap(); //! //! // Verify the signature. //! let mut ctx = PkeyCtx::new(&key).unwrap(); //! ctx.verify_init().unwrap(); //! let valid = ctx.verify(text, &signature).unwrap(); //! assert!(valid); //! ``` use crate::cipher::CipherRef; use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; use crate::rsa::Padding; use crate::{cvt, cvt_p}; use crate::{cvt, cvt_n, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use openssl_macros::corresponds; Loading Loading @@ -105,6 +131,17 @@ where Ok(()) } /// Prepares the context for signature verification using the public key. #[corresponds(EVP_PKEY_verify_init)] #[inline] pub fn verify_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?; } Ok(()) } /// Encrypts data using the public key. /// /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be Loading Loading @@ -135,6 +172,31 @@ where out.truncate(base + len); Ok(len) } /// Verifies the signature of data using the public key. /// /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error /// occurred. /// /// # Note /// /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do /// that. #[corresponds(EVP_PKEY_verify)] #[inline] pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> { unsafe { let r = cvt_n(ffi::EVP_PKEY_verify( self.as_ptr(), sig.as_ptr(), sig.len(), data.as_ptr(), data.len(), ))?; Ok(r == 1) } } } impl<T> PkeyCtxRef<T> Loading @@ -152,6 +214,17 @@ where Ok(()) } /// Prepares the context for signing using the private key. #[corresponds(EVP_PKEY_sign_init)] #[inline] pub fn sign_init(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?; } Ok(()) } /// Sets the peer key used for secret derivation. #[corresponds(EVP_PKEY_derive_set_peer)] pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> Loading Loading @@ -195,6 +268,42 @@ where out.truncate(base + len); Ok(len) } /// Signs the contents of `data`. /// /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffere will be /// returned. /// /// # Note /// /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that. #[corresponds(EVP_PKEY_sign)] #[inline] pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let mut written = sig.as_ref().map_or(0, |b| b.len()); unsafe { cvt(ffi::EVP_PKEY_sign( self.as_ptr(), sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut written, data.as_ptr(), data.len(), ))?; } Ok(written) } /// Like [`Self::sign`] but appends the signature to a [`Vec`]. pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> { let base = sig.len(); let len = self.sign(data, None)?; sig.resize(base + len, 0); let len = self.sign(data, Some(&mut sig[base..]))?; sig.truncate(base + len); Ok(len) } } impl<T> PkeyCtxRef<T> { Loading Loading @@ -629,4 +738,23 @@ mod test { .unwrap() ); } #[test] fn verify_fail() { let key1 = Rsa::generate(4096).unwrap(); let key1 = PKey::from_rsa(key1).unwrap(); let data = b"Some Crypto Text"; let mut ctx = PkeyCtx::new(&key1).unwrap(); ctx.sign_init().unwrap(); let mut signature = vec![]; ctx.sign_to_vec(data, &mut signature).unwrap(); let bad_data = b"Some Crypto text"; ctx.verify_init().unwrap(); let valid = ctx.verify(bad_data, &signature).unwrap(); assert!(!valid); } }