use crate::algorithms::asymmetric::kem::KemAlgorithm;
use crate::dispatch_kem;
use crate::error::Error;
use crate::impl_typed_asymmetric_private_key;
use crate::impl_typed_asymmetric_public_key;
use crate::keys::asymmetric::TypedAsymmetricKeyTrait;
use crate::keys::asymmetric::{AsymmetricPrivateKey, AsymmetricPublicKey};
use seal_crypto::prelude::{Key, KeyGenerator};
use seal_crypto::zeroize::Zeroizing;
use serde::{Deserialize, Serialize};
#[cfg(all(feature = "kdf", feature = "aead"))]
use crate::{
algorithms::kdf::key::KdfKeyAlgorithm,
prelude::{AeadAlgorithm, TypedAeadKey},
};
#[cfg(all(feature = "xof", feature = "aead"))]
use crate::wrappers::xof::XofReaderWrapper;
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, bincode::Encode, bincode::Decode)]
pub struct TypedKemKeyPair {
pub(crate) public_key: TypedKemPublicKey,
pub(crate) private_key: TypedKemPrivateKey,
}
impl TypedKemKeyPair {
pub fn generate(algorithm: KemAlgorithm) -> Result<Self, Error> {
macro_rules! generate_keypair {
($key_type:ty, $alg_enum:expr) => {
<$key_type>::generate_keypair()
.map_err(Error::from)
.and_then(|(pk, sk)| {
Ok(Self {
public_key: TypedKemPublicKey {
key: AsymmetricPublicKey::new(pk.to_bytes()?),
algorithm: $alg_enum,
},
private_key: TypedKemPrivateKey {
key: AsymmetricPrivateKey::new(sk.to_bytes()?),
algorithm: $alg_enum,
},
})
})
};
}
dispatch_kem!(algorithm, generate_keypair)
}
pub fn into_keypair(self) -> (TypedKemPublicKey, TypedKemPrivateKey) {
(self.public_key, self.private_key)
}
pub fn public_key(&self) -> &TypedKemPublicKey {
&self.public_key
}
pub fn private_key(&self) -> &TypedKemPrivateKey {
&self.private_key
}
pub fn algorithm(&self) -> KemAlgorithm {
self.public_key.algorithm
}
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, bincode::Encode, bincode::Decode)]
pub struct TypedKemPublicKey {
pub(crate) key: AsymmetricPublicKey,
pub(crate) algorithm: KemAlgorithm,
}
impl_typed_asymmetric_public_key!(TypedKemPublicKey, KemAlgorithm);
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, bincode::Encode, bincode::Decode)]
pub struct TypedKemPrivateKey {
pub(crate) key: AsymmetricPrivateKey,
pub(crate) algorithm: KemAlgorithm,
}
impl_typed_asymmetric_private_key!(TypedKemPrivateKey, KemAlgorithm);
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct SharedSecret(pub Zeroizing<Vec<u8>>);
impl bincode::Encode for SharedSecret {
fn encode<E: bincode::enc::Encoder>(
&self,
encoder: &mut E,
) -> Result<(), bincode::error::EncodeError> {
let bytes = self.0.as_slice();
bincode::Encode::encode(bytes, encoder)?;
Ok(())
}
}
impl<Context> bincode::Decode<Context> for SharedSecret {
fn decode<D: bincode::de::Decoder<Context = Context>>(
decoder: &mut D,
) -> Result<Self, bincode::error::DecodeError> {
let bytes = bincode::Decode::decode(decoder)?;
Ok(Self(Zeroizing::new(bytes)))
}
}
impl<'de, Context> bincode::BorrowDecode<'de, Context> for SharedSecret {
fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
decoder: &mut D,
) -> Result<Self, bincode::error::DecodeError> {
let bytes = bincode::BorrowDecode::borrow_decode(decoder)?;
Ok(Self(Zeroizing::new(bytes)))
}
}
impl SharedSecret {
#[cfg(all(feature = "kdf", feature = "aead"))]
pub fn derive_key(
&self,
kdf_algorithm: KdfKeyAlgorithm,
salt: Option<&[u8]>,
info: Option<&[u8]>,
algorithm: AeadAlgorithm,
) -> Result<TypedAeadKey, Error> {
use crate::traits::KdfKeyAlgorithmTrait;
let derived_key_bytes = kdf_algorithm.into_wrapper().derive(
self.0.as_ref(),
salt,
info,
algorithm.into_wrapper().key_size(),
)?;
TypedAeadKey::from_bytes(derived_key_bytes.as_slice(), algorithm)
}
#[cfg(all(feature = "xof", feature = "aead"))]
pub fn derive_key_from_xof(
&self,
xof_reader: &mut XofReaderWrapper,
algorithm: AeadAlgorithm,
) -> Result<TypedAeadKey, Error> {
let mut derived_key_bytes = vec![0u8; algorithm.into_wrapper().key_size()];
xof_reader.read(&mut derived_key_bytes);
TypedAeadKey::from_bytes(derived_key_bytes.as_slice(), algorithm)
}
pub fn into_bytes(self) -> Zeroizing<Vec<u8>> {
self.0
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_ref()
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_vec()
}
}
impl AsRef<[u8]> for SharedSecret {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl std::ops::Deref for SharedSecret {
type Target = Zeroizing<Vec<u8>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for SharedSecret {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, bincode::Encode, bincode::Decode)]
pub struct EncapsulatedKey {
pub(crate) key: Vec<u8>,
pub(crate) algorithm: KemAlgorithm,
}
impl EncapsulatedKey {
pub fn to_bytes(&self) -> Vec<u8> {
self.key.clone()
}
pub fn as_bytes(&self) -> &[u8] {
self.key.as_ref()
}
pub fn into_bytes(self) -> Vec<u8> {
self.key
}
}
impl AsRef<[u8]> for EncapsulatedKey {
fn as_ref(&self) -> &[u8] {
self.key.as_ref()
}
}
impl TypedAsymmetricKeyTrait for EncapsulatedKey {
type Algorithm = KemAlgorithm;
fn algorithm(&self) -> Self::Algorithm {
self.algorithm
}
}