use std::future::Future;
use rand_core::{CryptoRng, RngCore};
use crate::curve::SharedSecret;
use crate::curve::ed25519::{
Ed25519, Ed25519PublicKey, Ed25519Signature, SoftwareEd25519PrivateKey,
};
use crate::curve::p256::{P256, P256Signature, P256r1PrivateKey, P256r1PublicKey};
use crate::curve::x448::{SoftwareX448PrivateKey, X448, X448PublicKey};
use crate::curve::x25519::{SoftwareX25519PrivateKey, X25519, X25519PublicKey};
use crate::curve::{Curve, DhCurve, SigningCurve};
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg_attr(docsrs, doc(cfg(any(target_os = "macos", target_os = "ios"))))]
pub mod apple;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg_attr(docsrs, doc(cfg(any(target_os = "macos", target_os = "ios"))))]
pub use apple::{AppleSecureEnclave, SeedError};
#[cfg(any(target_os = "macos", target_os = "ios"))]
impl SecretKey for crate::provider::apple::P256r1PrivateKey {
type Curve = P256;
}
pub trait CryptoKeyProvider<C: Curve> {
type Error: std::error::Error + Send + Sync + 'static;
type PrivateKey: Send;
fn public_key(&self, key: &Self::PrivateKey) -> Result<C::PublicKey, Self::Error>;
fn generate_static_key(&mut self) -> Result<Self::PrivateKey, Self::Error>;
fn generate_ephemeral_key(&mut self) -> Result<Self::PrivateKey, Self::Error>;
}
pub trait CryptoKeyProviderAsync<C: Curve>: CryptoKeyProvider<C> {
fn generate_static_key_async(
&mut self,
) -> impl Future<Output = Result<Self::PrivateKey, Self::Error>> + Send;
fn generate_ephemeral_key_async(
&mut self,
) -> impl Future<Output = Result<Self::PrivateKey, Self::Error>> + Send;
}
pub trait DhProvider<C: DhCurve>: CryptoKeyProvider<C> {
fn dh(
&self,
key: &Self::PrivateKey,
peer: &C::PublicKey,
) -> Result<C::SharedSecret, Self::Error>;
}
pub trait DhProviderAsync<C: DhCurve>: CryptoKeyProviderAsync<C> {
fn dh_async(
&self,
key: &Self::PrivateKey,
peer: &C::PublicKey,
) -> impl Future<Output = Result<C::SharedSecret, Self::Error>> + Send;
}
pub trait SigningProvider<C: SigningCurve>: CryptoKeyProvider<C> {
fn sign(&self, key: &Self::PrivateKey, message: &[u8]) -> Result<C::Signature, Self::Error>;
}
pub trait SigningProviderAsync<C: SigningCurve>: CryptoKeyProvider<C> {
fn sign_async(
&self,
key: &Self::PrivateKey,
message: &[u8],
) -> impl Future<Output = Result<C::Signature, Self::Error>> + Send;
}
#[derive(Clone)]
pub struct EphemeralOnly<R> {
rng: R,
}
impl<R: CryptoRng + RngCore> CryptoKeyProvider<P256> for EphemeralOnly<R> {
type Error = crate::curve::p256::Error;
type PrivateKey = P256r1PrivateKey;
fn public_key(&self, key: &Self::PrivateKey) -> Result<P256r1PublicKey, Self::Error> {
Ok(key.public())
}
fn generate_static_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
P256r1PrivateKey::generate(&mut self.rng)
}
fn generate_ephemeral_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
P256r1PrivateKey::generate(&mut self.rng)
}
}
impl<R: CryptoRng + RngCore + Send + Sync> CryptoKeyProviderAsync<P256> for EphemeralOnly<R> {
async fn generate_static_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
P256r1PrivateKey::generate(&mut self.rng)
}
async fn generate_ephemeral_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
P256r1PrivateKey::generate(&mut self.rng)
}
}
impl<R: CryptoRng + RngCore> DhProvider<P256> for EphemeralOnly<R> {
fn dh(
&self,
key: &Self::PrivateKey,
peer: &P256r1PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
key.dh(peer)
}
}
impl<R: CryptoRng + RngCore + Send + Sync> DhProviderAsync<P256> for EphemeralOnly<R> {
async fn dh_async(
&self,
key: &Self::PrivateKey,
peer: &P256r1PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
key.dh(peer)
}
}
impl<R: CryptoRng + RngCore> SigningProvider<P256> for EphemeralOnly<R> {
fn sign(&self, key: &Self::PrivateKey, message: &[u8]) -> Result<P256Signature, Self::Error> {
key.sign(message)
}
}
impl<R: CryptoRng + RngCore + Send + Sync> SigningProviderAsync<P256> for EphemeralOnly<R> {
async fn sign_async(
&self,
key: &Self::PrivateKey,
message: &[u8],
) -> Result<P256Signature, Self::Error> {
key.sign(message)
}
}
impl<R: CryptoRng + RngCore> CryptoKeyProvider<Ed25519> for EphemeralOnly<R> {
type Error = crate::curve::ed25519::Error;
type PrivateKey = SoftwareEd25519PrivateKey;
fn public_key(&self, key: &Self::PrivateKey) -> Result<Ed25519PublicKey, Self::Error> {
Ok(key.public_key())
}
fn generate_static_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareEd25519PrivateKey::generate(&mut self.rng))
}
fn generate_ephemeral_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareEd25519PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> CryptoKeyProviderAsync<Ed25519> for EphemeralOnly<R> {
async fn generate_static_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareEd25519PrivateKey::generate(&mut self.rng))
}
async fn generate_ephemeral_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareEd25519PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore> DhProvider<Ed25519> for EphemeralOnly<R> {
fn dh(
&self,
key: &Self::PrivateKey,
peer: &Ed25519PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> DhProviderAsync<Ed25519> for EphemeralOnly<R> {
async fn dh_async(
&self,
key: &Self::PrivateKey,
peer: &Ed25519PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R: CryptoRng + RngCore> SigningProvider<Ed25519> for EphemeralOnly<R> {
fn sign(
&self,
key: &Self::PrivateKey,
message: &[u8],
) -> Result<Ed25519Signature, Self::Error> {
Ok(key.sign(message))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> SigningProviderAsync<Ed25519> for EphemeralOnly<R> {
async fn sign_async(
&self,
key: &Self::PrivateKey,
message: &[u8],
) -> Result<Ed25519Signature, Self::Error> {
Ok(key.sign(message))
}
}
impl<R: CryptoRng + RngCore> CryptoKeyProvider<X25519> for EphemeralOnly<R> {
type Error = crate::curve::x25519::Error;
type PrivateKey = SoftwareX25519PrivateKey;
fn public_key(&self, key: &Self::PrivateKey) -> Result<X25519PublicKey, Self::Error> {
Ok(key.public_key())
}
fn generate_static_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX25519PrivateKey::generate(&mut self.rng))
}
fn generate_ephemeral_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX25519PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> CryptoKeyProviderAsync<X25519> for EphemeralOnly<R> {
async fn generate_static_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX25519PrivateKey::generate(&mut self.rng))
}
async fn generate_ephemeral_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX25519PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore> DhProvider<X25519> for EphemeralOnly<R> {
fn dh(
&self,
key: &Self::PrivateKey,
peer: &X25519PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> DhProviderAsync<X25519> for EphemeralOnly<R> {
async fn dh_async(
&self,
key: &Self::PrivateKey,
peer: &X25519PublicKey,
) -> Result<SharedSecret<32>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R: CryptoRng + RngCore> CryptoKeyProvider<X448> for EphemeralOnly<R> {
type Error = crate::curve::x448::Error;
type PrivateKey = SoftwareX448PrivateKey;
fn public_key(&self, key: &Self::PrivateKey) -> Result<X448PublicKey, Self::Error> {
Ok(key.public_key())
}
fn generate_static_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX448PrivateKey::generate(&mut self.rng))
}
fn generate_ephemeral_key(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX448PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> CryptoKeyProviderAsync<X448> for EphemeralOnly<R> {
async fn generate_static_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX448PrivateKey::generate(&mut self.rng))
}
async fn generate_ephemeral_key_async(&mut self) -> Result<Self::PrivateKey, Self::Error> {
Ok(SoftwareX448PrivateKey::generate(&mut self.rng))
}
}
impl<R: CryptoRng + RngCore> DhProvider<X448> for EphemeralOnly<R> {
fn dh(
&self,
key: &Self::PrivateKey,
peer: &X448PublicKey,
) -> Result<SharedSecret<56>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R: CryptoRng + RngCore + Send + Sync> DhProviderAsync<X448> for EphemeralOnly<R> {
async fn dh_async(
&self,
key: &Self::PrivateKey,
peer: &X448PublicKey,
) -> Result<SharedSecret<56>, Self::Error> {
Ok(key.dh(peer))
}
}
impl<R> EphemeralOnly<R> {
pub fn new(rng: R) -> Self {
Self { rng }
}
}
pub trait SecretKey {
type Curve: Curve;
}
impl SecretKey for P256r1PrivateKey {
type Curve = P256;
}
impl SecretKey for SoftwareEd25519PrivateKey {
type Curve = Ed25519;
}
impl SecretKey for SoftwareX25519PrivateKey {
type Curve = X25519;
}
impl SecretKey for SoftwareX448PrivateKey {
type Curve = X448;
}
pub trait ProviderExt {
fn generate<C: Curve>(
&mut self,
) -> Result<<Self as CryptoKeyProvider<C>>::PrivateKey, <Self as CryptoKeyProvider<C>>::Error>
where
Self: CryptoKeyProvider<C>;
fn generate_ephemeral<C: Curve>(
&mut self,
) -> Result<<Self as CryptoKeyProvider<C>>::PrivateKey, <Self as CryptoKeyProvider<C>>::Error>
where
Self: CryptoKeyProvider<C>;
fn public<K: SecretKey>(
&self,
key: &K,
) -> Result<<K::Curve as Curve>::PublicKey, <Self as CryptoKeyProvider<K::Curve>>::Error>
where
Self: CryptoKeyProvider<K::Curve, PrivateKey = K>;
}
impl<P> ProviderExt for P {
fn generate<C: Curve>(
&mut self,
) -> Result<<Self as CryptoKeyProvider<C>>::PrivateKey, <Self as CryptoKeyProvider<C>>::Error>
where
Self: CryptoKeyProvider<C>,
{
<Self as CryptoKeyProvider<C>>::generate_static_key(self)
}
fn generate_ephemeral<C: Curve>(
&mut self,
) -> Result<<Self as CryptoKeyProvider<C>>::PrivateKey, <Self as CryptoKeyProvider<C>>::Error>
where
Self: CryptoKeyProvider<C>,
{
<Self as CryptoKeyProvider<C>>::generate_ephemeral_key(self)
}
fn public<K: SecretKey>(
&self,
key: &K,
) -> Result<<K::Curve as Curve>::PublicKey, <Self as CryptoKeyProvider<K::Curve>>::Error>
where
Self: CryptoKeyProvider<K::Curve, PrivateKey = K>,
{
<Self as CryptoKeyProvider<K::Curve>>::public_key(self, key)
}
}