use std::marker::PhantomData;
use digest::{typenum::Unsigned, OutputSizeUser};
use rsa::{
pkcs1v15::{self, Signature},
RsaPublicKey,
};
use sha2::Digest;
use signature::{hazmat::PrehashSigner, Keypair, SignatureEncoding};
use crate::pgp::{
adapter::PublicKey as HPublicKey,
crypto::{
hash::{HashAlgorithm, KnownDigest},
public_key::PublicKeyAlgorithm,
},
errors::{bail, Result},
packet::{PubKeyInner, PublicKey},
types::{
Fingerprint, KeyDetails, KeyId, KeyVersion, Mpi, Password, PublicParams, RsaPublicParams,
SignatureBytes, SigningKey, Timestamp, VerifyingKey,
},
};
impl HPublicKey for RsaPublicKey {
const PGP_ALGORITHM: PublicKeyAlgorithm = PublicKeyAlgorithm::RSA;
fn pgp_parameters(&self) -> PublicParams {
let key = self.clone();
PublicParams::RSA(RsaPublicParams { key })
}
}
#[derive(derive_more::Debug)]
#[debug("RsaSigner({public_key:?})")]
pub struct RsaSigner<T, D> {
inner: T,
public_key: PublicKey,
_digest: PhantomData<D>,
}
impl<T, D> RsaSigner<T, D>
where
D: Digest,
T: Keypair<VerifyingKey = pkcs1v15::VerifyingKey<D>>,
{
pub fn new(inner: T, version: KeyVersion, created_at: Timestamp) -> Result<Self> {
let public_key = PubKeyInner::new(
version,
RsaPublicKey::PGP_ALGORITHM,
created_at,
None,
inner.verifying_key().as_ref().pgp_parameters(),
)?;
let public_key = PublicKey::from_inner(public_key)?;
Ok(Self {
inner,
public_key,
_digest: PhantomData,
})
}
pub fn public_key(&self) -> &PublicKey {
&self.public_key
}
}
impl<D, T> RsaSigner<T, D>
where
D: Digest + KnownDigest,
T: PrehashSigner<Signature>,
{
fn sign_prehash(&self, hash: HashAlgorithm, prehash: &[u8]) -> Result<Vec<Vec<u8>>> {
if D::HASH_ALGORITHM != hash {
bail!(
"Signer only support {expected:?}, found {found:?}",
expected = D::HASH_ALGORITHM,
found = hash
);
}
if <D as OutputSizeUser>::OutputSize::USIZE != prehash.len() {
bail!(
"Signer expected a hash of length ({expected} bytes), found ({found} bytes)",
expected = <D as OutputSizeUser>::OutputSize::USIZE,
found = prehash.len()
);
}
let sig = self.inner.sign_prehash(prehash)?;
Ok(vec![sig.to_vec()])
}
}
impl<D, T> Keypair for RsaSigner<T, D>
where
T: Keypair,
{
type VerifyingKey = T::VerifyingKey;
fn verifying_key(&self) -> Self::VerifyingKey {
self.inner.verifying_key()
}
}
impl<D, T> SigningKey for RsaSigner<T, D>
where
T: PrehashSigner<Signature>,
D: Digest + KnownDigest,
{
fn sign(
&self,
_key_pw: &Password,
hash: HashAlgorithm,
prehashed_data: &[u8],
) -> Result<SignatureBytes> {
let sig = self.sign_prehash(hash, prehashed_data)?;
let mpis = sig
.iter()
.map(|v| Mpi::from_slice(&v[..]))
.collect::<Vec<_>>();
Ok(SignatureBytes::Mpis(mpis))
}
fn hash_alg(&self) -> HashAlgorithm {
D::HASH_ALGORITHM
}
}
impl<D, T> KeyDetails for RsaSigner<T, D> {
fn version(&self) -> KeyVersion {
self.public_key.version()
}
fn fingerprint(&self) -> Fingerprint {
self.public_key.fingerprint()
}
fn legacy_key_id(&self) -> KeyId {
self.public_key.legacy_key_id()
}
fn algorithm(&self) -> PublicKeyAlgorithm {
self.public_key.algorithm()
}
fn created_at(&self) -> Timestamp {
self.public_key.created_at()
}
fn expiration(&self) -> Option<u16> {
self.public_key.expiration()
}
fn public_params(&self) -> &PublicParams {
self.public_key.public_params()
}
}
impl<D, T> VerifyingKey for RsaSigner<T, D> {
fn verify(&self, hash: HashAlgorithm, data: &[u8], sig: &SignatureBytes) -> Result<()> {
self.public_key.verify(hash, data, sig)
}
}