Refactor low-level RSA signature verification API.
Replace `(n, e)` tuple with a structure with named `n` and `e` fields to improve safety. Remove the use of `untrusted`.
This commit is contained in:
parent
d56ca70fd0
commit
9f211157a8
@ -175,7 +175,7 @@ rsa_params!(
|
||||
`ring::signature`'s module-level documentation for more details."
|
||||
);
|
||||
|
||||
/// Lower-level API for the verification of RSA signatures.
|
||||
/// Low-level API for the verification of RSA signatures.
|
||||
///
|
||||
/// When the public key is in DER-encoded PKCS#1 ASN.1 format, it is
|
||||
/// recommended to use `ring::signature::verify()` with
|
||||
@ -183,16 +183,8 @@ rsa_params!(
|
||||
/// will handle the parsing in that case. Otherwise, this function can be used
|
||||
/// to pass in the raw bytes for the public key components as
|
||||
/// `untrusted::Input` arguments.
|
||||
///
|
||||
/// `params` determine what algorithm parameters (padding, digest algorithm,
|
||||
/// key length range, etc.) are used in the verification. `msg` is the message
|
||||
/// and `signature` is the signature.
|
||||
///
|
||||
/// `n` is the public key modulus and `e` is the public key exponent. Both are
|
||||
/// interpreted as unsigned big-endian encoded values. Both must be positive
|
||||
/// and neither may have any leading zeros.
|
||||
//
|
||||
// There are a small number of tests that test `verify_rsa` directly, but the
|
||||
// There are a small number of tests that test this directly, but the
|
||||
// test coverage for this function mostly depends on the test coverage for the
|
||||
// `signature::VerificationAlgorithm` implementation for `RsaParameters`. If we
|
||||
// change that, test coverage for `verify_rsa()` will need to be reconsidered.
|
||||
@ -200,12 +192,52 @@ rsa_params!(
|
||||
// testing `verify_rsa` directly, but the testing work for RSA PKCS#1
|
||||
// verification was done during the implementation of
|
||||
// `signature::VerificationAlgorithm`, before `verify_rsa` was factored out).
|
||||
pub fn verify_rsa(
|
||||
params: &RsaParameters, (n, e): (untrusted::Input, untrusted::Input), msg: untrusted::Input,
|
||||
signature: untrusted::Input,
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let _ = cpu::features();
|
||||
verify_rsa_(params, (n, e), msg, signature)
|
||||
#[derive(Debug)]
|
||||
pub struct RsaPublicKeyComponents<B: AsRef<[u8]> + core::fmt::Debug> {
|
||||
/// The public modulus, encoded in big-endian bytes without leading zeros.
|
||||
pub n: B,
|
||||
|
||||
/// The public exponent, encoded in big-endian bytes without leading zeros.
|
||||
/// without leading zeros.
|
||||
pub e: B,
|
||||
}
|
||||
|
||||
impl<B: Copy> Copy for RsaPublicKeyComponents<B> where B: AsRef<[u8]> + core::fmt::Debug {}
|
||||
|
||||
impl<B: Clone> Clone for RsaPublicKeyComponents<B>
|
||||
where
|
||||
B: AsRef<[u8]> + core::fmt::Debug,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
n: self.n.clone(),
|
||||
e: self.e.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> RsaPublicKeyComponents<B>
|
||||
where
|
||||
B: AsRef<[u8]> + core::fmt::Debug,
|
||||
{
|
||||
/// Verifies that `signature` is a valid signature of `message` using `self`
|
||||
/// as the public key. `params` determine what algorithm parameters
|
||||
/// (padding, digest algorithm, key length range, etc.) are used in the
|
||||
/// verification.
|
||||
pub fn verify(
|
||||
&self, params: &RsaParameters, message: &[u8], signature: &[u8],
|
||||
) -> Result<(), error::Unspecified> {
|
||||
let _ = cpu::features();
|
||||
verify_rsa_(
|
||||
params,
|
||||
(
|
||||
untrusted::Input::from(self.n.as_ref()),
|
||||
untrusted::Input::from(self.e.as_ref()),
|
||||
),
|
||||
untrusted::Input::from(message),
|
||||
untrusted::Input::from(signature),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn verify_rsa_(
|
||||
|
@ -286,9 +286,9 @@ pub use crate::rsa::{
|
||||
signing::RsaSubjectPublicKey,
|
||||
|
||||
verification::{
|
||||
RSA_PKCS1_2048_8192_SHA1, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA384,
|
||||
RSA_PKCS1_2048_8192_SHA512, RSA_PKCS1_3072_8192_SHA384, RSA_PSS_2048_8192_SHA256,
|
||||
RSA_PSS_2048_8192_SHA384, RSA_PSS_2048_8192_SHA512,
|
||||
RsaPublicKeyComponents, RSA_PKCS1_2048_8192_SHA1, RSA_PKCS1_2048_8192_SHA256,
|
||||
RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512, RSA_PKCS1_3072_8192_SHA384,
|
||||
RSA_PSS_2048_8192_SHA256, RSA_PSS_2048_8192_SHA384, RSA_PSS_2048_8192_SHA512,
|
||||
},
|
||||
|
||||
RsaEncoding,
|
||||
@ -307,17 +307,6 @@ pub use crate::rsa::{
|
||||
RSA_PSS_SHA512,
|
||||
};
|
||||
|
||||
/// Lower-level verification primitives.
|
||||
///
|
||||
/// Use [UnparsedPublicKey::verify()] instead when the public key is in a
|
||||
/// standard format.
|
||||
///
|
||||
/// [UnparsedPublicKey::verify()]: crate::signature::UnparsedPublicKey
|
||||
#[cfg(feature = "use_heap")]
|
||||
pub mod primitive {
|
||||
pub use crate::rsa::verification::verify_rsa;
|
||||
}
|
||||
|
||||
/// A public key signature returned from a signing operation.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Signature {
|
||||
|
@ -272,12 +272,8 @@ fn test_signature_rsa_primitive_verification() {
|
||||
let msg = test_case.consume_bytes("Msg");
|
||||
let sig = test_case.consume_bytes("Sig");
|
||||
let expected = test_case.consume_string("Result");
|
||||
let result = signature::primitive::verify_rsa(
|
||||
&signature::RSA_PKCS1_2048_8192_SHA256,
|
||||
(untrusted::Input::from(&n), untrusted::Input::from(&e)),
|
||||
untrusted::Input::from(&msg),
|
||||
untrusted::Input::from(&sig),
|
||||
);
|
||||
let public_key = signature::RsaPublicKeyComponents { n: &n, e: &e };
|
||||
let result = public_key.verify(&signature::RSA_PKCS1_2048_8192_SHA256, &msg, &sig);
|
||||
assert_eq!(result.is_ok(), expected == "Pass");
|
||||
Ok(())
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user