//! Holds the implementation of [`Signer`] and [`Decryptor`] for [`KeyPair`].
//!
//! [`Signer`]: ../../asymmetric/trait.Signer.html
//! [`Decryptor`]: ../../asymmetric/trait.Decryptor.html
//! [`KeyPair`]: ../../asymmetric/struct.KeyPair.html
use std::convert::TryFrom;
use std::time::SystemTime;
use num_bigint_dig::{traits::ModInverse, BigUint};
use rsa::traits::{PrivateKeyParts, PublicKeyParts};
use rsa::{Pkcs1v15Encrypt, RsaPublicKey, RsaPrivateKey, Pkcs1v15Sign};
use ecdsa::{
EncodedPoint,
hazmat::{SignPrimitive, VerifyPrimitive},
};
use p256::elliptic_curve::{
generic_array::GenericArray as GA,
ops::Reduce,
sec1::FromEncodedPoint,
};
use crate::{Error, Result};
use crate::crypto::asymmetric::KeyPair;
use crate::crypto::backend::interface::Asymmetric;
use crate::crypto::mem::Protected;
use crate::crypto::mpi::{self, MPI, ProtectedMPI};
use crate::crypto::SessionKey;
use crate::crypto::pad_truncating;
use crate::packet::{key, Key};
use crate::packet::key::{Key4, SecretParts};
use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm};
use super::GenericArrayExt;
impl TryFrom<&Protected> for Box<ed25519_dalek::SigningKey> {
type Error = anyhow::Error;
fn try_from(value: &Protected) -> Result<Self> {
if value.len() != ed25519_dalek::SECRET_KEY_LENGTH {
return Err(crate::Error::InvalidArgument(
"Bad Ed25519 secret length".into()).into());
}
Ok(Box::new(ed25519_dalek::SigningKey::from_bytes(
value.as_ref().try_into().map_err(
|e: std::array::TryFromSliceError| {
Error::InvalidKey(e.to_string())
})?)))
}
}
impl Asymmetric for super::Backend {
fn supports_algo(algo: PublicKeyAlgorithm) -> bool {
use PublicKeyAlgorithm::*;
#[allow(deprecated)]
match algo {
RSAEncryptSign | RSAEncrypt | RSASign | ECDH | EdDSA | ECDSA
=> true,
DSA
=> true,
ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_)
=> false,
}
}
fn supports_curve(curve: &Curve) -> bool {
use self::Curve::*;
match curve {
NistP256 | NistP384
=> true,
NistP521
=> false,
Ed25519 | Cv25519
=> true,
BrainpoolP256 | BrainpoolP512 | Unknown(_)
=> false,
}
}
fn x25519_generate_key() -> Result<(Protected, [u8; 32])> {
use x25519_dalek::{StaticSecret, PublicKey};
// x25519_dalek v1.1 doesn't reexport OsRng. It
// depends on rand 0.8.
use rand::rngs::OsRng;
let secret = StaticSecret::random_from_rng(&mut OsRng);
let public = PublicKey::from(&secret);
let mut secret_bytes = secret.to_bytes();
let secret: Protected = secret_bytes.as_ref().into();
unsafe {
memsec::memzero(secret_bytes.as_mut_ptr(), secret_bytes.len());
}
Ok((secret, public.to_bytes()))
}
fn x25519_derive_public(secret: &Protected) -> Result<[u8; 32]> {
use x25519_dalek::{PublicKey, StaticSecret};
let secret = StaticSecret::from(<[u8; 32]>::try_from(&secret[..])?);
Ok(*PublicKey::from(&secret).as_bytes())
}
fn x25519_shared_point(secret: &Protected, public: &[u8; 32])
-> Result<Protected> {
use x25519_dalek::{StaticSecret, PublicKey};
let secret = StaticSecret::from(<[u8; 32]>::try_from(&secret[..])?);
let public = PublicKey::from(public.clone());
Ok((&secret.diffie_hellman(&public).as_bytes()[