Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ x509-tsp = { path = "./x509-tsp" }
x509-cert = { path = "./x509-cert" }
x509-ocsp = { path = "./x509-ocsp" }

# RSA: refactor: use RsaPublicKeyRef instead of RsaPublicKey from RustCrypto/formats - #706
rsa = { git = "https://github.com/RustCrypto/RSA.git", rev = "dc89967d5acf570f35375a9eb9151380fabd2f28" }


[workspace.lints.clippy]
borrow_as_ptr = "warn"
cast_lossless = "warn"
Expand Down
3 changes: 2 additions & 1 deletion pkcs1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ pub use crate::{
error::{Error, Result},
params::{RsaOaepParams, RsaPssParams, TrailerField},
private_key::RsaPrivateKey,
public_key::RsaPublicKey,
public_key::{RsaPublicKey, RsaPublicKeyRef},
traits::{DecodeRsaPrivateKey, DecodeRsaPublicKey},
version::Version,
};

#[cfg(feature = "alloc")]
pub use crate::{
private_key::{OtherPrimeInfos, other_prime_info::OtherPrimeInfo},
public_key::RsaPublicKeyOwned,
traits::{EncodeRsaPrivateKey, EncodeRsaPublicKey},
};

Expand Down
14 changes: 7 additions & 7 deletions pkcs1/src/private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#[cfg(feature = "alloc")]
pub(crate) mod other_prime_info;

use crate::{Error, Result, RsaPublicKey, Version};
use crate::{Error, Result, RsaPublicKeyRef, Version};
use core::fmt;
use der::{
Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Tag, Writer,
Expand Down Expand Up @@ -72,8 +72,8 @@ pub struct RsaPrivateKey<'a> {

impl<'a> RsaPrivateKey<'a> {
/// Get the public key that corresponds to this [`RsaPrivateKey`].
pub fn public_key(&self) -> RsaPublicKey<'a> {
RsaPublicKey {
pub fn public_key(&self) -> RsaPublicKeyRef<'a> {
RsaPublicKeyRef {
modulus: self.modulus,
public_exponent: self.public_exponent,
}
Expand Down Expand Up @@ -150,14 +150,14 @@ impl EncodeValue for RsaPrivateKey<'_> {

impl<'a> Sequence<'a> for RsaPrivateKey<'a> {}

impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKey<'a> {
fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKeyRef<'a> {
fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKeyRef<'a> {
private_key.public_key()
}
}

impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKey<'a> {
fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKeyRef<'a> {
fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKeyRef<'a> {
private_key.public_key()
}
}
Expand Down
51 changes: 37 additions & 14 deletions pkcs1/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@

use crate::{Error, Result};
use der::{
Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Writer,
Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Writer,
asn1::UintRef,
};

#[cfg(feature = "alloc")]
use der::Document;
use der::{Document, asn1::Uint};

#[cfg(feature = "pem")]
use der::pem::PemLabel;

/// [`RsaPublicKey`] with [`UintRef`] INTEGERs.
pub type RsaPublicKeyRef<'a> = RsaPublicKey<UintRef<'a>>;

/// [`RsaPublicKey`] with allocating [`Uint`] INTEGERs.
#[cfg(feature = "alloc")]
pub type RsaPublicKeyOwned = RsaPublicKey<Uint>;

/// PKCS#1 RSA Public Keys as defined in [RFC 8017 Appendix 1.1].
///
/// ASN.1 structure containing a serialized RSA public key:
Expand All @@ -25,15 +32,18 @@ use der::pem::PemLabel;
///
/// [RFC 8017 Appendix 1.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.1
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct RsaPublicKey<'a> {
pub struct RsaPublicKey<UintType> {
/// `n`: RSA modulus
pub modulus: UintRef<'a>,
pub modulus: UintType,

/// `e`: RSA public exponent
pub public_exponent: UintRef<'a>,
pub public_exponent: UintType,
}

impl<'a> DecodeValue<'a> for RsaPublicKey<'a> {
impl<'a, UintType> DecodeValue<'a> for RsaPublicKey<UintType>
where
UintType: DecodeValue<'a, Error = der::Error> + FixedTag + 'a,
{
type Error = der::Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
Ok(Self {
Expand All @@ -43,7 +53,10 @@ impl<'a> DecodeValue<'a> for RsaPublicKey<'a> {
}
}

impl EncodeValue for RsaPublicKey<'_> {
impl<UintType> EncodeValue for RsaPublicKey<UintType>
where
UintType: EncodeValue + FixedTag,
{
fn value_len(&self) -> der::Result<Length> {
self.modulus.encoded_len()? + self.public_exponent.encoded_len()?
}
Expand All @@ -55,9 +68,13 @@ impl EncodeValue for RsaPublicKey<'_> {
}
}

impl<'a> Sequence<'a> for RsaPublicKey<'a> {}
impl<'a, UintType> Sequence<'a> for RsaPublicKey<UintType> {}

impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> {
impl<'a, UintType> TryFrom<&'a [u8]> for RsaPublicKey<UintType>
where
RsaPublicKey<UintType>: Decode<'a>,
Error: From<<RsaPublicKey<UintType> as Decode<'a>>::Error>,
{
type Error = Error;

fn try_from(bytes: &'a [u8]) -> Result<Self> {
Expand All @@ -66,24 +83,30 @@ impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> {
}

#[cfg(feature = "alloc")]
impl TryFrom<RsaPublicKey<'_>> for Document {
impl<UintType> TryFrom<RsaPublicKey<UintType>> for Document
where
RsaPublicKey<UintType>: EncodeValue,
{
type Error = Error;

fn try_from(spki: RsaPublicKey<'_>) -> Result<Document> {
fn try_from(spki: RsaPublicKey<UintType>) -> Result<Document> {
Self::try_from(&spki)
}
}

#[cfg(feature = "alloc")]
impl TryFrom<&RsaPublicKey<'_>> for Document {
impl<UintType> TryFrom<&RsaPublicKey<UintType>> for Document
where
RsaPublicKey<UintType>: EncodeValue,
{
type Error = Error;

fn try_from(spki: &RsaPublicKey<'_>) -> Result<Document> {
fn try_from(spki: &RsaPublicKey<UintType>) -> Result<Document> {
Ok(Self::encode_msg(spki)?)
}
}

#[cfg(feature = "pem")]
impl PemLabel for RsaPublicKey<'_> {
impl<UintType> PemLabel for RsaPublicKey<UintType> {
const PEM_LABEL: &'static str = "RSA PUBLIC KEY";
}
13 changes: 8 additions & 5 deletions pkcs1/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use {
use std::path::Path;

#[cfg(all(feature = "alloc", feature = "pem"))]
use crate::{RsaPrivateKey, RsaPublicKey};
use crate::{RsaPrivateKey, RsaPublicKeyRef};

#[cfg(doc)]
use crate::RsaPublicKey;

/// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document.
pub trait DecodeRsaPrivateKey: Sized {
Expand Down Expand Up @@ -70,7 +73,7 @@ pub trait DecodeRsaPublicKey: Sized {
#[cfg(feature = "pem")]
fn from_pkcs1_pem(s: &str) -> Result<Self> {
let (label, doc) = Document::from_pem(s)?;
RsaPublicKey::validate_pem_label(label)?;
RsaPublicKeyRef::validate_pem_label(label)?;
Self::from_pkcs1_der(doc.as_bytes())
}

Expand All @@ -86,7 +89,7 @@ pub trait DecodeRsaPublicKey: Sized {
#[cfg(all(feature = "pem", feature = "std"))]
fn read_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
let (label, doc) = Document::read_pem_file(path)?;
RsaPublicKey::validate_pem_label(&label)?;
RsaPublicKeyRef::validate_pem_label(&label)?;
Self::from_pkcs1_der(doc.as_bytes())
}
}
Expand Down Expand Up @@ -128,7 +131,7 @@ pub trait EncodeRsaPublicKey {
#[cfg(feature = "pem")]
fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<String> {
let doc = self.to_pkcs1_der()?;
Ok(doc.to_pem(RsaPublicKey::PEM_LABEL, line_ending)?)
Ok(doc.to_pem(RsaPublicKeyRef::PEM_LABEL, line_ending)?)
}

/// Write ASN.1 DER-encoded public key to the given path.
Expand All @@ -141,6 +144,6 @@ pub trait EncodeRsaPublicKey {
#[cfg(all(feature = "pem", feature = "std"))]
fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
let doc = self.to_pkcs1_der()?;
Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?)
Ok(doc.write_pem_file(path, RsaPublicKeyRef::PEM_LABEL, line_ending)?)
}
}
6 changes: 3 additions & 3 deletions pkcs1/tests/public_key.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! PKCS#1 public key tests

use hex_literal::hex;
use pkcs1::RsaPublicKey;
use pkcs1::RsaPublicKeyRef;

/// RSA-2048 PKCS#1 public key encoded as ASN.1 DER.
///
Expand All @@ -22,7 +22,7 @@ const RSA_4096_DER_EXAMPLE: &[u8] = include_bytes!("examples/rsa4096-pub.der");

#[test]
fn decode_rsa2048_der() {
let key = RsaPublicKey::try_from(RSA_2048_DER_EXAMPLE).unwrap();
let key = RsaPublicKeyRef::try_from(RSA_2048_DER_EXAMPLE).unwrap();

// Extracted using:
// $ openssl asn1parse -in tests/examples/rsa2048-pub.pem
Expand All @@ -37,7 +37,7 @@ fn decode_rsa2048_der() {

#[test]
fn decode_rsa4096_der() {
let key = RsaPublicKey::try_from(RSA_4096_DER_EXAMPLE).unwrap();
let key = RsaPublicKeyRef::try_from(RSA_4096_DER_EXAMPLE).unwrap();

// Extracted using:
// $ openssl asn1parse -in tests/examples/rsa4096-pub.pem
Expand Down