RSA: Replace RsaSubjectPublicKey::{modulus,exponent}
with rsa::Public::{Modulus,Exponent}::be_bytes()
.
This is a step towards removing the heap-allocated and usually-unnecessary `public_key: RsaSubjectPublicKey` field. The new API allows the caller to better control how it stores/allocates the component values. This also removes a couple of infallible `unwrap()`s. This is a step towards removing `io::Positive` from the public API. This is a breaking API change.
This commit is contained in:
parent
dd14e593e1
commit
511740c29f
@ -131,6 +131,7 @@ include = [
|
||||
"tests/rsa_test_private_key_2048.p8",
|
||||
"tests/rsa_test_public_key_2048.der",
|
||||
"tests/rsa_test_public_key_2048_debug.txt",
|
||||
"tests/rsa_test_public_modulus.bin",
|
||||
"third_party/fiat/curve25519_32.h",
|
||||
"third_party/fiat/curve25519_64.h",
|
||||
"third_party/fiat/p256_32.h",
|
||||
|
@ -40,7 +40,7 @@ use crate::{
|
||||
arithmetic::montgomery::*,
|
||||
bits, bssl, c, error,
|
||||
limb::{self, Limb, LimbMask, LIMB_BITS, LIMB_BYTES},
|
||||
polyfill::u64_from_usize,
|
||||
polyfill::{u64_from_usize, LeadingZerosStripped},
|
||||
};
|
||||
use alloc::{borrow::ToOwned as _, boxed::Box, vec, vec::Vec};
|
||||
use core::{
|
||||
@ -352,6 +352,12 @@ impl<M> Modulus<M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: PublicModulus> Modulus<M> {
|
||||
pub fn be_bytes(&self) -> LeadingZerosStripped<impl ExactSizeIterator<Item = u8> + Clone + '_> {
|
||||
LeadingZerosStripped::new(limb::unstripped_be_bytes(&self.limbs))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PartialModulus<'a, M> {
|
||||
limbs: &'a [Limb],
|
||||
n0: N0,
|
||||
|
@ -237,7 +237,7 @@ pub fn parse_big_endian_and_pad_consttime(
|
||||
}
|
||||
|
||||
pub fn big_endian_from_limbs(limbs: &[Limb], out: &mut [u8]) {
|
||||
let be_bytes = be_bytes(limbs);
|
||||
let be_bytes = unstripped_be_bytes(limbs);
|
||||
assert_eq!(out.len(), be_bytes.len());
|
||||
out.iter_mut().zip(be_bytes).for_each(|(o, i)| {
|
||||
*o = i;
|
||||
@ -246,8 +246,9 @@ pub fn big_endian_from_limbs(limbs: &[Limb], out: &mut [u8]) {
|
||||
|
||||
/// Returns an iterator of the big-endian encoding of `limbs`.
|
||||
///
|
||||
/// The number of bytes returned will be a multiple of `LIMB_BYTES`.
|
||||
fn be_bytes(limbs: &[Limb]) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
|
||||
/// The number of bytes returned will be a multiple of `LIMB_BYTES`
|
||||
/// and thus may be padded with leading zeros.
|
||||
pub fn unstripped_be_bytes(limbs: &[Limb]) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
|
||||
// The unwrap is safe because a slice can never be larger than `usize` bytes.
|
||||
ArrayFlatMap::new(limbs.iter().rev().copied(), |limb| {
|
||||
core::array::IntoIter::new(Limb::to_be_bytes(limb))
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::error;
|
||||
use crate::polyfill::{ArrayFlatMap, LeadingZerosStripped};
|
||||
use core::num::NonZeroU64;
|
||||
|
||||
/// The exponent `e` of an RSA public key.
|
||||
@ -77,6 +78,18 @@ impl Exponent {
|
||||
|
||||
Ok(Self(value))
|
||||
}
|
||||
|
||||
/// The big-endian encoding of the exponent.
|
||||
///
|
||||
/// There are no leading zeros.
|
||||
pub fn be_bytes(&self) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
|
||||
// The `unwrap()` won't fail as `self.0` is only a few bytes long.
|
||||
let bytes = ArrayFlatMap::new(core::iter::once(self.0.get()), |value| {
|
||||
core::array::IntoIter::new(u64::to_be_bytes(value))
|
||||
})
|
||||
.unwrap();
|
||||
LeadingZerosStripped::new(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Exponent> for NonZeroU64 {
|
||||
|
@ -48,6 +48,14 @@ impl Modulus {
|
||||
Ok(Self { value, bits })
|
||||
}
|
||||
|
||||
/// The big-endian encoding of the modulus.
|
||||
///
|
||||
/// There are no leading zeros.
|
||||
#[inline]
|
||||
pub fn be_bytes(&self) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
|
||||
self.value.be_bytes()
|
||||
}
|
||||
|
||||
/// The length of the modulus in bits.
|
||||
#[inline]
|
||||
pub fn len_bits(&self) -> bits::BitLength {
|
||||
|
@ -484,22 +484,6 @@ impl RsaSubjectPublicKey {
|
||||
});
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
|
||||
/// The public modulus (n).
|
||||
pub fn modulus(&self) -> io::Positive {
|
||||
// Parsing won't fail because we serialized it ourselves.
|
||||
let (public_key, _exponent) =
|
||||
super::parse_public_key(untrusted::Input::from(self.as_ref())).unwrap();
|
||||
public_key
|
||||
}
|
||||
|
||||
/// The public exponent (e).
|
||||
pub fn exponent(&self) -> io::Positive {
|
||||
// Parsing won't fail because we serialized it ourselves.
|
||||
let (_public_key, exponent) =
|
||||
super::parse_public_key(untrusted::Input::from(self.as_ref())).unwrap();
|
||||
exponent
|
||||
}
|
||||
}
|
||||
|
||||
struct PrivatePrime<M: Prime> {
|
||||
|
BIN
tests/rsa_test_public_modulus.bin
Normal file
BIN
tests/rsa_test_public_modulus.bin
Normal file
Binary file not shown.
@ -329,13 +329,18 @@ fn rsa_test_public_key_coverage() {
|
||||
// Test `Clone`.
|
||||
let _ = key_pair.public_key().clone();
|
||||
|
||||
// Test `exponent()`.
|
||||
// Test modulus encoding.
|
||||
const PUBLIC_KEY_MODULUS_BE_BYTES: &[u8] = include_bytes!("rsa_test_public_modulus.bin");
|
||||
assert_eq!(
|
||||
&[0x01, 0x00, 0x01],
|
||||
key_pair
|
||||
.public_key()
|
||||
.exponent()
|
||||
.big_endian_without_leading_zero()
|
||||
PUBLIC_KEY_MODULUS_BE_BYTES,
|
||||
key_pair.public().n().be_bytes().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Test exponent encoding.
|
||||
const _65537: &[u8] = &[0x01, 0x00, 0x01];
|
||||
assert_eq!(
|
||||
_65537,
|
||||
&key_pair.public().e().be_bytes().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// Test `Debug`
|
||||
|
Loading…
x
Reference in New Issue
Block a user