Remove RSASigningState.

This commit is contained in:
Brian Smith 2018-12-12 11:12:46 -10:00
parent 67425b7463
commit 69e1ad202a
3 changed files with 22 additions and 58 deletions

View File

@ -27,11 +27,6 @@ use std;
use untrusted;
/// An RSA key pair, used for signing.
///
/// After constructing an `RSAKeyPair`, construct one or more
/// `RSASigningState`s that reference the `RSAKeyPair` and use
/// `RSASigningState::sign()` to generate signatures. See `ring::signature`'s
/// module-level documentation for an example.
pub struct KeyPair {
p: PrivatePrime<P>,
q: PrivatePrime<Q>,
@ -458,23 +453,7 @@ unsafe impl bigint::SlightlySmallerModulus<P> for Q {}
unsafe impl bigint::SmallerModulus<QQ> for Q {}
unsafe impl bigint::NotMuchSmallerModulus<QQ> for Q {}
/// State used for RSA Signing.
//
// TODO: Remove this; it's not needed if we don't have RSA blinding.
pub struct SigningState {
key_pair: std::sync::Arc<KeyPair>,
}
impl SigningState {
/// Construct a signing state appropriate for use with the given key pair.
pub fn new(key_pair: std::sync::Arc<KeyPair>) -> Result<Self, error::Unspecified> {
Ok(SigningState { key_pair })
}
/// The key pair. This can be used, for example, to access the key pair's
/// public key.
pub fn key_pair(&self) -> &KeyPair { self.key_pair.as_ref() }
impl KeyPair {
/// Sign `msg`. `msg` is digested using the digest algorithm from
/// `padding_alg` and the digest is then padded using the padding algorithm
/// from `padding_alg`. The signature it written into `signature`;
@ -492,23 +471,21 @@ impl SigningState {
/// x86-64, this is done pretty well, but not perfectly. On other
/// platforms, it is done less perfectly.
pub fn sign(
&mut self, padding_alg: &'static crate::signature::RSAEncoding, rng: &rand::SecureRandom,
&self, padding_alg: &'static crate::signature::RSAEncoding, rng: &rand::SecureRandom,
msg: &[u8], signature: &mut [u8],
) -> Result<(), error::Unspecified> {
let mod_bits = self.key_pair.public_key.n_bits;
let mod_bits = self.public_key.n_bits;
if signature.len() != mod_bits.as_usize_bytes_rounded_up() {
return Err(error::Unspecified);
}
let SigningState { key_pair: key } = self;
let m_hash = digest::digest(padding_alg.digest_alg(), msg);
padding_alg.encode(&m_hash, signature, mod_bits, rng)?;
// RFC 8017 Section 5.1.2: RSADP, using the Chinese Remainder Theorem
// with Garner's algorithm.
let n = &key.public_key.n;
let n = &self.public_key.n;
// Step 1. The value zero is also rejected.
let base = bigint::Elem::from_be_bytes_padded(untrusted::Input::from(signature), n)?;
@ -517,24 +494,24 @@ impl SigningState {
let c = base;
// Step 2.b.i.
let m_1 = elem_exp_consttime(&c, &key.p)?;
let c_mod_qq = bigint::elem_reduced_once(&c, &key.qq);
let m_2 = elem_exp_consttime(&c_mod_qq, &key.q)?;
let m_1 = elem_exp_consttime(&c, &self.p)?;
let c_mod_qq = bigint::elem_reduced_once(&c, &self.qq);
let m_2 = elem_exp_consttime(&c_mod_qq, &self.q)?;
// Step 2.b.ii isn't needed since there are only two primes.
// Step 2.b.iii.
let p = &key.p.modulus;
let p = &self.p.modulus;
let m_2 = bigint::elem_widen(m_2, p);
let m_1_minus_m_2 = bigint::elem_sub(m_1, &m_2, p);
let h = bigint::elem_mul(&key.qInv, m_1_minus_m_2, p);
let h = bigint::elem_mul(&self.qInv, m_1_minus_m_2, p);
// Step 2.b.iv. The reduction in the modular multiplication isn't
// necessary because `h < p` and `p * q == n` implies `h * q < n`.
// Modular arithmetic is used simply to avoid implementing
// non-modular arithmetic.
let h = bigint::elem_widen(h, n);
let q_times_h = bigint::elem_mul(&key.q_mod_n, h, n);
let q_times_h = bigint::elem_mul(&self.q_mod_n, h, n);
let m_2 = bigint::elem_widen(m_2, n);
let m = bigint::elem_add(m_2, q_times_h, n);
@ -549,7 +526,7 @@ impl SigningState {
// minimum value, since the relationship of `e` to `d`, `p`, and `q` is
// not verified during `KeyPair` construction.
{
let verify = bigint::elem_exp_vartime(m.clone(), key.public_key.e, n);
let verify = bigint::elem_exp_vartime(m.clone(), self.public_key.e, n);
let verify = verify.into_unencoded(n);
bigint::elem_verify_equal_consttime(&verify, &c)?;
}
@ -584,25 +561,23 @@ mod tests {
include_bytes!("signature_rsa_example_private_key.der");
let key_bytes_der = untrusted::Input::from(PRIVATE_KEY_DER);
let key_pair = signature::RSAKeyPair::from_der(key_bytes_der).unwrap();
let key_pair = std::sync::Arc::new(key_pair);
let mut signing_state = signature::RSASigningState::new(key_pair).unwrap();
// The output buffer is one byte too short.
let mut signature = vec![0; signing_state.key_pair().public_modulus_len() - 1];
let mut signature = vec![0; key_pair.public_modulus_len() - 1];
assert!(signing_state
assert!(key_pair
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_err());
// The output buffer is the right length.
signature.push(0);
assert!(signing_state
assert!(key_pair
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_ok());
// The output buffer is one byte too long.
signature.push(0);
assert!(signing_state
assert!(key_pair
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_err());
}

View File

@ -206,18 +206,12 @@
//! let key_pair = signature::RSAKeyPair::from_der(private_key_der)
//! .map_err(|_| MyError::BadPrivateKey)?;
//!
//! // Create a signing state.
//! let key_pair = std::sync::Arc::new(key_pair);
//! let mut signing_state = signature::RSASigningState::new(key_pair)
//! .map_err(|_| MyError::OOM)?;
//!
//! // Sign the message "hello, world", using PKCS#1 v1.5 padding and the
//! // SHA256 digest algorithm.
//! const MESSAGE: &'static [u8] = b"hello, world";
//! let rng = rand::SystemRandom::new();
//! let mut signature = vec![0; signing_state.key_pair().public_modulus_len()];
//! signing_state.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE,
//! &mut signature)
//! let mut signature = vec![0; key_pair.public_modulus_len()];
//! key_pair.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
//! .map_err(|_| MyError::OOM)?;
//!
//! // Verify the signature.
@ -297,7 +291,7 @@ pub use crate::ec::curve25519::ed25519::signing::{
};
#[cfg(feature = "use_heap")]
pub use crate::rsa::signing::{KeyPair as RSAKeyPair, SigningState as RSASigningState};
pub use crate::rsa::signing::KeyPair as RSAKeyPair;
#[cfg(feature = "use_heap")]
pub use crate::rsa::{

View File

@ -89,9 +89,8 @@ fn test_signature_rsa_pkcs1_sign() {
// XXX: This test is too slow on Android ARM Travis CI builds.
// TODO: re-enable these tests on Android ARM.
let mut signing_state = signature::RSASigningState::new(key_pair).unwrap();
let mut actual = vec![0u8; signing_state.key_pair().public_modulus_len()];
signing_state
let mut actual = vec![0u8; key_pair.public_modulus_len()];
key_pair
.sign(alg, &rng, &msg, actual.as_mut_slice())
.unwrap();
assert_eq!(actual.as_slice() == &expected[..], result == "Pass");
@ -121,16 +120,14 @@ fn test_signature_rsa_pss_sign() {
return Ok(());
}
let key_pair = key_pair.unwrap();
let key_pair = std::sync::Arc::new(key_pair);
let msg = test_case.consume_bytes("Msg");
let salt = test_case.consume_bytes("Salt");
let expected = test_case.consume_bytes("Sig");
let rng = test::rand::FixedSliceRandom { bytes: &salt };
let mut signing_state = signature::RSASigningState::new(key_pair).unwrap();
let mut actual = vec![0u8; signing_state.key_pair().public_modulus_len()];
signing_state.sign(alg, &rng, &msg, actual.as_mut_slice())?;
let mut actual = vec![0u8; key_pair.public_modulus_len()];
key_pair.sign(alg, &rng, &msg, actual.as_mut_slice())?;
assert_eq!(actual.as_slice() == &expected[..], result == "Pass");
Ok(())
});
@ -142,8 +139,6 @@ fn test_rsa_key_pair_traits() {
test::compile_time_assert_send::<signature::RSAKeyPair>();
test::compile_time_assert_sync::<signature::RSAKeyPair>();
test::compile_time_assert_debug::<signature::RSAKeyPair>();
test::compile_time_assert_send::<signature::RSASigningState>();
// TODO: Test that RSASigningState is NOT Sync.
}
#[cfg(feature = "use_heap")]