Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
27 changes: 11 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,20 @@ base-mode-seal = []
serde = ["serde_crate"]
algo-all = ["aead-all", "kdf-all", "kem-all"]
default = ["algo-all", "base-mode-seal", "base-mode-open"]
aead-all = ["aead-aes-gcm-128", "aead-aes-gcm-256", "aead-chacha-20-poly-1305"]
aead-aes-gcm-128 = []
aead-aes-gcm-256 = []
aead-chacha-20-poly-1305 = []
kdf-all = ["kdf-sha256", "kdf-sha384", "kdf-sha512"]
kdf-sha256 = []
kdf-sha384 = []
kdf-sha512 = []
kem-all = ["kem-dh-p256-hkdf-sha256", "kem-dh-p384-hkdf-sha384", "kem-dh-p521-hkdf-sha512", "kem-x25519-hkdf-sha256"]
kem-dh-p256-hkdf-sha256 = ["hpke/p256"]
kem-dh-p384-hkdf-sha384 = ["hpke/p384"]
kem-dh-p521-hkdf-sha512 = ["hpke/p521"]
kem-x25519-hkdf-sha256 = ["hpke/x25519"]
aead-all = ["aead-aes", "aead-chacha"]
aead-aes = ["hpke/aes"]
aead-chacha = ["hpke/chacha"]
kdf-all = ["kdf-hkdfsha2", "kdf-shake"]
kdf-hkdfsha2 = ["hpke/hkdfsha2"]
kdf-shake = ["hpke/shake"]
kem-all = ["kem-x25519", "kem-nistp", "kem-mlkem"]
kem-x25519 = ["hpke/x25519"]
kem-nistp = ["hpke/nistp"]
kem-mlkem = ["hpke/mlkem"]

[dependencies]
rand = "0.9.2"
num_enum = "0.7.0"
cfg-if = "1.0.0"
hpke = { version = "0.13.0", default-features = false, features = ["std"] }
Comment thread
rozbb marked this conversation as resolved.
hpke = { version = "0.14", default-features = false, features = ["getrandom", "alloc"] }
zeroize = "1.6"

[dependencies.serde_crate]
Expand Down
18 changes: 9 additions & 9 deletions src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ encryption function, as per [RFC9180§7.3](https://www.rfc-editor.org/rfc/rfc918
)]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub enum Aead {
#[cfg(feature = "aead-aes-gcm-128")]
#[cfg(feature = "aead-aes")]
/// AES-128-GCM [GCM](https://doi.org/10.6028/nist.sp.800-38d)
AesGcm128 = 1,
#[cfg(feature = "aead-aes-gcm-256")]
#[cfg(feature = "aead-aes")]
/// AES-256-GCM [GCM](https://doi.org/10.6028/nist.sp.800-38d)
AesGcm256 = 2,
#[cfg(feature = "aead-chacha-20-poly-1305")]
#[cfg(feature = "aead-chacha")]
/// ChaCha20Poly1305 [RFC8439](https://www.rfc-editor.org/info/rfc8439)
ChaCha20Poly1305 = 3,
}
Expand All @@ -31,11 +31,11 @@ impl FromStr for Aead {

fn from_str(s: &str) -> Result<Self, Self::Err> {
match &*s.to_lowercase().replace('-', "") {
#[cfg(feature = "aead-aes-gcm-128")]
#[cfg(feature = "aead-aes")]
"aesgcm128" | "aes128gcm" => Ok(Self::AesGcm128),
#[cfg(feature = "aead-aes-gcm-256")]
#[cfg(feature = "aead-aes")]
"aesgcm256" | "aes256gcm" => Ok(Self::AesGcm256),
#[cfg(feature = "aead-chacha-20-poly-1305")]
#[cfg(feature = "aead-chacha")]
"chacha20poly1305" => Ok(Self::ChaCha20Poly1305),
_ => Err(IdLookupError("aead not recognized")),
}
Expand All @@ -44,10 +44,10 @@ impl FromStr for Aead {

/// An iterable slice of [`Aead`] variants
pub const AEAD_ALL: &[Aead] = &[
#[cfg(feature = "aead-aes-gcm-128")]
#[cfg(feature = "aead-aes")]
Aead::AesGcm128,
#[cfg(feature = "aead-aes-gcm-256")]
#[cfg(feature = "aead-aes")]
Aead::AesGcm256,
#[cfg(feature = "aead-chacha-20-poly-1305")]
#[cfg(feature = "aead-chacha")]
Aead::ChaCha20Poly1305,
];
3 changes: 1 addition & 2 deletions src/base_mode_seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ where
KdfT: hpke::kdf::Kdf,
KemT: hpke::kem::Kem,
{
let (encapped_key, ciphertext) = hpke::single_shot_seal::<AeadT, KdfT, KemT, _>(
let (encapped_key, ciphertext) = hpke::single_shot_seal::<AeadT, KdfT, KemT>(
&hpke::OpModeS::Base,
&from_bytes(recipient_public_key)?,
info,
plaintext,
aad,
&mut rand::rng(),
)?;

Ok(EncappedKeyAndCiphertext {
Expand Down
53 changes: 40 additions & 13 deletions src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use num_enum::TryFromPrimitive;
use std::str::FromStr;

/**
Kdf represents an key derivation function, as per
Kdf represents a key derivation function, as per
[RFC9180§7.2](https://www.rfc-editor.org/rfc/rfc9180.html#section-7.2)
and
https://www.ietf.org/archive/id/draft-ietf-hpke-pq-05.html#table-1
*/
#[non_exhaustive]
#[repr(u16)]
Expand All @@ -15,39 +17,64 @@ Kdf represents an key derivation function, as per
)]
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub enum Kdf {
#[cfg(feature = "kdf-sha256")]
#[cfg(feature = "kdf-hkdfsha2")]
/// Sha256 [RFC5869](https://www.rfc-editor.org/info/rfc5869)
Sha256 = 1,
#[cfg(feature = "kdf-sha384")]
Sha256 = 0x0001,
#[cfg(feature = "kdf-hkdfsha2")]
/// Sha384 [RFC5869](https://www.rfc-editor.org/info/rfc5869)
Sha384 = 2,
#[cfg(feature = "kdf-sha512")]
Sha384 = 0x0002,
#[cfg(feature = "kdf-hkdfsha2")]
/// Sha512 [RFC5869](https://www.rfc-editor.org/info/rfc5869)
Sha512 = 3,
Sha512 = 0x0003,
#[cfg(feature = "kdf-shake")]
/// SHAKE128 [RFC 9861](https://www.rfc-editor.org/info/rfc9861/)
Shake128 = 0x0010,
/// SHAKE256 [RFC 9861](https://www.rfc-editor.org/info/rfc9861/)
Shake256 = 0x0011,
/// TurboSHAKE128 [RFC 9861](https://www.rfc-editor.org/info/rfc9861/)
TurboShake128 = 0x0012,
/// TurboSHAKE256 [RFC 9861](https://www.rfc-editor.org/info/rfc9861/)
TurboShake256 = 0x0013,
}

impl FromStr for Kdf {
type Err = IdLookupError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match &*s.to_lowercase().replace('-', "") {
#[cfg(feature = "kdf-sha256")]
#[cfg(feature = "kdf-hkdfsha2")]
"hkdfsha256" | "sha256" => Ok(Self::Sha256),
#[cfg(feature = "kdf-sha384")]
#[cfg(feature = "kdf-hkdfsha2")]
"hkdfsha384" | "sha384" => Ok(Self::Sha384),
#[cfg(feature = "kdf-sha512")]
#[cfg(feature = "kdf-hkdfsha2")]
"hkdfsha512" | "sha512" => Ok(Self::Sha512),
#[cfg(feature = "kdf-shake")]
"shake128" => Ok(Self::Shake128),
#[cfg(feature = "kdf-shake")]
"shake256" => Ok(Self::Shake256),
#[cfg(feature = "kdf-shake")]
"turboshake128" => Ok(Self::TurboShake128),
#[cfg(feature = "kdf-shake")]
"turboshake256" => Ok(Self::TurboShake256),
_ => Err(IdLookupError("kdf not recognized")),
}
}
}

/// An iterable slice of [`Kdf`] variants
pub const KDF_ALL: &[Kdf] = &[
#[cfg(feature = "kdf-sha256")]
#[cfg(feature = "kdf-hkdfsha2")]
Kdf::Sha256,
#[cfg(feature = "kdf-sha384")]
#[cfg(feature = "kdf-hkdfsha2")]
Kdf::Sha384,
#[cfg(feature = "kdf-sha512")]
#[cfg(feature = "kdf-hkdfsha2")]
Kdf::Sha512,
#[cfg(feature = "kdf-shake")]
Kdf::Shake128,
#[cfg(feature = "kdf-shake")]
Kdf::Shake256,
#[cfg(feature = "kdf-shake")]
Kdf::TurboShake128,
#[cfg(feature = "kdf-shake")]
Kdf::TurboShake256,
];
79 changes: 59 additions & 20 deletions src/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ use std::str::FromStr;

/**
Kem represents an asymmetric key encapsulation mechanism, as per
[RFC9180§7.1][section-7.1]. Currently only four of the options listed in
the hpke draft are available.

[section-7.1]: https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1
[RFC9180§7.1](https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1)
and
https://www.ietf.org/archive/id/draft-ietf-hpke-pq-05.html#name-updated-ml-kem-entries-for-
*/
#[non_exhaustive]
#[repr(u16)]
Expand All @@ -19,44 +18,74 @@ the hpke draft are available.
#[cfg_attr(feature = "serde", serde(crate = "serde_crate"))]
pub enum Kem {
/// DHKEM(P-256, HKDF-SHA256) [NISTCurves](https://doi.org/10.6028/nist.fips.186-4)
#[cfg(feature = "kem-dh-p256-hkdf-sha256")]
DhP256HkdfSha256 = 16,
#[cfg(feature = "kem-nistp")]
DhP256HkdfSha256 = 0x0010,

/// DHKEM(P-384, HKDF-SHA384) [NISTCurves](https://doi.org/10.6028/nist.fips.186-4)
#[cfg(feature = "kem-dh-p384-hkdf-sha384")]
DhP384HkdfSha384 = 17,
#[cfg(feature = "kem-nistp")]
DhP384HkdfSha384 = 0x0011,

/// DHKEM(P-521, HKDF-SHA512) [NISTCurves](https://doi.org/10.6028/nist.fips.186-4)
#[cfg(feature = "kem-dh-p521-hkdf-sha512")]
DhP521HkdfSha512 = 18,
#[cfg(feature = "kem-nistp")]
DhP521HkdfSha512 = 0x0012,

/// DHKEM(X25519, HKDF-SHA256) [RFC7748](https://www.rfc-editor.org/info/rfc7748)
#[cfg(feature = "kem-x25519-hkdf-sha256")]
X25519HkdfSha256 = 32,
#[cfg(feature = "kem-x25519")]
X25519HkdfSha256 = 0x0020,

/// MLKEM-768 [FIPS 203](https://csrc.nist.gov/pubs/fips/203/final)
#[cfg(feature = "kem-mlkem")]
MlKem768 = 0x0041,

/// MLKEM-1024 [FIPS 203](https://csrc.nist.gov/pubs/fips/203/final)
#[cfg(feature = "kem-mlkem")]
MlKem1024 = 0x0042,

/// X-Wing (MLKEM768-X25519) <https://www.ietf.org/archive/id/draft-irtf-cfrg-concrete-hybrid-kems-04.html>
#[cfg(all(feature = "kem-mlkem", feature = "kem-x25519"))]
XWing = 0x647a,

/// MLKEM768-P256 <https://www.ietf.org/archive/id/draft-irtf-cfrg-concrete-hybrid-kems-04.html>
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
MlKem768P256 = 0x0050,

/// MLKEM1024-P384 <https://www.ietf.org/archive/id/draft-irtf-cfrg-concrete-hybrid-kems-04.html>
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
MlKem1024P384 = 0x0051,
}

impl FromStr for Kem {
type Err = IdLookupError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match &*s.to_lowercase().replace('-', "") {
#[cfg(feature = "kem-dh-p256-hkdf-sha256")]
#[cfg(feature = "kem-nistp")]
"p256sha256" | "dhkemp256hkdfsha256" | "p256hkdfsha256" | "dhkem(p256, hkdfsha256)" => {
Ok(Self::DhP256HkdfSha256)
}
#[cfg(feature = "kem-dh-p384-hkdf-sha384")]
#[cfg(feature = "kem-nistp")]
"p384sha384" | "dhkemp384hkdfsha384" | "p384hkdfsha384" | "dhkem(p384, hkdfsha384)" => {
Ok(Self::DhP384HkdfSha384)
}
#[cfg(feature = "kem-dh-p521-hkdf-sha512")]
#[cfg(feature = "kem-nistp")]
"p521sha512" | "dhkemp521hkdfsha512" | "p521hkdfsha512" | "dhkem(p521, hkdfsha512)" => {
Ok(Self::DhP521HkdfSha512)
}
#[cfg(feature = "kem-x25519-hkdf-sha256")]
#[cfg(feature = "kem-x25519")]
"x25519sha256"
| "dhkemx25519hkdfsha256"
| "x25519hkdfsha256"
| "dhkem(x25519, hkdfsha256)" => Ok(Self::X25519HkdfSha256),
#[cfg(feature = "kem-mlkem")]
"mlkem768" => Ok(Self::MlKem768),
#[cfg(feature = "kem-mlkem")]
"mlkem1024" => Ok(Self::MlKem1024),
#[cfg(all(feature = "kem-mlkem", feature = "kem-x25519"))]
"xwing" | "mlkem768x25119" | "mlkem768-x25119" => Ok(Self::XWing),
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
"mlkem768p256" | "mlkem768-p256" => Ok(Self::MlKem768P256),
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
"mlkem1024p384" | "mlkem1024-p384" => Ok(Self::MlKem1024P384),
_ => Err(IdLookupError("kem not recognized")),
}
}
Expand All @@ -72,12 +101,22 @@ impl Kem {

/// An iterable slice of [`Kem`] variants
pub const KEM_ALL: &[Kem] = &[
#[cfg(feature = "kem-dh-p256-hkdf-sha256")]
#[cfg(feature = "kem-nistp")]
Kem::DhP256HkdfSha256,
#[cfg(feature = "kem-dh-p384-hkdf-sha384")]
#[cfg(feature = "kem-nistp")]
Kem::DhP384HkdfSha384,
#[cfg(feature = "kem-dh-p521-hkdf-sha512")]
#[cfg(feature = "kem-nistp")]
Kem::DhP521HkdfSha512,
#[cfg(feature = "kem-x25519-hkdf-sha256")]
#[cfg(feature = "kem-x25519")]
Kem::X25519HkdfSha256,
#[cfg(feature = "kem-mlkem")]
Kem::MlKem768,
#[cfg(feature = "kem-mlkem")]
Kem::MlKem1024,
#[cfg(all(feature = "kem-mlkem", feature = "kem-x25519"))]
Kem::XWing,
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
Kem::MlKem768P256,
#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
Kem::MlKem1024P384,
];
25 changes: 20 additions & 5 deletions src/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,37 @@ impl Keypair {
#[must_use]
pub fn gen_keypair(kem: Kem) -> Keypair {
match kem {
#[cfg(feature = "kem-dh-p256-hkdf-sha256")]
#[cfg(feature = "kem-nistp")]
Kem::DhP256HkdfSha256 => gen_kp::<hpke::kem::DhP256HkdfSha256>(),

#[cfg(feature = "kem-dh-p384-hkdf-sha384")]
#[cfg(feature = "kem-nistp")]
Kem::DhP384HkdfSha384 => gen_kp::<hpke::kem::DhP384HkdfSha384>(),

#[cfg(feature = "kem-dh-p521-hkdf-sha512")]
#[cfg(feature = "kem-nistp")]
Kem::DhP521HkdfSha512 => gen_kp::<hpke::kem::DhP521HkdfSha512>(),

#[cfg(feature = "kem-x25519-hkdf-sha256")]
#[cfg(feature = "kem-x25519")]
Kem::X25519HkdfSha256 => gen_kp::<hpke::kem::X25519HkdfSha256>(),

#[cfg(feature = "kem-mlkem")]
Kem::MlKem768 => gen_kp::<hpke::kem::MlKem768>(),

#[cfg(feature = "kem-mlkem")]
Kem::MlKem1024 => gen_kp::<hpke::kem::MlKem1024>(),

#[cfg(all(feature = "kem-mlkem", feature = "kem-x25519"))]
Kem::XWing => gen_kp::<hpke::kem::XWing>(),

#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
Kem::MlKem768P256 => gen_kp::<hpke::kem::MlKem768P256>(),

#[cfg(all(feature = "kem-mlkem", feature = "kem-nistp"))]
Kem::MlKem1024P384 => gen_kp::<hpke::kem::MlKem1024P384>(),
}
}

fn gen_kp<KemT: hpke::kem::Kem>() -> Keypair {
let (private_key, public_key) = KemT::gen_keypair(&mut rand::rng());
let (private_key, public_key) = KemT::gen_keypair();
let public_key = public_key.to_bytes().to_vec();
let private_key = private_key.to_bytes().to_vec();

Expand Down
15 changes: 3 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,9 @@
#![doc = include_str!("../README.md")]
#![cfg(all(
any(feature = "base-mode-open", feature = "base-mode-seal"),
any(
feature = "aead-aes-gcm-128",
feature = "aead-aes-gcm-256",
feature = "aead-chacha-20-poly-1305",
),
any(feature = "kdf-sha256", feature = "kdf-sha384", feature = "kdf-sha512"),
any(
feature = "kem-dh-p256-hkdf-sha256",
feature = "kem-dh-p384-hkdf-sha384",
feature = "kem-dh-p521-hkdf-sha512",
feature = "kem-x25519-hkdf-sha256",
),
any(feature = "aead-aes", feature = "aead-chacha",),
any(feature = "kdf-hkdfsha2", feature = "kdf-shake"),
any(feature = "kem-nistp", feature = "kem-x25519", feature = "kem-mlkem",),
))]

use hpke::{Deserializable, HpkeError};
Expand Down
Loading