Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions kem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ pub trait Encapsulate<EK, SS> {

/// Encapsulates a fresh shared secret
fn encapsulate(&self, rng: &mut impl CryptoRngCore) -> Result<(EK, SS), Self::Error>;

/// Encapsulates a fresh shared secret, placing the encapsulated key into the given mut ref.
/// If this errors, the final value of `encapsulated_key` MUST equal its original value.
fn encapsulate_in_place(
&self,
rng: &mut impl CryptoRngCore,
encapsulated_key: &mut EK,
) -> Result<SS, Self::Error>;
}

/// A value that can be used to decapsulate an encapsulated key. Often, this will just be a secret
Expand Down
12 changes: 11 additions & 1 deletion kem/tests/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ impl Encapsulate<EncappedKey, SharedSecret> for PublicKey {
&self,
mut csprng: &mut impl CryptoRngCore,
) -> Result<(EncappedKey, SharedSecret), HpkeError> {
<X25519HkdfSha256 as KemTrait>::encap(&self.0, None, &mut csprng).map(|(ek, ss)| (ss, ek))
<X25519HkdfSha256 as KemTrait>::encap(&self.0, None, &mut csprng).map(|(ss, ek)| (ek, ss))
}

fn encapsulate_in_place(
&self,
csprng: &mut impl CryptoRngCore,
encapsulated_key: &mut EncappedKey,
) -> Result<SharedSecret, HpkeError> {
let (ek, ss) = self.encapsulate(csprng)?;
*encapsulated_key = ek;
Ok(ss)
}
}

Expand Down
22 changes: 16 additions & 6 deletions kem/tests/saber.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use kem::{Decapsulate, Encapsulate};

use core::convert::Infallible;

use pqcrypto::kem::firesaber::{
decapsulate, encapsulate, keypair, Ciphertext as SaberEncappedKey, PublicKey, SecretKey,
SharedSecret as SaberSharedSecret,
Expand All @@ -12,23 +14,31 @@ struct SaberPublicKey(PublicKey);
struct SaberPrivateKey(SecretKey);

impl Encapsulate<SaberEncappedKey, SaberSharedSecret> for SaberPublicKey {
// TODO: Encapsulation is infallible. Make this the never type once it's available
type Error = ();
type Error = Infallible;

fn encapsulate(
&self,
_: &mut impl CryptoRngCore,
) -> Result<(SaberEncappedKey, SaberSharedSecret), ()> {
) -> Result<(SaberEncappedKey, SaberSharedSecret), Infallible> {
let (ss, ek) = encapsulate(&self.0);
Ok((ek, ss))
}

fn encapsulate_in_place(
&self,
csprng: &mut impl CryptoRngCore,
encapsulated_key: &mut SaberEncappedKey,
) -> Result<SaberSharedSecret, Infallible> {
let (ek, ss) = self.encapsulate(csprng)?;
*encapsulated_key = ek;
Ok(ss)
}
}

impl Decapsulate<SaberEncappedKey, SaberSharedSecret> for SaberPrivateKey {
// TODO: Decapsulation is infallible. Make this the never type once it's available
type Error = ();
type Error = Infallible;

fn decapsulate(&self, ek: &SaberEncappedKey) -> Result<SaberSharedSecret, ()> {
fn decapsulate(&self, ek: &SaberEncappedKey) -> Result<SaberSharedSecret, Infallible> {
Ok(decapsulate(ek, &self.0))
}
}
Expand Down
10 changes: 10 additions & 0 deletions kem/tests/x3dh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ impl Encapsulate<EphemeralKey, SharedSecret> for EncapContext {

Ok((ek, shared_secret))
}

fn encapsulate_in_place(
&self,
rng: &mut impl CryptoRngCore,
encapsulated_key: &mut EphemeralKey,
) -> Result<SharedSecret, Self::Error> {
let (ek, ss) = self.encapsulate(rng)?;
*encapsulated_key = ek;
Ok(ss)
}
}

// Define an decapsulator. Since authenticated and unauthenticated encapped keys are represented by
Expand Down