#[cfg(feature = "alloc")]
use super::pkcs1v15_generate_prefix;
#[cfg(not(feature = "alloc"))]
use super::{pkcs1v15_generate_prefix_helper, Prefix};
use super::{sign_into, sign_with_rng_into, GenericVerifyingKey};
use crate::{
errors::Result,
key::GenericRsaPrivateKey,
traits::{
modular::{ModulusParams, Pow, PowBoundedExp},
PublicKeyParts, UnsignedModularInt,
},
};
use const_oid::AssociatedOid;
use core::fmt;
use core::marker::PhantomData;
use digest::Digest;
use zeroize::Zeroize;
pub struct GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
pub(super) inner: GenericRsaPrivateKey<T, M>,
#[cfg(feature = "alloc")]
pub(super) prefix: alloc::vec::Vec<u8>,
#[cfg(not(feature = "alloc"))]
pub(super) prefix: Prefix,
pub(super) phantom: PhantomData<D>,
}
impl<D, T, M> fmt::Debug for GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
GenericRsaPrivateKey<T, M>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GenericSigningKey")
.field("inner", &self.inner)
.field("prefix", &self.prefix)
.finish()
}
}
#[cfg(feature = "alloc")]
impl<D, T, M> Clone for GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize + Clone,
M: ModulusParams<Modulus = T> + Clone,
M::MontgomeryForm: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
prefix: self.prefix.clone(),
phantom: PhantomData,
}
}
}
#[cfg(not(feature = "alloc"))]
impl<D, T, M> Clone for GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize + Clone,
M: ModulusParams<Modulus = T> + Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
prefix: self.prefix.clone(),
phantom: PhantomData,
}
}
}
impl<D, T, M> GenericSigningKey<D, T, M>
where
D: Digest + AssociatedOid,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
pub fn new(key: GenericRsaPrivateKey<T, M>) -> Self {
Self {
inner: key,
#[cfg(feature = "alloc")]
prefix: pkcs1v15_generate_prefix::<D>(),
#[cfg(not(feature = "alloc"))]
prefix: pkcs1v15_generate_prefix_helper::<D>(),
phantom: PhantomData,
}
}
}
impl<D, T, M> GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
pub fn new_unprefixed(key: GenericRsaPrivateKey<T, M>) -> Self {
Self {
inner: key,
#[cfg(feature = "alloc")]
prefix: alloc::vec::Vec::new(),
#[cfg(not(feature = "alloc"))]
prefix: Prefix::new(),
phantom: PhantomData,
}
}
}
impl<D, T, M> AsRef<GenericRsaPrivateKey<T, M>> for GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
fn as_ref(&self) -> &GenericRsaPrivateKey<T, M> {
&self.inner
}
}
impl<D, T, M> GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
T::Bytes: Zeroize,
M: ModulusParams<Modulus = T> + crate::traits::modular::CtModulusParams,
M::MontgomeryForm: Pow<M> + PowBoundedExp<M>,
{
pub fn try_sign_into<'sig>(
&self,
msg: &[u8],
em_storage: &mut [u8],
sig_storage: &'sig mut [u8],
) -> Result<&'sig [u8]> {
let digest = D::digest(msg);
let k = self.inner.size();
sign_into(
self.inner.n_params(),
crate::traits::keys::PrivateKeyParts::d(&self.inner),
self.inner.e(),
self.prefix.as_ref(),
digest.as_ref(),
k,
em_storage,
sig_storage,
)
}
pub fn try_sign_prehash_into<'sig>(
&self,
prehash: &[u8],
em_storage: &mut [u8],
sig_storage: &'sig mut [u8],
) -> Result<&'sig [u8]> {
if prehash.len() != <D as Digest>::output_size() {
return Err(crate::errors::Error::InputNotHashed);
}
let k = self.inner.size();
sign_into(
self.inner.n_params(),
crate::traits::keys::PrivateKeyParts::d(&self.inner),
self.inner.e(),
self.prefix.as_ref(),
prehash,
k,
em_storage,
sig_storage,
)
}
}
impl<D, T, M> GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize + crate::traits::modular::TryRandomMod,
T::Bytes: Zeroize,
M: ModulusParams<Modulus = T> + crate::traits::modular::CtModulusParams,
M::MontgomeryForm: Pow<M>
+ PowBoundedExp<M>
+ crate::traits::modular::InvertCt<M>
+ crate::traits::modular::MulCt<M>,
{
pub fn try_sign_with_rng_into<'sig, R: rand_core::TryCryptoRng + ?Sized>(
&self,
rng: &mut R,
msg: &[u8],
em_storage: &mut [u8],
sig_storage: &'sig mut [u8],
) -> Result<&'sig [u8]> {
let digest = D::digest(msg);
let k = self.inner.size();
sign_with_rng_into(
rng,
self.inner.n_params(),
crate::traits::keys::PrivateKeyParts::d(&self.inner),
self.inner.e(),
self.prefix.as_ref(),
digest.as_ref(),
k,
em_storage,
sig_storage,
)
}
pub fn try_sign_prehash_with_rng_into<'sig, R: rand_core::TryCryptoRng + ?Sized>(
&self,
rng: &mut R,
prehash: &[u8],
em_storage: &mut [u8],
sig_storage: &'sig mut [u8],
) -> Result<&'sig [u8]> {
if prehash.len() != <D as Digest>::output_size() {
return Err(crate::errors::Error::InputNotHashed);
}
let k = self.inner.size();
sign_with_rng_into(
rng,
self.inner.n_params(),
crate::traits::keys::PrivateKeyParts::d(&self.inner),
self.inner.e(),
self.prefix.as_ref(),
prehash,
k,
em_storage,
sig_storage,
)
}
}
impl<D, T, M> Zeroize for GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
fn zeroize(&mut self) {
self.inner.zeroize();
}
}
impl<D, T, M> GenericSigningKey<D, T, M>
where
D: Digest,
T: UnsignedModularInt + Zeroize,
M: ModulusParams<Modulus = T>,
{
pub fn to_verifying_key(&self) -> GenericVerifyingKey<D, T, M>
where
crate::key::GenericRsaPublicKey<T, M>: Clone,
{
GenericVerifyingKey {
inner: self.inner.as_public().clone(),
prefix: self.prefix.clone(),
phantom: PhantomData,
}
}
}