use subtle::ConstantTimeEq;
use thiserror::Error;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Debug, Error)]
pub enum KEMError {
#[error("Key generation failed")]
KeyGenerationError,
#[error("Encapsulation failed")]
EncapsulationError,
#[error("Decapsulation failed")]
DecapsulationError,
#[error("Invalid length")]
InvalidLength,
#[error("Invalid key format")]
InvalidKey,
#[error("Internal error")]
InternalError,
}
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub struct PublicKey(Vec<u8>);
impl PublicKey {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
Ok(Self(bytes.to_vec()))
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0.ct_eq(&other.0).into()
}
}
impl Eq for PublicKey {}
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub struct SecretKey(Vec<u8>);
impl SecretKey {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
Ok(Self(bytes.to_vec()))
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for SecretKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl PartialEq for SecretKey {
fn eq(&self, other: &Self) -> bool {
self.0.ct_eq(&other.0).into()
}
}
impl Eq for SecretKey {}
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub struct Ciphertext(Vec<u8>);
impl Ciphertext {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
Ok(Self(bytes.to_vec()))
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for Ciphertext {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl PartialEq for Ciphertext {
fn eq(&self, other: &Self) -> bool {
self.0.ct_eq(&other.0).into()
}
}
impl Eq for Ciphertext {}
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub struct SharedSecret(Vec<u8>);
impl SharedSecret {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
Ok(Self(bytes.to_vec()))
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for SharedSecret {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl PartialEq for SharedSecret {
fn eq(&self, other: &Self) -> bool {
self.0.ct_eq(&other.0).into()
}
}
impl Eq for SharedSecret {}
pub trait KeyEncapsulation {
fn keygen() -> Result<(PublicKey, SecretKey), KEMError>;
fn encapsulate(public_key: &PublicKey) -> Result<(Ciphertext, SharedSecret), KEMError>;
fn decapsulate(
secret_key: &SecretKey,
ciphertext: &Ciphertext,
) -> Result<SharedSecret, KEMError>;
}
#[derive(Debug, ZeroizeOnDrop)]
pub struct KeyPair {
pub public_key: Vec<u8>,
pub secret_key: Vec<u8>,
}
impl Default for KeyPair {
fn default() -> Self {
Self::new()
}
}
impl KeyPair {
pub fn new() -> Self {
Self {
public_key: vec![0u8; 32], secret_key: vec![0u8; 32], }
}
pub fn public_key(&self) -> &[u8] {
&self.public_key
}
pub fn secret_key(&self) -> &[u8] {
&self.secret_key
}
}