#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(missing_docs, unused_qualifications, missing_debug_implementations)]
#![cfg_attr(feature = "getrandom", doc = "```")]
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
pub use common::{
self, Generate, InvalidKey, Key, KeyExport, KeyInit, KeySizeUser, TryKeyInit, typenum::consts,
};
use common::array::{self, ArraySize};
use core::fmt::Debug;
use core::{array::TryFromSliceError, convert::Infallible};
use rand_core::CryptoRng;
#[cfg(feature = "getrandom")]
use common::getrandom::{SysRng, rand_core::UnwrapErr};
pub type Seed<K> = array::Array<u8, <K as FromSeed>::SeedSize>;
pub type DecapsulationKey<K> = <K as Kem>::DecapsulationKey;
pub type EncapsulationKey<K> = <K as Kem>::EncapsulationKey;
pub type SharedKey<K> = array::Array<u8, <K as Kem>::SharedKeySize>;
pub type Ciphertext<K> = array::Array<u8, <K as Kem>::CiphertextSize>;
pub trait Kem: Copy + Clone + Debug + Default + Eq + Ord + Send + Sync + 'static {
type DecapsulationKey: TryDecapsulate<Kem = Self> + Generate;
type EncapsulationKey: Encapsulate<Kem = Self> + Clone + Debug + Eq;
type SharedKeySize: ArraySize;
type CiphertextSize: ArraySize;
fn generate_keypair_from_rng<R: CryptoRng>(
rng: &mut R,
) -> (DecapsulationKey<Self>, EncapsulationKey<Self>) {
let dk = DecapsulationKey::<Self>::generate_from_rng(rng);
let ek = dk.encapsulation_key().clone();
(dk, ek)
}
#[cfg(feature = "getrandom")]
fn generate_keypair() -> (DecapsulationKey<Self>, EncapsulationKey<Self>) {
Self::generate_keypair_from_rng(&mut UnwrapErr(SysRng))
}
}
pub trait FromSeed: Kem {
type SeedSize: ArraySize;
fn from_seed(seed: &Seed<Self>) -> (DecapsulationKey<Self>, EncapsulationKey<Self>);
}
impl<K> FromSeed for K
where
K: Kem,
K::DecapsulationKey: KeyInit,
{
type SeedSize = <K::DecapsulationKey as KeySizeUser>::KeySize;
fn from_seed(seed: &Seed<Self>) -> (DecapsulationKey<Self>, EncapsulationKey<Self>) {
let dk = DecapsulationKey::<Self>::new(seed);
let ek = dk.encapsulation_key().clone();
(dk, ek)
}
}
pub trait Decapsulator {
type Kem: Kem;
fn encapsulation_key(&self) -> &EncapsulationKey<Self::Kem>;
}
pub trait Decapsulate: TryDecapsulate<Error = Infallible> {
fn decapsulate(&self, ct: &Ciphertext<Self::Kem>) -> SharedKey<Self::Kem>;
fn decapsulate_slice(&self, ct: &[u8]) -> Result<SharedKey<Self::Kem>, TryFromSliceError> {
ct.try_into().map(|ct| self.decapsulate(&ct))
}
}
pub trait TryDecapsulate: Decapsulator {
type Error: core::error::Error;
fn try_decapsulate(
&self,
ct: &Ciphertext<Self::Kem>,
) -> Result<SharedKey<Self::Kem>, Self::Error>;
fn try_decapsulate_slice(&self, ct: &[u8]) -> Result<SharedKey<Self::Kem>, Self::Error>
where
Self::Error: From<TryFromSliceError>,
{
self.try_decapsulate(ct.try_into()?)
}
}
impl<D> TryDecapsulate for D
where
D: Decapsulate + Decapsulator,
{
type Error = Infallible;
fn try_decapsulate(
&self,
ct: &Ciphertext<Self::Kem>,
) -> Result<SharedKey<Self::Kem>, Infallible> {
Ok(self.decapsulate(ct))
}
}
pub trait Encapsulate: TryKeyInit + KeyExport {
type Kem: Kem;
fn encapsulate_with_rng<R>(&self, rng: &mut R) -> (Ciphertext<Self::Kem>, SharedKey<Self::Kem>)
where
R: CryptoRng + ?Sized;
#[cfg(feature = "getrandom")]
fn encapsulate(&self) -> (Ciphertext<Self::Kem>, SharedKey<Self::Kem>) {
self.encapsulate_with_rng(&mut UnwrapErr(SysRng))
}
}