Skip to content

Commit

Permalink
kem: simplify API (#1509)
Browse files Browse the repository at this point in the history
* Simplified API significantly; updated HPKE test

* Updated all the tests

* Deleted cruft; Updated docs

* Removed std feature

* Made clippy happy

* kem: Made rng input a mut ref; made Error assoc type impl Debug
  • Loading branch information
rozbb authored Apr 2, 2024
1 parent 84b4dc1 commit 59c34d2
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 439 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 19 additions & 19 deletions kem/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
[package]
name = "kem"
description = "Traits for key encapsulation mechanisms"
version = "0.3.0-pre"
authors = ["RustCrypto Developers"]
license = "Apache-2.0 OR MIT"
name = "kem"
description = "Traits for key encapsulation mechanisms"
version = "0.3.0-pre"
authors = ["RustCrypto Developers"]
license = "Apache-2.0 OR MIT"
documentation = "https://docs.rs/kem"
repository = "https://github.com/RustCrypto/traits/tree/master/kem"
readme = "README.md"
edition = "2021"
keywords = ["crypto"]
categories = ["cryptography", "no-std"]
rust-version = "1.66"
repository = "https://github.com/RustCrypto/traits/tree/master/kem"
readme = "README.md"
edition = "2021"
keywords = ["crypto"]
categories = ["cryptography", "no-std"]
rust-version = "1.66"

[dependencies]
rand_core = "0.6"
generic-array = "0.14"
zeroize = { version = "1.7", default-features = false }

[dev-dependencies]
hpke = "0.10"
p256 = { version = "0.9", features = [ "ecdsa" ] }
pqcrypto = { version = "0.15", default-features = false, features = [ "pqcrypto-saber" ] }
p256 = { version = "0.9", features = ["ecdsa"] }
pqcrypto = { version = "0.15", default-features = false, features = [
"pqcrypto-saber",
] }
pqcrypto-traits = "0.3"
rand = { version = "0.8", features = [ "getrandom" ] }
rand = { version = "0.8" }
x3dh-ke = "0.1"

[features]
default = []
std = []

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[lib]
doctest = false
61 changes: 60 additions & 1 deletion kem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,66 @@

This crate provides a common set of traits for [key encapsulation mechanisms][1]—algorithms for non-interactively establishing secrets between peers. This is intended to be implemented by libraries which produce or contain implementations of key encapsulation mechanisms, and used by libraries which want to produce or consume encapsulated secrets while generically supporting any compatible backend.

The crate exposes four traits, `Encapsulator`, `Decapsulator`, `AuthEncapsulator`, and `AuthDecapsulator`. These traits represent the ability to initiate a key exchange and complete a key exchange, in the case where the sender is authenticated to the receiver and in the case where the sender is not.
The crate exposes two traits, `Encapsulate` and `Decapsulate`, which are both generic over the encapsulated key type and the shared secret type. They are also agnostic about the structure of `Self`. For example, a simple Saber implementation may just impl `Encapsulate` for a single public key:
```rust
// Must make a newtype to implement the trait
struct MyPubkey(SaberPublicKey);

impl Encapsulate<SaberEncappedKey, SaberSharedSecret> for MyPubkey {
// Encapsulation is infallible
type Error = !;

fn encapsulate(
&self,
csprng: impl CryptoRngCore,
) -> Result<(SaberEncappedKey, SaberSharedSecret), !> {
let (ss, ek) = saber_encapsulate(&csprng, &self.0);
Ok((ek, ss))
}
}
```
And on the other end of complexity, an [X3DH](https://www.signal.org/docs/specifications/x3dh/) implementation might impl `Encapsulate` for a public key bundle plus a sender identity key:
```rust
struct PubkeyBundle {
ik: IdentityPubkey,
spk: SignedPrePubkey,
sig: Signature,
opk: OneTimePrePubkey,
}

// Encap context is the recipient's pubkeys and the sender's identity key
struct EncapContext(PubkeyBundle, IdentityPrivkey);

impl Encapsulate<EphemeralKey, SharedSecret> for EncapContext {
// Encapsulation fails if signature verification fails
type Error = SigError;

fn encapsulate(
&self,
csprng: impl CryptoRngCore,
) -> Result<(EphemeralKey, SharedSecret), Self::Error> {
// Make a new ephemeral key. This will be the encapped key
let ek = EphemeralKey::gen(&mut csprng);

// Deconstruct the recipient's pubkey bundle
let PubkeyBundle {
ref ik,
ref spk,
ref sig,
ref opk,
} = self.0;
let my_ik = &self.1;

// Verify the signature
self.0.verify(&sig, &some_sig_pubkey)?;

// Do the X3DH operation to get the shared secret
let shared_secret = x3dh_a(sig, my_ik, spk, &ek, ik, opk)?;

Ok((ek, shared_secret))
}
}
```

[Documentation][docs-link]

Expand Down
17 changes: 0 additions & 17 deletions kem/src/errors.rs

This file was deleted.

100 changes: 0 additions & 100 deletions kem/src/kem.rs

This file was deleted.

28 changes: 22 additions & 6 deletions kem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,27 @@
#![forbid(unsafe_code)]
#![warn(missing_docs, unused_qualifications, missing_debug_implementations)]

#[cfg(feature = "std")]
extern crate std;
use core::fmt::Debug;
use rand_core::CryptoRngCore;

mod errors;
mod kem;
/// A value that can be encapsulated to. Often, this will just be a public key. However, it can
/// also be a bundle of public keys, or it can include a sender's private key for authenticated
/// encapsulation.
pub trait Encapsulate<EK, SS> {
/// Encapsulation error
type Error: Debug;

pub use crate::{errors::*, kem::*};
pub use generic_array;
/// Encapsulates a fresh shared secret
fn encapsulate(&self, rng: &mut impl CryptoRngCore) -> Result<(EK, SS), Self::Error>;
}

/// A value that can be used to decapsulate an encapsulated key. Often, this will just be a secret
/// key. But, as with [`Encapsulate`], it can be a bundle of secret keys, or it can include a
/// sender's private key for authenticated encapsulation.
pub trait Decapsulate<EK, SS> {
/// Decapsulation error
type Error: Debug;

/// Decapsulates the given encapsulated key
fn decapsulate(&self, encapsulated_key: &EK) -> Result<SS, Self::Error>;
}
Loading

0 comments on commit 59c34d2

Please sign in to comment.