//! Hold the implementation of [`Signer`] and [`Decryptor`] for [`KeyPair`].
//!
//! [`Signer`]: super::super::asymmetric::Signer
//! [`Decryptor`]: super::super::asymmetric::Decryptor
//! [`KeyPair`]: super::super::asymmetric::KeyPair
use std::time::SystemTime;
use botan::{
RandomNumberGenerator,
Pubkey,
Privkey,
};
use crate::{
Error,
Result,
crypto::{
asymmetric::{KeyPair, Decryptor, Signer},
mem::Protected,
mpi::{self, MPI, ProtectedMPI, PublicKey},
SessionKey,
},
packet::{
key::{self, Key4, SecretParts},
Key,
},
types::{
Curve,
HashAlgorithm,
PublicKeyAlgorithm,
SymmetricAlgorithm,
},
};
// CONFIDENTIALITY: Botan clears the MPIs after use.
impl TryFrom<&ProtectedMPI> for botan::MPI {
type Error = anyhow::Error;
fn try_from(mpi: &ProtectedMPI) -> anyhow::Result<botan::MPI> {
Ok(botan::MPI::new_from_bytes(mpi.value())?)
}
}
impl TryFrom<&botan::MPI> for ProtectedMPI {
type Error = anyhow::Error;
fn try_from(bn: &botan::MPI) -> anyhow::Result<Self> {
Ok(bn.to_bin()?.into())
}
}
impl TryFrom<botan::MPI> for ProtectedMPI {
type Error = anyhow::Error;
fn try_from(bn: botan::MPI) -> anyhow::Result<Self> {
Ok(bn.to_bin()?.into())
}
}
impl TryFrom<&MPI> for botan::MPI {
type Error = anyhow::Error;
fn try_from(mpi: &MPI) -> anyhow::Result<botan::MPI> {
Ok(botan::MPI::new_from_bytes(mpi.value())?)
}
}
impl TryFrom<&botan::MPI> for MPI {
type Error = anyhow::Error;
fn try_from(bn: &botan::MPI) -> anyhow::Result<Self> {
Ok(bn.to_bin()?.into())
}
}
impl TryFrom<botan::MPI> for MPI {
type Error = anyhow::Error;
fn try_from(bn: botan::MPI) -> anyhow::Result<Self> {
Ok(bn.to_bin()?.into())
}
}
impl Signer for KeyPair {
fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
KeyPair::public(self)
}
fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
-> Result<mpi::Signature>
{
use crate::PublicKeyAlgorithm::*;
let mut rng = RandomNumberGenerator::new_userspace()?;
self.secret().map(|secret| {
#[allow(deprecated)]
match (self.public().pk_algo(), self.public().mpis(), secret)
{
(RSASign,
PublicKey::RSA { e, .. },
mpi::SecretKeyMaterial::RSA { p, q, .. }) |
(RSAEncryptSign,
PublicKey::RSA { e, .. },
mpi::SecretKeyMaterial::RSA { p, q, .. }) => {
let secret = Privkey::load_rsa(&p.try_into()?, &q.try_into()?,
&e.try_into()?)?;
let sig = secret.sign(
digest,
&format!("PKCS1v15(Raw,{})", hash_algo.botan_name()?),
&mut rng)?;
Ok(mpi::Signature::RSA {
s: MPI::new(&sig),
})
},
(DSA,
PublicKey::DSA { p, q, g, .. },
mpi::SecretKeyMaterial::DSA { x }) => {
let secret = Privkey::load_dsa(&p.