Skip to content

Commit

Permalink
encapsulated keys and shared secrets can be represented by native type
Browse files Browse the repository at this point in the history
  • Loading branch information
incertia committed Apr 18, 2024
1 parent 5af0437 commit 27f452d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 42 deletions.
31 changes: 13 additions & 18 deletions dhkem/src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use crate::{Decapsulator, DhKem, EncapsulatedKey, Encapsulator, SharedSecret};
use elliptic_curve::ecdh::{EphemeralSecret, SharedSecret as EcdhSecret};
use crate::{Decapsulator, DhKem, Encapsulator};
use elliptic_curve::ecdh::{EphemeralSecret, SharedSecret};
use elliptic_curve::{CurveArithmetic, PublicKey};
use kem::{Decapsulate, Encapsulate};
use rand_core::CryptoRngCore;
use std::marker::PhantomData;

pub struct ArithmeticKem<C: CurveArithmetic>(PhantomData<C>);

impl<C> Encapsulate<EncapsulatedKey<PublicKey<C>>, SharedSecret<EcdhSecret<C>>>
for Encapsulator<PublicKey<C>>
impl<C> Encapsulate<PublicKey<C>, SharedSecret<C>> for Encapsulator<PublicKey<C>>
where
C: CurveArithmetic,
{
Expand All @@ -17,30 +16,26 @@ where
fn encapsulate(
&self,
rng: &mut impl CryptoRngCore,
) -> Result<(EncapsulatedKey<PublicKey<C>>, SharedSecret<EcdhSecret<C>>), Self::Error> {
) -> Result<(PublicKey<C>, SharedSecret<C>), Self::Error> {
// ECDH encapsulation involves creating a new ephemeral key pair and then doing DH
let sk = EphemeralSecret::random(rng);
let pk = sk.public_key();
let ss = sk.diffie_hellman(&self.0);

Ok((EncapsulatedKey(pk), SharedSecret(ss)))
Ok((pk, ss))
}
}

impl<C> Decapsulate<EncapsulatedKey<PublicKey<C>>, SharedSecret<EcdhSecret<C>>>
for Decapsulator<EphemeralSecret<C>>
impl<C> Decapsulate<PublicKey<C>, SharedSecret<C>> for Decapsulator<EphemeralSecret<C>>
where
C: CurveArithmetic,
{
type Error = ();

fn decapsulate(
&self,
encapsulated_key: &EncapsulatedKey<PublicKey<C>>,
) -> Result<SharedSecret<EcdhSecret<C>>, Self::Error> {
let ss = self.0.diffie_hellman(&encapsulated_key.0);
fn decapsulate(&self, encapsulated_key: &PublicKey<C>) -> Result<SharedSecret<C>, Self::Error> {
let ss = self.0.diffie_hellman(&encapsulated_key);

Ok(SharedSecret(ss))
Ok(ss)
}
}

Expand All @@ -50,8 +45,8 @@ where
{
type DecapsulatingKey = Decapsulator<EphemeralSecret<C>>;
type EncapsulatingKey = Encapsulator<PublicKey<C>>;
type EncapsulatedKey = EncapsulatedKey<PublicKey<C>>;
type SharedSecret = SharedSecret<EcdhSecret<C>>;
type EncapsulatedKey = PublicKey<C>;
type SharedSecret = SharedSecret<C>;

fn random_keypair(
rng: &mut impl CryptoRngCore,
Expand All @@ -64,11 +59,11 @@ where
}

#[cfg(test)]
impl<C> crate::SecretBytes for SharedSecret<EcdhSecret<C>>
impl<C> crate::SecretBytes for SharedSecret<C>
where
C: CurveArithmetic,
{
fn as_slice(&self) -> &[u8] {
self.0.raw_secret_bytes().as_slice()
self.raw_secret_bytes().as_slice()
}
}
4 changes: 0 additions & 4 deletions dhkem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ use rand_core::CryptoRngCore;
pub struct Encapsulator<X>(X);
/// Newtype for a piece of data that may be decapsulated
pub struct Decapsulator<X>(X);
/// Newtype for a shared secret
pub struct SharedSecret<X>(X);
/// Newtype for an encapsulated key
pub struct EncapsulatedKey<X>(X);

#[cfg(test)]
pub trait SecretBytes {
Expand Down
33 changes: 13 additions & 20 deletions dhkem/src/x25519_kem.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,41 @@
use crate::{Decapsulator, DhKem, EncapsulatedKey, Encapsulator, SharedSecret};
use crate::{Decapsulator, DhKem, Encapsulator};
use kem::{Decapsulate, Encapsulate};
use rand_core::CryptoRngCore;
use x25519::{PublicKey, ReusableSecret, SharedSecret as X25519Secret};
use x25519::{PublicKey, ReusableSecret, SharedSecret};

pub struct X25519;

impl Encapsulate<EncapsulatedKey<PublicKey>, SharedSecret<X25519Secret>>
for Encapsulator<PublicKey>
{
impl Encapsulate<PublicKey, SharedSecret> for Encapsulator<PublicKey> {
type Error = ();

fn encapsulate(
&self,
rng: &mut impl CryptoRngCore,
) -> Result<(EncapsulatedKey<PublicKey>, SharedSecret<X25519Secret>), Self::Error> {
) -> Result<(PublicKey, SharedSecret), Self::Error> {
// ECDH encapsulation involves creating a new ephemeral key pair and then doing DH
let sk = ReusableSecret::random_from_rng(rng);
let pk = PublicKey::from(&sk);
let ss = sk.diffie_hellman(&self.0);

Ok((EncapsulatedKey(pk), SharedSecret(ss)))
Ok((pk, ss))
}
}

impl Decapsulate<EncapsulatedKey<PublicKey>, SharedSecret<X25519Secret>>
for Decapsulator<ReusableSecret>
{
impl Decapsulate<PublicKey, SharedSecret> for Decapsulator<ReusableSecret> {
type Error = ();

fn decapsulate(
&self,
encapsulated_key: &EncapsulatedKey<PublicKey>,
) -> Result<SharedSecret<X25519Secret>, Self::Error> {
let ss = self.0.diffie_hellman(&encapsulated_key.0);
fn decapsulate(&self, encapsulated_key: &PublicKey) -> Result<SharedSecret, Self::Error> {
let ss = self.0.diffie_hellman(&encapsulated_key);

Ok(SharedSecret(ss))
Ok(ss)
}
}

impl DhKem for X25519 {
type DecapsulatingKey = Decapsulator<ReusableSecret>;
type EncapsulatingKey = Encapsulator<PublicKey>;
type EncapsulatedKey = EncapsulatedKey<PublicKey>;
type SharedSecret = SharedSecret<X25519Secret>;
type EncapsulatedKey = PublicKey;
type SharedSecret = SharedSecret;

fn random_keypair(
rng: &mut impl CryptoRngCore,
Expand All @@ -55,8 +48,8 @@ impl DhKem for X25519 {
}

#[cfg(test)]
impl crate::SecretBytes for SharedSecret<X25519Secret> {
impl crate::SecretBytes for SharedSecret {
fn as_slice(&self) -> &[u8] {
self.0.as_bytes().as_slice()
self.as_bytes().as_slice()
}
}

0 comments on commit 27f452d

Please sign in to comment.