pub mod auth;
pub mod enc;
pub mod key;
pub mod markers;
#[cfg(not(any(feature = "ECIES-MAC", feature = "ECIES-AEAD", feature = "ECIES-SYN")))]
compile_error!(
"At least one variant feature must be activated: 'ECIES-MAC', 'ECIES_AEAD', or 'ECIES-SYN'"
);
#[cfg(feature = "ECIES-MAC")]
use auth::generics::{Mac, TakeMac, TakeMacKey};
#[cfg(feature = "ECIES-MAC")]
use markers::{EciesMacDecryptionSupport, EciesMacEncryptionSupport};
#[cfg(feature = "ECIES-AEAD")]
use auth::Aead;
#[cfg(feature = "ECIES-AEAD")]
use markers::{EciesAeadDecryptionSupport, EciesAeadEncryptionSupport};
#[cfg(feature = "ECIES-SYN")]
use auth::Syn;
#[cfg(feature = "ECIES-SYN")]
use markers::{EciesSynDecryptionSupport, EciesSynEncryptionSupport};
#[cfg(any(feature = "ECIES-MAC", feature = "ECIES-AEAD"))]
use enc::generics::GenerateNonce;
#[cfg(any(feature = "ECIES-MAC", feature = "ECIES-AEAD", feature = "ECIES-SYN"))]
use enc::generics::{Encryption, TakeEncryptionKey, TakeNonce};
#[cfg(any(feature = "ECIES-MAC", feature = "ECIES-AEAD", feature = "ECIES-SYN"))]
use key::conversion::IntoSecretKeyRef;
#[cfg(any(feature = "ECIES-MAC", feature = "ECIES-AEAD", feature = "ECIES-SYN"))]
use key::generics::{DeriveKeyMaterial, GenerateEphemeralKey, KeyExchange, TakeEphemeralKey};
use key::conversion::{IntoPublicKey, TryIntoPublicKey};
use key::generics::Key;
use std::marker::PhantomData;
#[derive(Debug)]
pub enum EciesError {
BadData,
VerificationError,
EncryptionError,
DecryptionError,
}
#[derive(Debug)]
pub enum KeyError {
BadData,
}
pub struct Ecies<K, E, A> {
recipient_pk: K,
k: PhantomData<K>,
e: PhantomData<E>,
a: PhantomData<A>,
}
impl<K: Key, E, A> Ecies<K, E, A> {
pub fn new<T: IntoPublicKey<K>>(recipient_public_key: T) -> Self {
Self {
recipient_pk: recipient_public_key.into_pk(),
k: PhantomData,
e: PhantomData,
a: PhantomData,
}
}
pub fn try_new<T: TryIntoPublicKey<K>>(recipient_public_key: T) -> Result<Self, KeyError> {
Ok(Self::new(recipient_public_key.try_into_pk()?))
}
}
#[cfg(feature = "ECIES-MAC")]
impl<K, E, A> Ecies<K, E, A>
where
K: EciesMacEncryptionSupport + Key + GenerateEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesMacEncryptionSupport + Encryption + GenerateNonce + TakeEncryptionKey,
A: Mac + TakeMacKey,
{
pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, EciesError> {
let (ephemeral_pk, ephemeral_sk) = K::get_ephemeral_key();
let nonce = E::get_nonce();
let shared_secret = K::key_exchange(&self.recipient_pk, &ephemeral_sk);
let mut derived_key = K::derive_key_material(
&ephemeral_pk,
shared_secret,
E::ENCRYPTION_KEY_LEN + A::MAC_KEY_LEN,
);
let enc_key = E::get_encryption_key(&mut derived_key)?;
let mac_key = A::get_mac_key(&mut derived_key)?;
let ciphertext = E::encrypt(&enc_key, &nonce, plaintext)?;
let mac = A::digest(&mac_key, &nonce, &ciphertext)?;
let mut out = Vec::new();
out.extend_from_slice(&ephemeral_pk.as_bytes());
out.extend_from_slice(nonce.as_slice());
out.extend_from_slice(mac.as_slice());
out.extend_from_slice(ciphertext.as_slice());
Ok(out)
}
}
#[cfg(feature = "ECIES-MAC")]
impl<K, E, A> Ecies<K, E, A>
where
K: EciesMacDecryptionSupport + Key + TakeEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesMacDecryptionSupport + Encryption + TakeNonce + TakeEncryptionKey,
A: Mac + TakeMac,
{
pub fn decrypt<T: IntoSecretKeyRef<K>>(
recipient_secret_key: &T,
ciphertext: &[u8],
) -> Result<Vec<u8>, EciesError> {
let mut ciphertext = ciphertext.to_vec();
let ephemeral_pk = K::get_ephemeral_key(&mut ciphertext)?;
let nonce = E::get_nonce(&mut ciphertext)?;
let mac = A::get_mac(&mut ciphertext)?;
let shared_secret = K::key_exchange(&ephemeral_pk, recipient_secret_key.into_sk_ref());
let mut derived_key = K::derive_key_material(
&ephemeral_pk,
shared_secret,
E::ENCRYPTION_KEY_LEN + A::MAC_KEY_LEN,
);
let enc_key = E::get_encryption_key(&mut derived_key)?;
let mac_key = A::get_mac_key(&mut derived_key)?;
A::verify(&mac_key, &nonce, &ciphertext, &mac)?;
E::decrypt(&enc_key, &nonce, &ciphertext)
}
}
#[cfg(feature = "ECIES-AEAD")]
impl<K, E> Ecies<K, E, Aead>
where
K: EciesAeadEncryptionSupport + Key + GenerateEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesAeadEncryptionSupport + Encryption + GenerateNonce + TakeEncryptionKey,
{
pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, EciesError> {
let (ephemeral_pk, ephemeral_sk) = K::get_ephemeral_key();
let nonce = E::get_nonce();
let shared_secret = K::key_exchange(&self.recipient_pk, &ephemeral_sk);
let mut derived_key =
K::derive_key_material(&ephemeral_pk, shared_secret, E::ENCRYPTION_KEY_LEN);
let enc_key = E::get_encryption_key(&mut derived_key)?;
let ciphertext = E::encrypt(&enc_key, &nonce, plaintext)?;
let mut out = Vec::new();
out.extend_from_slice(&ephemeral_pk.as_bytes());
out.extend_from_slice(nonce.as_slice());
out.extend_from_slice(ciphertext.as_slice());
Ok(out)
}
}
#[cfg(feature = "ECIES-AEAD")]
impl<K, E> Ecies<K, E, Aead>
where
K: EciesAeadDecryptionSupport + Key + TakeEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesAeadDecryptionSupport + Encryption + TakeNonce + TakeEncryptionKey,
{
pub fn decrypt<T: IntoSecretKeyRef<K>>(
recipient_secret_key: &T,
ciphertext: &[u8],
) -> Result<Vec<u8>, EciesError> {
let mut ciphertext = ciphertext.to_vec();
let ephemeral_pk = K::get_ephemeral_key(&mut ciphertext)?;
let nonce = E::get_nonce(&mut ciphertext)?;
let shared_secret = K::key_exchange(&ephemeral_pk, recipient_secret_key.into_sk_ref());
let mut derived_key =
K::derive_key_material(&ephemeral_pk, shared_secret, E::ENCRYPTION_KEY_LEN);
let enc_key = E::get_encryption_key(&mut derived_key)?;
E::decrypt(&enc_key, &nonce, &ciphertext)
}
}
#[cfg(feature = "ECIES-SYN")]
impl<K, E> Ecies<K, E, Syn>
where
K: EciesSynEncryptionSupport + Key + GenerateEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesSynEncryptionSupport + Encryption + TakeNonce + TakeEncryptionKey,
{
pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, EciesError> {
let (ephemeral_pk, ephemeral_sk) = K::get_ephemeral_key();
let shared_secret = K::key_exchange(&self.recipient_pk, &ephemeral_sk);
let mut derived_key = K::derive_key_material(
&ephemeral_pk,
shared_secret,
E::ENCRYPTION_KEY_LEN + E::ENCRYPTION_NONCE_LEN,
);
let enc_key = E::get_encryption_key(&mut derived_key)?;
let nonce = E::get_nonce(&mut derived_key)?;
let ciphertext = E::encrypt(&enc_key, &nonce, plaintext)?;
let mut out = Vec::new();
out.extend_from_slice(&ephemeral_pk.as_bytes());
out.extend_from_slice(ciphertext.as_slice());
Ok(out)
}
}
#[cfg(feature = "ECIES-SYN")]
impl<K, E> Ecies<K, E, Syn>
where
K: EciesSynDecryptionSupport + Key + TakeEphemeralKey + KeyExchange + DeriveKeyMaterial,
E: EciesSynDecryptionSupport + Encryption + TakeNonce + TakeEncryptionKey,
{
pub fn decrypt<T: IntoSecretKeyRef<K>>(
recipient_secret_key: &T,
ciphertext: &[u8],
) -> Result<Vec<u8>, EciesError> {
let mut ciphertext = ciphertext.to_vec();
let ephemeral_pk = K::get_ephemeral_key(&mut ciphertext)?;
let shared_secret = K::key_exchange(&ephemeral_pk, recipient_secret_key.into_sk_ref());
let mut derived_key = K::derive_key_material(
&ephemeral_pk,
shared_secret,
E::ENCRYPTION_KEY_LEN + E::ENCRYPTION_NONCE_LEN,
);
let enc_key = E::get_encryption_key(&mut derived_key)?;
let nonce = E::get_nonce(&mut derived_key)?;
E::decrypt(&enc_key, &nonce, &ciphertext)
}
}