/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.13/src/signature.rs
Line | Count | Source |
1 | | // Copyright 2015-2017 Brian Smith. |
2 | | // |
3 | | // Permission to use, copy, modify, and/or distribute this software for any |
4 | | // purpose with or without fee is hereby granted, provided that the above |
5 | | // copyright notice and this permission notice appear in all copies. |
6 | | // |
7 | | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
8 | | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
10 | | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | | |
15 | | //! Public key signatures: signing and verification. |
16 | | //! |
17 | | //! Use the `verify` function to verify signatures, passing a reference to the |
18 | | //! algorithm that identifies the algorithm. See the documentation for `verify` |
19 | | //! for examples. |
20 | | //! |
21 | | //! For signature verification, this API treats each combination of parameters |
22 | | //! as a separate algorithm. For example, instead of having a single "RSA" |
23 | | //! algorithm with a verification function that takes a bunch of parameters, |
24 | | //! there are `RSA_PKCS1_2048_8192_SHA256`, `RSA_PKCS1_2048_8192_SHA384`, etc., |
25 | | //! which encode sets of parameter choices into objects. This is designed to |
26 | | //! reduce the risks of algorithm agility and to provide consistency with ECDSA |
27 | | //! and EdDSA. |
28 | | //! |
29 | | //! Currently this module does not support digesting the message to be signed |
30 | | //! separately from the public key operation, as it is currently being |
31 | | //! optimized for Ed25519 and for the implementation of protocols that do not |
32 | | //! requiring signing large messages. An interface for efficiently supporting |
33 | | //! larger messages may be added later. |
34 | | //! |
35 | | //! |
36 | | //! # Algorithm Details |
37 | | //! |
38 | | //! ## `ECDSA_*_ASN1` Details: ASN.1-encoded ECDSA Signatures |
39 | | //! |
40 | | //! The signature is a ASN.1 DER-encoded `Ecdsa-Sig-Value` as described in |
41 | | //! [RFC 3279 Section 2.2.3]. This is the form of ECDSA signature used in |
42 | | //! X.509-related structures and in TLS's `ServerKeyExchange` messages. |
43 | | //! |
44 | | //! The public key is encoding in uncompressed form using the |
45 | | //! Octet-String-to-Elliptic-Curve-Point algorithm in |
46 | | //! [SEC 1: Elliptic Curve Cryptography, Version 2.0]. |
47 | | //! |
48 | | //! During verification, the public key is validated using the ECC Partial |
49 | | //! Public-Key Validation Routine from Section 5.6.2.3.3 of |
50 | | //! [NIST Special Publication 800-56A, revision 2] and Appendix A.3 of the |
51 | | //! NSA's [Suite B implementer's guide to FIPS 186-3]. Note that, as explained |
52 | | //! in the NSA guide, ECC Partial Public-Key Validation is equivalent to ECC |
53 | | //! Full Public-Key Validation for prime-order curves like this one. |
54 | | //! |
55 | | //! ## `ECDSA_*_FIXED` Details: Fixed-length (PKCS#11-style) ECDSA Signatures |
56 | | //! |
57 | | //! The signature is *r*||*s*, where || denotes concatenation, and where both |
58 | | //! *r* and *s* are both big-endian-encoded values that are left-padded to the |
59 | | //! maximum length. A P-256 signature will be 64 bytes long (two 32-byte |
60 | | //! components) and a P-384 signature will be 96 bytes long (two 48-byte |
61 | | //! components). This is the form of ECDSA signature used PKCS#11 and DNSSEC. |
62 | | //! |
63 | | //! The public key is encoding in uncompressed form using the |
64 | | //! Octet-String-to-Elliptic-Curve-Point algorithm in |
65 | | //! [SEC 1: Elliptic Curve Cryptography, Version 2.0]. |
66 | | //! |
67 | | //! During verification, the public key is validated using the ECC Partial |
68 | | //! Public-Key Validation Routine from Section 5.6.2.3.3 of |
69 | | //! [NIST Special Publication 800-56A, revision 2] and Appendix A.3 of the |
70 | | //! NSA's [Suite B implementer's guide to FIPS 186-3]. Note that, as explained |
71 | | //! in the NSA guide, ECC Partial Public-Key Validation is equivalent to ECC |
72 | | //! Full Public-Key Validation for prime-order curves like this one. |
73 | | //! |
74 | | //! ## `RSA_PKCS1_*` Details: RSA PKCS#1 1.5 Signatures |
75 | | //! |
76 | | //! The signature is an RSASSA-PKCS1-v1_5 signature as described in |
77 | | //! [RFC 3447 Section 8.2]. |
78 | | //! |
79 | | //! The public key is encoded as an ASN.1 `RSAPublicKey` as described in |
80 | | //! [RFC 3447 Appendix-A.1.1]. The public key modulus length, rounded *up* to |
81 | | //! the nearest (larger) multiple of 8 bits, must be in the range given in the |
82 | | //! name of the algorithm. The public exponent must be an odd integer of 2-33 |
83 | | //! bits, inclusive. |
84 | | //! |
85 | | //! |
86 | | //! ## `RSA_PSS_*` Details: RSA PSS Signatures |
87 | | //! |
88 | | //! The signature is an RSASSA-PSS signature as described in |
89 | | //! [RFC 3447 Section 8.1]. |
90 | | //! |
91 | | //! The public key is encoded as an ASN.1 `RSAPublicKey` as described in |
92 | | //! [RFC 3447 Appendix-A.1.1]. The public key modulus length, rounded *up* to |
93 | | //! the nearest (larger) multiple of 8 bits, must be in the range given in the |
94 | | //! name of the algorithm. The public exponent must be an odd integer of 2-33 |
95 | | //! bits, inclusive. |
96 | | //! |
97 | | //! During verification, signatures will only be accepted if the MGF1 digest |
98 | | //! algorithm is the same as the message digest algorithm and if the salt |
99 | | //! length is the same length as the message digest. This matches the |
100 | | //! requirements in TLS 1.3 and other recent specifications. |
101 | | //! |
102 | | //! During signing, the message digest algorithm will be used as the MGF1 |
103 | | //! digest algorithm. The salt will be the same length as the message digest. |
104 | | //! This matches the requirements in TLS 1.3 and other recent specifications. |
105 | | //! Additionally, the entire salt is randomly generated separately for each |
106 | | //! signature using the secure random number generator passed to `sign()`. |
107 | | //! |
108 | | //! |
109 | | //! [SEC 1: Elliptic Curve Cryptography, Version 2.0]: |
110 | | //! http://www.secg.org/sec1-v2.pdf |
111 | | //! [NIST Special Publication 800-56A, revision 2]: |
112 | | //! http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf |
113 | | //! [Suite B implementer's guide to FIPS 186-3]: |
114 | | //! https://github.com/briansmith/ring/blob/main/doc/ecdsa.pdf |
115 | | //! [RFC 3279 Section 2.2.3]: |
116 | | //! https://tools.ietf.org/html/rfc3279#section-2.2.3 |
117 | | //! [RFC 3447 Section 8.2]: |
118 | | //! https://tools.ietf.org/html/rfc3447#section-7.2 |
119 | | //! [RFC 3447 Section 8.1]: |
120 | | //! https://tools.ietf.org/html/rfc3447#section-8.1 |
121 | | //! [RFC 3447 Appendix-A.1.1]: |
122 | | //! https://tools.ietf.org/html/rfc3447#appendix-A.1.1 |
123 | | //! |
124 | | //! |
125 | | //! # Examples |
126 | | //! |
127 | | //! ## Signing and verifying with Ed25519 |
128 | | //! |
129 | | //! ``` |
130 | | //! use ring::{ |
131 | | //! rand, |
132 | | //! signature::{self, KeyPair}, |
133 | | //! }; |
134 | | //! |
135 | | //! # fn main() -> Result<(), ring::error::Unspecified> { |
136 | | //! // Generate a key pair in PKCS#8 (v2) format. |
137 | | //! let rng = rand::SystemRandom::new(); |
138 | | //! let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng)?; |
139 | | //! |
140 | | //! // Normally the application would store the PKCS#8 file persistently. Later |
141 | | //! // it would read the PKCS#8 file from persistent storage to use it. |
142 | | //! |
143 | | //! let key_pair = signature::Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref())?; |
144 | | //! |
145 | | //! // Sign the message "hello, world". |
146 | | //! const MESSAGE: &[u8] = b"hello, world"; |
147 | | //! let sig = key_pair.sign(MESSAGE); |
148 | | //! |
149 | | //! // Normally an application would extract the bytes of the signature and |
150 | | //! // send them in a protocol message to the peer(s). Here we just get the |
151 | | //! // public key key directly from the key pair. |
152 | | //! let peer_public_key_bytes = key_pair.public_key().as_ref(); |
153 | | //! |
154 | | //! // Verify the signature of the message using the public key. Normally the |
155 | | //! // verifier of the message would parse the inputs to this code out of the |
156 | | //! // protocol message(s) sent by the signer. |
157 | | //! let peer_public_key = |
158 | | //! signature::UnparsedPublicKey::new(&signature::ED25519, peer_public_key_bytes); |
159 | | //! peer_public_key.verify(MESSAGE, sig.as_ref())?; |
160 | | //! |
161 | | //! # Ok(()) |
162 | | //! # } |
163 | | //! ``` |
164 | | //! |
165 | | //! ## Signing and verifying with RSA (PKCS#1 1.5 padding) |
166 | | //! |
167 | | //! By default OpenSSL writes RSA public keys in SubjectPublicKeyInfo format, |
168 | | //! not RSAPublicKey format, and Base64-encodes them (“PEM” format). |
169 | | //! |
170 | | //! To convert the PEM SubjectPublicKeyInfo format (“BEGIN PUBLIC KEY”) to the |
171 | | //! binary RSAPublicKey format needed by `verify()`, use: |
172 | | //! |
173 | | //! ```sh |
174 | | //! openssl rsa -pubin \ |
175 | | //! -in public_key.pem \ |
176 | | //! -inform PEM \ |
177 | | //! -RSAPublicKey_out \ |
178 | | //! -outform DER \ |
179 | | //! -out public_key.der |
180 | | //! ``` |
181 | | //! |
182 | | //! To extract the RSAPublicKey-formatted public key from an ASN.1 (binary) |
183 | | //! DER-encoded RSAPrivateKey format private key file, use: |
184 | | //! |
185 | | //! ```sh |
186 | | //! openssl rsa -in private_key.der \ |
187 | | //! -inform DER \ |
188 | | //! -RSAPublicKey_out \ |
189 | | //! -outform DER \ |
190 | | //! -out public_key.der |
191 | | //! ``` |
192 | | //! |
193 | | //! ``` |
194 | | //! # #[cfg(feature = "std")] |
195 | | //! use ring::{rand, rsa, signature}; |
196 | | //! |
197 | | //! # #[cfg(feature = "std")] |
198 | | //! fn sign_and_verify_rsa(private_key_path: &std::path::Path, |
199 | | //! public_key_path: &std::path::Path) |
200 | | //! -> Result<(), MyError> { |
201 | | //! // Create an RSA keypair from the DER-encoded bytes. This example uses |
202 | | //! // a 2048-bit key, but larger keys are also supported. |
203 | | //! let private_key_der = read_file(private_key_path)?; |
204 | | //! let key_pair = rsa::KeyPair::from_der(&private_key_der) |
205 | | //! .map_err(|_| MyError::BadPrivateKey)?; |
206 | | //! |
207 | | //! // Sign the message "hello, world", using PKCS#1 v1.5 padding and the |
208 | | //! // SHA256 digest algorithm. |
209 | | //! const MESSAGE: &'static [u8] = b"hello, world"; |
210 | | //! let rng = rand::SystemRandom::new(); |
211 | | //! let mut signature = vec![0; key_pair.public().modulus_len()]; |
212 | | //! key_pair.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature) |
213 | | //! .map_err(|_| MyError::OOM)?; |
214 | | //! |
215 | | //! // Verify the signature. |
216 | | //! let public_key = |
217 | | //! signature::UnparsedPublicKey::new(&signature::RSA_PKCS1_2048_8192_SHA256, |
218 | | //! read_file(public_key_path)?); |
219 | | //! public_key.verify(MESSAGE, &signature) |
220 | | //! .map_err(|_| MyError::BadSignature) |
221 | | //! } |
222 | | //! |
223 | | //! #[derive(Debug)] |
224 | | //! enum MyError { |
225 | | //! # #[cfg(feature = "std")] |
226 | | //! IO(std::io::Error), |
227 | | //! BadPrivateKey, |
228 | | //! OOM, |
229 | | //! BadSignature, |
230 | | //! } |
231 | | //! |
232 | | //! # #[cfg(feature = "std")] |
233 | | //! fn read_file(path: &std::path::Path) -> Result<Vec<u8>, MyError> { |
234 | | //! use std::io::Read; |
235 | | //! |
236 | | //! let mut file = std::fs::File::open(path).map_err(|e| MyError::IO(e))?; |
237 | | //! let mut contents: Vec<u8> = Vec::new(); |
238 | | //! file.read_to_end(&mut contents).map_err(|e| MyError::IO(e))?; |
239 | | //! Ok(contents) |
240 | | //! } |
241 | | //! # |
242 | | //! # #[cfg(not(feature = "std"))] |
243 | | //! # fn sign_and_verify_rsa(_private_key_path: &std::path::Path, |
244 | | //! # _public_key_path: &std::path::Path) |
245 | | //! # -> Result<(), ()> { |
246 | | //! # Ok(()) |
247 | | //! # } |
248 | | //! # |
249 | | //! # fn main() { |
250 | | //! # let private_key_path = |
251 | | //! # std::path::Path::new("src/rsa/signature_rsa_example_private_key.der"); |
252 | | //! # let public_key_path = |
253 | | //! # std::path::Path::new("src/rsa/signature_rsa_example_public_key.der"); |
254 | | //! # sign_and_verify_rsa(&private_key_path, &public_key_path).unwrap() |
255 | | //! # } |
256 | | //! ``` |
257 | | |
258 | | use crate::{cpu, debug, ec, error, sealed}; |
259 | | |
260 | | pub use crate::ec::{ |
261 | | curve25519::ed25519::{ |
262 | | signing::Ed25519KeyPair, |
263 | | verification::{EdDSAParameters, ED25519}, |
264 | | ED25519_PUBLIC_KEY_LEN, |
265 | | }, |
266 | | suite_b::ecdsa::{ |
267 | | signing::{ |
268 | | EcdsaKeyPair, EcdsaSigningAlgorithm, ECDSA_P256_SHA256_ASN1_SIGNING, |
269 | | ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_ASN1_SIGNING, |
270 | | ECDSA_P384_SHA384_FIXED_SIGNING, |
271 | | }, |
272 | | verification::{ |
273 | | EcdsaVerificationAlgorithm, ECDSA_P256_SHA256_ASN1, ECDSA_P256_SHA256_FIXED, |
274 | | ECDSA_P256_SHA384_ASN1, ECDSA_P384_SHA256_ASN1, ECDSA_P384_SHA384_ASN1, |
275 | | ECDSA_P384_SHA384_FIXED, |
276 | | }, |
277 | | }, |
278 | | }; |
279 | | |
280 | | #[cfg(feature = "alloc")] |
281 | | pub use crate::rsa::{ |
282 | | padding::{ |
283 | | RsaEncoding, RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, |
284 | | RSA_PSS_SHA384, RSA_PSS_SHA512, |
285 | | }, |
286 | | verification::{ |
287 | | RsaPublicKeyComponents, RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY, |
288 | | RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY, |
289 | | RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY, |
290 | | RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY, RSA_PKCS1_2048_8192_SHA256, |
291 | | RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512, RSA_PKCS1_3072_8192_SHA384, |
292 | | RSA_PSS_2048_8192_SHA256, RSA_PSS_2048_8192_SHA384, RSA_PSS_2048_8192_SHA512, |
293 | | }, |
294 | | RsaParameters, |
295 | | }; |
296 | | |
297 | | /// An RSA key pair, used for signing. |
298 | | #[cfg(feature = "alloc")] |
299 | | pub type RsaKeyPair = crate::rsa::KeyPair; |
300 | | |
301 | | /// A public key signature returned from a signing operation. |
302 | | #[derive(Clone, Copy)] |
303 | | pub struct Signature { |
304 | | value: [u8; MAX_LEN], |
305 | | len: usize, |
306 | | } |
307 | | |
308 | | impl Signature { |
309 | | // Panics if `value` is too long. |
310 | 0 | pub(crate) fn new<F>(fill: F) -> Self |
311 | 0 | where |
312 | 0 | F: FnOnce(&mut [u8; MAX_LEN]) -> usize, |
313 | | { |
314 | 0 | let mut r = Self { |
315 | 0 | value: [0; MAX_LEN], |
316 | 0 | len: 0, |
317 | 0 | }; |
318 | 0 | r.len = fill(&mut r.value); |
319 | 0 | r |
320 | 0 | } Unexecuted instantiation: <ring::signature::Signature>::new::<<ring::ec::curve25519::ed25519::signing::Ed25519KeyPair>::sign::{closure#0}>Unexecuted instantiation: <ring::signature::Signature>::new::<<ring::ec::suite_b::ecdsa::signing::EcdsaKeyPair>::sign_digest::{closure#0}> |
321 | | } |
322 | | |
323 | | impl AsRef<[u8]> for Signature { |
324 | 0 | fn as_ref(&self) -> &[u8] { |
325 | 0 | &self.value[..self.len] |
326 | 0 | } |
327 | | } |
328 | | |
329 | | /// Key pairs for signing messages (private key and public key). |
330 | | pub trait KeyPair: core::fmt::Debug + Send + Sized + Sync { |
331 | | /// The type of the public key. |
332 | | type PublicKey: AsRef<[u8]> + core::fmt::Debug + Clone + Send + Sized + Sync; |
333 | | |
334 | | /// The public key for the key pair. |
335 | | fn public_key(&self) -> &Self::PublicKey; |
336 | | } |
337 | | |
338 | | /// The longest signature is an ASN.1 P-384 signature where *r* and *s* are of |
339 | | /// maximum length with the leading high bit set on each. Then each component |
340 | | /// will have a tag, a one-byte length, and a one-byte “I'm not negative” |
341 | | /// prefix, and the outer sequence will have a two-byte length. |
342 | | pub(crate) const MAX_LEN: usize = 1/*tag:SEQUENCE*/ + 2/*len*/ + |
343 | | (2 * (1/*tag:INTEGER*/ + 1/*len*/ + 1/*zero*/ + ec::SCALAR_MAX_BYTES)); |
344 | | |
345 | | /// A signature verification algorithm. |
346 | | pub trait VerificationAlgorithm: core::fmt::Debug + Sync + sealed::Sealed { |
347 | | /// Verify the signature `signature` of message `msg` with the public key |
348 | | /// `public_key`. |
349 | | fn verify( |
350 | | &self, |
351 | | public_key: untrusted::Input, |
352 | | msg: untrusted::Input, |
353 | | signature: untrusted::Input, |
354 | | ) -> Result<(), error::Unspecified>; |
355 | | } |
356 | | |
357 | | /// An unparsed, possibly malformed, public key for signature verification. |
358 | | #[derive(Clone, Copy)] |
359 | | pub struct UnparsedPublicKey<B> { |
360 | | algorithm: &'static dyn VerificationAlgorithm, |
361 | | bytes: B, |
362 | | } |
363 | | |
364 | | impl<B> AsRef<[u8]> for UnparsedPublicKey<B> |
365 | | where |
366 | | B: AsRef<[u8]>, |
367 | | { |
368 | 0 | fn as_ref(&self) -> &[u8] { |
369 | 0 | self.bytes.as_ref() |
370 | 0 | } |
371 | | } |
372 | | |
373 | | impl<B: core::fmt::Debug> core::fmt::Debug for UnparsedPublicKey<B> |
374 | | where |
375 | | B: AsRef<[u8]>, |
376 | | { |
377 | 0 | fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { |
378 | 0 | f.debug_struct("UnparsedPublicKey") |
379 | 0 | .field("algorithm", &self.algorithm) |
380 | 0 | .field("bytes", &debug::HexStr(self.bytes.as_ref())) |
381 | 0 | .finish() |
382 | 0 | } |
383 | | } |
384 | | |
385 | | impl<B> UnparsedPublicKey<B> { |
386 | | /// Construct a new `UnparsedPublicKey`. |
387 | | /// |
388 | | /// No validation of `bytes` is done until `verify()` is called. |
389 | | #[inline] |
390 | 0 | pub fn new(algorithm: &'static dyn VerificationAlgorithm, bytes: B) -> Self { |
391 | 0 | Self { algorithm, bytes } |
392 | 0 | } |
393 | | |
394 | | /// Parses the public key and verifies `signature` is a valid signature of |
395 | | /// `message` using it. |
396 | | /// |
397 | | /// See the [crate::signature] module-level documentation for examples. |
398 | 0 | pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), error::Unspecified> |
399 | 0 | where |
400 | 0 | B: AsRef<[u8]>, |
401 | | { |
402 | 0 | let _ = cpu::features(); |
403 | 0 | self.algorithm.verify( |
404 | 0 | untrusted::Input::from(self.bytes.as_ref()), |
405 | 0 | untrusted::Input::from(message), |
406 | 0 | untrusted::Input::from(signature), |
407 | | ) |
408 | 0 | } |
409 | | } |