Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}