#[cfg(feature = "alloc")]
pub(crate) mod document;
#[cfg(feature = "alloc")]
pub(crate) mod other_prime_info;
use crate::{Error, Result, RsaPublicKey, Version};
use core::fmt;
use der::{asn1::UIntBytes, Decodable, Decoder, Encodable, Sequence, Tag};
#[cfg(feature = "alloc")]
use {self::other_prime_info::OtherPrimeInfo, crate::RsaPrivateKeyDocument, alloc::vec::Vec};
#[cfg(feature = "pem")]
use {
crate::{EncodeRsaPrivateKey, LineEnding},
alloc::string::String,
zeroize::Zeroizing,
};
#[derive(Clone)]
pub struct RsaPrivateKey<'a> {
pub modulus: UIntBytes<'a>,
pub public_exponent: UIntBytes<'a>,
pub private_exponent: UIntBytes<'a>,
pub prime1: UIntBytes<'a>,
pub prime2: UIntBytes<'a>,
pub exponent1: UIntBytes<'a>,
pub exponent2: UIntBytes<'a>,
pub coefficient: UIntBytes<'a>,
pub other_prime_infos: Option<OtherPrimeInfos<'a>>,
}
impl<'a> RsaPrivateKey<'a> {
pub fn public_key(&self) -> RsaPublicKey<'a> {
RsaPublicKey {
modulus: self.modulus,
public_exponent: self.public_exponent,
}
}
pub fn version(&self) -> Version {
if self.other_prime_infos.is_some() {
Version::Multi
} else {
Version::TwoPrime
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn to_der(&self) -> Result<RsaPrivateKeyDocument> {
self.try_into()
}
#[cfg(feature = "pem")]
#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
pub fn to_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
self.to_der()?.to_pkcs1_pem(line_ending)
}
}
impl<'a> Decodable<'a> for RsaPrivateKey<'a> {
fn decode(decoder: &mut Decoder<'a>) -> der::Result<Self> {
decoder.sequence(|decoder| {
let version = Version::decode(decoder)?;
let result = Self {
modulus: decoder.decode()?,
public_exponent: decoder.decode()?,
private_exponent: decoder.decode()?,
prime1: decoder.decode()?,
prime2: decoder.decode()?,
exponent1: decoder.decode()?,
exponent2: decoder.decode()?,
coefficient: decoder.decode()?,
other_prime_infos: decoder.decode()?,
};
if version.is_multi() != result.other_prime_infos.is_some() {
return Err(decoder.error(der::ErrorKind::Value { tag: Tag::Integer }));
}
Ok(result)
})
}
}
impl<'a> Sequence<'a> for RsaPrivateKey<'a> {
fn fields<F, T>(&self, f: F) -> der::Result<T>
where
F: FnOnce(&[&dyn Encodable]) -> der::Result<T>,
{
f(&[
&self.version(),
&self.modulus,
&self.public_exponent,
&self.private_exponent,
&self.prime1,
&self.prime2,
&self.exponent1,
&self.exponent2,
&self.coefficient,
#[cfg(feature = "alloc")]
&self.other_prime_infos,
])
}
}
impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKey<'a> {
fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
private_key.public_key()
}
}
impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKey<'a> {
fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
private_key.public_key()
}
}
impl<'a> TryFrom<&'a [u8]> for RsaPrivateKey<'a> {
type Error = Error;
fn try_from(bytes: &'a [u8]) -> Result<Self> {
Ok(Self::from_der(bytes)?)
}
}
impl<'a> fmt::Debug for RsaPrivateKey<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RsaPrivateKey")
.field("version", &self.version())
.field("modulus", &self.modulus)
.field("public_exponent", &self.public_exponent)
.finish_non_exhaustive()
}
}
#[cfg(not(feature = "alloc"))]
#[derive(Clone)]
#[non_exhaustive]
pub struct OtherPrimeInfos<'a> {
_lifetime: core::marker::PhantomData<&'a ()>,
}
#[cfg(not(feature = "alloc"))]
impl<'a> Decodable<'a> for OtherPrimeInfos<'a> {
fn decode(decoder: &mut Decoder<'a>) -> der::Result<Self> {
Err(decoder.error(der::ErrorKind::Value { tag: Tag::Integer }))
}
}
#[cfg(not(feature = "alloc"))]
impl<'a> der::FixedTag for OtherPrimeInfos<'a> {
const TAG: Tag = Tag::Sequence;
}
#[cfg(feature = "alloc")]
pub type OtherPrimeInfos<'a> = Vec<OtherPrimeInfo<'a>>;