3333//! ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
3434//! let cmac_key = ctx.keygen().unwrap();
3535//! ```
36+ //!
37+ //! Sign and verify data with RSA
38+ //!
39+ //! ```
40+ //! use openssl::pkey_ctx::PkeyCtx;
41+ //! use openssl::pkey::PKey;
42+ //! use openssl::rsa::Rsa;
43+ //!
44+ //! // Generate a random RSA key.
45+ //! let key = Rsa::generate(4096).unwrap();
46+ //! let key = PKey::from_rsa(key).unwrap();
47+ //!
48+ //! let text = b"Some Crypto Text";
49+ //!
50+ //! // Create the signature.
51+ //! let mut ctx = PkeyCtx::new(&key).unwrap();
52+ //! ctx.sign_init().unwrap();
53+ //! let mut signature = vec![];
54+ //! ctx.sign_to_vec(text, &mut signature).unwrap();
55+ //!
56+ //! // Verify the signature.
57+ //! let mut ctx = PkeyCtx::new(&key).unwrap();
58+ //! ctx.verify_init().unwrap();
59+ //! let valid = ctx.verify(text, &signature).unwrap();
60+ //! assert!(valid);
61+ //! ```
3662use crate :: cipher:: CipherRef ;
3763use crate :: error:: ErrorStack ;
3864use crate :: md:: MdRef ;
3965use crate :: pkey:: { HasPrivate , HasPublic , Id , PKey , PKeyRef , Private } ;
4066use crate :: rsa:: Padding ;
41- use crate :: { cvt, cvt_p} ;
67+ use crate :: { cvt, cvt_n , cvt_p} ;
4268use foreign_types:: { ForeignType , ForeignTypeRef } ;
4369use libc:: c_int;
4470use openssl_macros:: corresponds;
@@ -105,6 +131,17 @@ where
105131 Ok ( ( ) )
106132 }
107133
134+ /// Prepares the context for signature verification using the public key.
135+ #[ corresponds( EVP_PKEY_verify_init ) ]
136+ #[ inline]
137+ pub fn verify_init ( & mut self ) -> Result < ( ) , ErrorStack > {
138+ unsafe {
139+ cvt ( ffi:: EVP_PKEY_verify_init ( self . as_ptr ( ) ) ) ?;
140+ }
141+
142+ Ok ( ( ) )
143+ }
144+
108145 /// Encrypts data using the public key.
109146 ///
110147 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
@@ -135,6 +172,31 @@ where
135172 out. truncate ( base + len) ;
136173 Ok ( len)
137174 }
175+
176+ /// Verifies the signature of data using the public key.
177+ ///
178+ /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
179+ /// occurred.
180+ ///
181+ /// # Note
182+ ///
183+ /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the
184+ /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do
185+ /// that.
186+ #[ corresponds( EVP_PKEY_verify ) ]
187+ #[ inline]
188+ pub fn verify ( & mut self , data : & [ u8 ] , sig : & [ u8 ] ) -> Result < bool , ErrorStack > {
189+ unsafe {
190+ let r = cvt_n ( ffi:: EVP_PKEY_verify (
191+ self . as_ptr ( ) ,
192+ sig. as_ptr ( ) ,
193+ sig. len ( ) ,
194+ data. as_ptr ( ) ,
195+ data. len ( ) ,
196+ ) ) ?;
197+ Ok ( r == 1 )
198+ }
199+ }
138200}
139201
140202impl < T > PkeyCtxRef < T >
@@ -152,6 +214,17 @@ where
152214 Ok ( ( ) )
153215 }
154216
217+ /// Prepares the context for signing using the private key.
218+ #[ corresponds( EVP_PKEY_sign_init ) ]
219+ #[ inline]
220+ pub fn sign_init ( & mut self ) -> Result < ( ) , ErrorStack > {
221+ unsafe {
222+ cvt ( ffi:: EVP_PKEY_sign_init ( self . as_ptr ( ) ) ) ?;
223+ }
224+
225+ Ok ( ( ) )
226+ }
227+
155228 /// Sets the peer key used for secret derivation.
156229 #[ corresponds( EVP_PKEY_derive_set_peer ) ]
157230 pub fn derive_set_peer < U > ( & mut self , key : & PKeyRef < U > ) -> Result < ( ) , ErrorStack >
@@ -195,6 +268,42 @@ where
195268 out. truncate ( base + len) ;
196269 Ok ( len)
197270 }
271+
272+ /// Signs the contents of `data`.
273+ ///
274+ /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffere will be
275+ /// returned.
276+ ///
277+ /// # Note
278+ ///
279+ /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of
280+ /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that.
281+ #[ corresponds( EVP_PKEY_sign ) ]
282+ #[ inline]
283+ pub fn sign ( & mut self , data : & [ u8 ] , sig : Option < & mut [ u8 ] > ) -> Result < usize , ErrorStack > {
284+ let mut written = sig. as_ref ( ) . map_or ( 0 , |b| b. len ( ) ) ;
285+ unsafe {
286+ cvt ( ffi:: EVP_PKEY_sign (
287+ self . as_ptr ( ) ,
288+ sig. map_or ( ptr:: null_mut ( ) , |b| b. as_mut_ptr ( ) ) ,
289+ & mut written,
290+ data. as_ptr ( ) ,
291+ data. len ( ) ,
292+ ) ) ?;
293+ }
294+
295+ Ok ( written)
296+ }
297+
298+ /// Like [`Self::sign`] but appends the signature to a [`Vec`].
299+ pub fn sign_to_vec ( & mut self , data : & [ u8 ] , sig : & mut Vec < u8 > ) -> Result < usize , ErrorStack > {
300+ let base = sig. len ( ) ;
301+ let len = self . sign ( data, None ) ?;
302+ sig. resize ( base + len, 0 ) ;
303+ let len = self . sign ( data, Some ( & mut sig[ base..] ) ) ?;
304+ sig. truncate ( base + len) ;
305+ Ok ( len)
306+ }
198307}
199308
200309impl < T > PkeyCtxRef < T > {
@@ -629,4 +738,23 @@ mod test {
629738 . unwrap( )
630739 ) ;
631740 }
741+
742+ #[ test]
743+ fn verify_fail ( ) {
744+ let key1 = Rsa :: generate ( 4096 ) . unwrap ( ) ;
745+ let key1 = PKey :: from_rsa ( key1) . unwrap ( ) ;
746+
747+ let data = b"Some Crypto Text" ;
748+
749+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
750+ ctx. sign_init ( ) . unwrap ( ) ;
751+ let mut signature = vec ! [ ] ;
752+ ctx. sign_to_vec ( data, & mut signature) . unwrap ( ) ;
753+
754+ let bad_data = b"Some Crypto text" ;
755+
756+ ctx. verify_init ( ) . unwrap ( ) ;
757+ let valid = ctx. verify ( bad_data, & signature) . unwrap ( ) ;
758+ assert ! ( !valid) ;
759+ }
632760}
0 commit comments