#![deny(missing_docs)]
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::missing_errors_doc, clippy::must_use_candidate)]
#[cfg(feature = "pem")]
extern crate pem as pem_crate;
use {
crate::error::Error,
num_bigint_dig::ToBigInt,
rsa::{RSAPrivateKey, RSAPublicKey},
};
fn rsa_oid() -> simple_asn1::OID {
use simple_asn1::{BigUint, OID};
simple_asn1::oid!(1, 2, 840, 113_549, 1, 1, 1)
}
fn to_bigint(biguint: &rsa::BigUint) -> simple_asn1::BigInt {
simple_asn1::BigInt::from_signed_bytes_le(
biguint.to_bigint().unwrap().to_signed_bytes_le().as_slice(),
)
}
pub trait Encode: sealed::Sealed {
fn as_pkcs1(&self) -> Result<Vec<u8>, Error>;
fn as_pkcs8(&self) -> Result<Vec<u8>, Error>;
}
impl Encode for RSAPrivateKey {
fn as_pkcs1(&self) -> Result<Vec<u8>, Error> {
pkcs1::private_key(self)
}
fn as_pkcs8(&self) -> Result<Vec<u8>, Error> {
pkcs8::private_key(self)
}
}
impl Encode for RSAPublicKey {
fn as_pkcs1(&self) -> Result<Vec<u8>, Error> {
pkcs1::public_key(self)
}
fn as_pkcs8(&self) -> Result<Vec<u8>, Error> {
pkcs8::public_key(self)
}
}
#[cfg(feature = "pem")]
pub trait PemEncode: sealed::Sealed + Encode {
fn as_pkcs1_pem(&self) -> Result<String, Error>;
fn as_pkcs8_pem(&self) -> Result<String, Error>;
fn as_pkcs1_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error>;
fn as_pkcs8_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error>;
}
#[cfg(feature = "pem")]
impl PemEncode for RSAPrivateKey {
fn as_pkcs1_pem(&self) -> Result<String, Error> {
self.as_pkcs1_pem_custom_ending(LineEnding::LF)
}
fn as_pkcs8_pem(&self) -> Result<String, Error> {
self.as_pkcs8_pem_custom_ending(LineEnding::LF)
}
fn as_pkcs1_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error> {
let pkcs1_der = self.as_pkcs1()?;
Ok(pem::encode(
pem::EncodingScheme::PKCS1,
pem::KeyType::Private,
line_ending,
pkcs1_der,
))
}
fn as_pkcs8_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error> {
let pkcs8_der = self.as_pkcs8()?;
Ok(pem::encode(
pem::EncodingScheme::PKCS8,
pem::KeyType::Private,
line_ending,
pkcs8_der,
))
}
}
#[cfg(feature = "pem")]
impl PemEncode for RSAPublicKey {
fn as_pkcs1_pem(&self) -> Result<String, Error> {
self.as_pkcs1_pem_custom_ending(LineEnding::LF)
}
fn as_pkcs8_pem(&self) -> Result<String, Error> {
self.as_pkcs8_pem_custom_ending(LineEnding::LF)
}
fn as_pkcs1_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error> {
let pkcs1_der = self.as_pkcs1()?;
Ok(pem::encode(
pem::EncodingScheme::PKCS1,
pem::KeyType::Public,
line_ending,
pkcs1_der,
))
}
fn as_pkcs8_pem_custom_ending(&self, line_ending: LineEnding) -> Result<String, Error> {
let pkcs8_der = self.as_pkcs8()?;
Ok(pem::encode(
pem::EncodingScheme::PKCS8,
pem::KeyType::Public,
line_ending,
pkcs8_der,
))
}
}
#[cfg(feature = "pem")]
pub use pem_crate::LineEnding;
mod sealed {
pub trait Sealed {}
impl Sealed for rsa::RSAPrivateKey {}
impl Sealed for rsa::RSAPublicKey {}
}
pub mod error;
mod pkcs1;
mod pkcs8;
#[cfg(feature = "pem")]
mod pem;
#[cfg(test)]
mod test;