From 67190fc760a95a0391a1b21ac6db972372fede5c Mon Sep 17 00:00:00 2001 From: Will Song Date: Thu, 18 Apr 2024 20:56:06 -0400 Subject: [PATCH 1/5] add first version of KEM trait --- kem/Cargo.toml | 2 +- kem/src/lib.rs | 20 +++++++++++ kem/tests/kemtrait_p256.rs | 69 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 kem/tests/kemtrait_p256.rs diff --git a/kem/Cargo.toml b/kem/Cargo.toml index dce5587c1..fa11209e5 100644 --- a/kem/Cargo.toml +++ b/kem/Cargo.toml @@ -18,7 +18,7 @@ zeroize = { version = "1.7", default-features = false } [dev-dependencies] hpke = "0.10" -p256 = { version = "0.9", features = ["ecdsa"] } +p256 = { version = "0.9", features = ["ecdh", "ecdsa"] } pqcrypto = { version = "0.15", default-features = false, features = [ "pqcrypto-saber", ] } diff --git a/kem/src/lib.rs b/kem/src/lib.rs index 27dc0aa19..e8ed0df77 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -33,3 +33,23 @@ pub trait Decapsulate { /// Decapsulates the given encapsulated key fn decapsulate(&self, encapsulated_key: &EK) -> Result; } + +/// This is a trait that all KEM models should implement, and should probably be promoted to the kem +/// crate itself. It specifies the types of encapsulating and decapsulating keys created by key +/// generation, the shared secret type, and the encapsulated key type +pub trait KEM { + /// The type that will implement [`Decapsulate`] + type DecapsulatingKey: Decapsulate; + + /// The type that will implement [`Encapsulate`] + type EncapsulatingKey: Encapsulate; + + /// The type of the encapsulated key + type EncapsulatedKey; + + /// The type of the shared secret + type SharedSecret; + + /// Generates a new (decapsulating key, encapsulating key) keypair for the KEM model + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::EncapsulatingKey); +} diff --git a/kem/tests/kemtrait_p256.rs b/kem/tests/kemtrait_p256.rs new file mode 100644 index 000000000..ab5680096 --- /dev/null +++ b/kem/tests/kemtrait_p256.rs @@ -0,0 +1,69 @@ +use kem::{Decapsulate, Encapsulate, KEM}; +use p256::{ecdh::{EphemeralSecret, SharedSecret}, PublicKey}; +use rand_core::CryptoRngCore; + +struct KemNistP256; +struct DecapsulatorP256(EphemeralSecret); +struct EncapsulatorP256(PublicKey); +struct Secret(SharedSecret); + +impl Decapsulate for DecapsulatorP256 { + type Error = (); + + fn decapsulate(&self, encapsulated_key: &PublicKey) -> Result { + Ok(Secret(self.0.diffie_hellman(encapsulated_key))) + } +} + +impl Encapsulate for EncapsulatorP256 { + type Error = (); + + fn encapsulate(&self, rng: &mut impl CryptoRngCore) -> Result<(PublicKey, Secret), Self::Error> { + let sk = EphemeralSecret::random(rng); + let pk = sk.public_key(); + + Ok((pk, Secret(sk.diffie_hellman(&self.0)))) + } +} + +impl KEM for KemNistP256 { + type DecapsulatingKey = DecapsulatorP256; + type EncapsulatingKey = EncapsulatorP256; + type EncapsulatedKey = PublicKey; + type SharedSecret = Secret; + + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::EncapsulatingKey) { + let sk = EphemeralSecret::random(rng); + let pk = sk.public_key(); + + (DecapsulatorP256(sk), EncapsulatorP256(pk)) + } +} + +// Helper trait so that shared secrets can be more easily tested for equality during testing +pub trait SecretBytes { + fn as_slice(&self) -> &[u8]; +} + +impl SecretBytes for Secret { + fn as_slice(&self) -> &[u8] { + self.0.as_bytes().as_slice() + } +} + +fn test_kemtrait() +where + ::SharedSecret: SecretBytes, +{ + let mut rng = rand::thread_rng(); + let (sk, pk) = K::random_keypair(&mut rng); + let (ek, ss1) = pk.encapsulate(&mut rng).expect("never fails"); + let ss2 = sk.decapsulate(&ek).expect("never fails"); + + assert_eq!(ss1.as_slice(), ss2.as_slice()); +} + +#[test] +fn test_kemtrait_p256() { + test_kemtrait::(); +} From 9978ef7c93963fd9a3466c95cde7eafd934720c0 Mon Sep 17 00:00:00 2001 From: Will Song Date: Thu, 18 Apr 2024 23:49:18 -0400 Subject: [PATCH 2/5] seperate public key from encapsulating key --- kem/src/lib.rs | 5 ++++- kem/tests/kemtrait_p256.rs | 30 +++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index e8ed0df77..cdbd78048 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -41,6 +41,9 @@ pub trait KEM { /// The type that will implement [`Decapsulate`] type DecapsulatingKey: Decapsulate; + /// The public key produced by [`random_keypair`] + type PublicKey; + /// The type that will implement [`Encapsulate`] type EncapsulatingKey: Encapsulate; @@ -51,5 +54,5 @@ pub trait KEM { type SharedSecret; /// Generates a new (decapsulating key, encapsulating key) keypair for the KEM model - fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::EncapsulatingKey); + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey); } diff --git a/kem/tests/kemtrait_p256.rs b/kem/tests/kemtrait_p256.rs index ab5680096..880734ce1 100644 --- a/kem/tests/kemtrait_p256.rs +++ b/kem/tests/kemtrait_p256.rs @@ -1,5 +1,8 @@ use kem::{Decapsulate, Encapsulate, KEM}; -use p256::{ecdh::{EphemeralSecret, SharedSecret}, PublicKey}; +use p256::{ + ecdh::{EphemeralSecret, SharedSecret}, + PublicKey, +}; use rand_core::CryptoRngCore; struct KemNistP256; @@ -18,7 +21,10 @@ impl Decapsulate for DecapsulatorP256 { impl Encapsulate for EncapsulatorP256 { type Error = (); - fn encapsulate(&self, rng: &mut impl CryptoRngCore) -> Result<(PublicKey, Secret), Self::Error> { + fn encapsulate( + &self, + rng: &mut impl CryptoRngCore, + ) -> Result<(PublicKey, Secret), Self::Error> { let sk = EphemeralSecret::random(rng); let pk = sk.public_key(); @@ -26,17 +32,24 @@ impl Encapsulate for EncapsulatorP256 { } } +impl From for EncapsulatorP256 { + fn from(value: PublicKey) -> Self { + Self(value) + } +} + impl KEM for KemNistP256 { type DecapsulatingKey = DecapsulatorP256; + type PublicKey = PublicKey; type EncapsulatingKey = EncapsulatorP256; type EncapsulatedKey = PublicKey; type SharedSecret = Secret; - fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::EncapsulatingKey) { + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey) { let sk = EphemeralSecret::random(rng); let pk = sk.public_key(); - (DecapsulatorP256(sk), EncapsulatorP256(pk)) + (DecapsulatorP256(sk), pk) } } @@ -51,13 +64,16 @@ impl SecretBytes for Secret { } } -fn test_kemtrait() +fn test_kemtrait_basic() where ::SharedSecret: SecretBytes, + ::EncapsulatingKey: From<::PublicKey>, { let mut rng = rand::thread_rng(); let (sk, pk) = K::random_keypair(&mut rng); - let (ek, ss1) = pk.encapsulate(&mut rng).expect("never fails"); + let (ek, ss1) = ::EncapsulatingKey::from(pk) + .encapsulate(&mut rng) + .expect("never fails"); let ss2 = sk.decapsulate(&ek).expect("never fails"); assert_eq!(ss1.as_slice(), ss2.as_slice()); @@ -65,5 +81,5 @@ where #[test] fn test_kemtrait_p256() { - test_kemtrait::(); + test_kemtrait_basic::(); } From 4402e15ef126c043b0e2c5ac540b8074069d11bc Mon Sep 17 00:00:00 2001 From: Will Song Date: Fri, 19 Apr 2024 00:54:47 -0400 Subject: [PATCH 3/5] use SimpleKEM and FullKEM model and promote all SimpleKEMs to FullKEMs --- kem/src/lib.rs | 45 +++++++++++++++++++++++++++++++++----- kem/tests/kemtrait_p256.rs | 26 ++++++++-------------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index cdbd78048..14ddf3605 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -34,14 +34,37 @@ pub trait Decapsulate { fn decapsulate(&self, encapsulated_key: &EK) -> Result; } -/// This is a trait that all KEM models should implement, and should probably be promoted to the kem -/// crate itself. It specifies the types of encapsulating and decapsulating keys created by key -/// generation, the shared secret type, and the encapsulated key type -pub trait KEM { +/// This trait represents a simplified KEM model, where the encapsulating key and public key are the +/// same type. +pub trait SimpleKEM { /// The type that will implement [`Decapsulate`] type DecapsulatingKey: Decapsulate; - /// The public key produced by [`random_keypair`] + /// The type that will implement [`Encapsulate`] + type EncapsulatingKey: Encapsulate; + + /// The type of the encapsulated key + type EncapsulatedKey; + + /// The type of the shared secret + type SharedSecret; + + /// Generates a new (decapsulating key, encapsulating key) keypair for the KEM model + fn random_keypair( + rng: &mut impl CryptoRngCore, + ) -> (Self::DecapsulatingKey, Self::EncapsulatingKey); +} + +/// This is a trait that all KEM models should implement. It represents all the stages and types +/// necessary for a KEM, from `KeyGen() -> (DecapsKey, PublicKey)`, `Encaps(EncapsulatingKey) -> +/// (EncappedKey, SharedSecret)`, and `Decaps(EncappedKey) -> SharedSecret`. Promotion from +/// [`PublicKey`](FullKEM::PublicKey) to [`EncapsulatingKey`](FullKEM::EncapsulatingKey) is context +/// dependent. +pub trait FullKEM { + /// The type that will implement [`Decapsulate`] + type DecapsulatingKey: Decapsulate; + + /// The public key produced by [`random_keypair`](FullKEM::random_keypair) type PublicKey; /// The type that will implement [`Encapsulate`] @@ -56,3 +79,15 @@ pub trait KEM { /// Generates a new (decapsulating key, encapsulating key) keypair for the KEM model fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey); } + +impl FullKEM for K { + type DecapsulatingKey = K::DecapsulatingKey; + type PublicKey = K::EncapsulatingKey; + type EncapsulatingKey = K::EncapsulatingKey; + type EncapsulatedKey = K::EncapsulatedKey; + type SharedSecret = K::SharedSecret; + + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey) { + Self::random_keypair(rng) + } +} diff --git a/kem/tests/kemtrait_p256.rs b/kem/tests/kemtrait_p256.rs index 880734ce1..127edf98d 100644 --- a/kem/tests/kemtrait_p256.rs +++ b/kem/tests/kemtrait_p256.rs @@ -1,4 +1,4 @@ -use kem::{Decapsulate, Encapsulate, KEM}; +use kem::{Decapsulate, Encapsulate, SimpleKEM}; use p256::{ ecdh::{EphemeralSecret, SharedSecret}, PublicKey, @@ -32,24 +32,19 @@ impl Encapsulate for EncapsulatorP256 { } } -impl From for EncapsulatorP256 { - fn from(value: PublicKey) -> Self { - Self(value) - } -} - -impl KEM for KemNistP256 { +impl SimpleKEM for KemNistP256 { type DecapsulatingKey = DecapsulatorP256; - type PublicKey = PublicKey; type EncapsulatingKey = EncapsulatorP256; type EncapsulatedKey = PublicKey; type SharedSecret = Secret; - fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey) { + fn random_keypair( + rng: &mut impl CryptoRngCore, + ) -> (Self::DecapsulatingKey, Self::EncapsulatingKey) { let sk = EphemeralSecret::random(rng); let pk = sk.public_key(); - (DecapsulatorP256(sk), pk) + (DecapsulatorP256(sk), EncapsulatorP256(pk)) } } @@ -64,16 +59,13 @@ impl SecretBytes for Secret { } } -fn test_kemtrait_basic() +fn test_kemtrait_basic() where - ::SharedSecret: SecretBytes, - ::EncapsulatingKey: From<::PublicKey>, + ::SharedSecret: SecretBytes, { let mut rng = rand::thread_rng(); let (sk, pk) = K::random_keypair(&mut rng); - let (ek, ss1) = ::EncapsulatingKey::from(pk) - .encapsulate(&mut rng) - .expect("never fails"); + let (ek, ss1) = pk.encapsulate(&mut rng).expect("never fails"); let ss2 = sk.decapsulate(&ek).expect("never fails"); assert_eq!(ss1.as_slice(), ss2.as_slice()); From a5c1a2146ef980d802574e8744519c0662220d9c Mon Sep 17 00:00:00 2001 From: Will Song Date: Fri, 19 Apr 2024 01:21:18 -0400 Subject: [PATCH 4/5] add more methods, documentation, and tests --- kem/src/lib.rs | 76 +++++++++++++++++++++++++++++++++----- kem/tests/kemtrait_p256.rs | 5 ++- kem/tests/x3dh.rs | 41 +++++++++++++++++++- 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index 14ddf3605..e8cc672a5 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -53,20 +53,52 @@ pub trait SimpleKEM { fn random_keypair( rng: &mut impl CryptoRngCore, ) -> (Self::DecapsulatingKey, Self::EncapsulatingKey); + + /// Forwards a call to [`encapsulate`](Encapsulate::encapsulate) + fn encapsulate( + ek: &Self::EncapsulatingKey, + rng: &mut impl CryptoRngCore, + ) -> Result< + (Self::EncapsulatedKey, Self::SharedSecret), + >::Error, + > { + ek.encapsulate(rng) + } + + /// Forwards a call to [`decapsulate`](Decapsulate::decapsulate) + fn decapsulate( + dk: &Self::DecapsulatingKey, + ek: &Self::EncapsulatedKey, + ) -> Result< + Self::SharedSecret, + >::Error, + > { + dk.decapsulate(ek) + } } /// This is a trait that all KEM models should implement. It represents all the stages and types -/// necessary for a KEM, from `KeyGen() -> (DecapsKey, PublicKey)`, `Encaps(EncapsulatingKey) -> -/// (EncappedKey, SharedSecret)`, and `Decaps(EncappedKey) -> SharedSecret`. Promotion from -/// [`PublicKey`](FullKEM::PublicKey) to [`EncapsulatingKey`](FullKEM::EncapsulatingKey) is context -/// dependent. +/// necessary for a KEM. +/// +/// In particular, +/// +/// 1. `KeyGen() -> (PrivateKey, PublicKey)` +/// 2. `Encaps(EncapsulatingKey) -> (EncappedKey, SharedSecret)` +/// 3. `Decaps(DecapsulatingKey, EncappedKey) -> SharedSecret` +/// +/// Promotion from [`PrivateKey`](FullKEM::PrivateKey) to +/// [`DecapsulatingKey`](FullKEM::DecapsulatingKey) and [`PublicKey`](FullKEM::PublicKey) to +/// [`EncapsulatingKey`](FullKEM::EncapsulatingKey) is context dependent. pub trait FullKEM { - /// The type that will implement [`Decapsulate`] - type DecapsulatingKey: Decapsulate; + /// The private key produced by [`random_keypair`](FullKEM::random_keypair) + type PrivateKey; /// The public key produced by [`random_keypair`](FullKEM::random_keypair) type PublicKey; + /// The type that will implement [`Decapsulate`] + type DecapsulatingKey: Decapsulate; + /// The type that will implement [`Encapsulate`] type EncapsulatingKey: Encapsulate; @@ -76,18 +108,42 @@ pub trait FullKEM { /// The type of the shared secret type SharedSecret; - /// Generates a new (decapsulating key, encapsulating key) keypair for the KEM model - fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey); + /// Generates a new ([`PrivateKey`](FullKEM::PrivateKey), [`PublicKey`](FullKEM::PublicKey)) + /// keypair for the KEM model + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::PrivateKey, Self::PublicKey); + + /// Forwards a call to [`encapsulate`](Encapsulate::encapsulate) + fn encapsulate( + ek: &Self::EncapsulatingKey, + rng: &mut impl CryptoRngCore, + ) -> Result< + (Self::EncapsulatedKey, Self::SharedSecret), + >::Error, + > { + ek.encapsulate(rng) + } + + /// Forwards a call to [`decapsulate`](Decapsulate::decapsulate) + fn decapsulate( + dk: &Self::DecapsulatingKey, + ek: &Self::EncapsulatedKey, + ) -> Result< + Self::SharedSecret, + >::Error, + > { + dk.decapsulate(ek) + } } impl FullKEM for K { - type DecapsulatingKey = K::DecapsulatingKey; + type PrivateKey = K::DecapsulatingKey; type PublicKey = K::EncapsulatingKey; + type DecapsulatingKey = K::DecapsulatingKey; type EncapsulatingKey = K::EncapsulatingKey; type EncapsulatedKey = K::EncapsulatedKey; type SharedSecret = K::SharedSecret; - fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::DecapsulatingKey, Self::PublicKey) { + fn random_keypair(rng: &mut impl CryptoRngCore) -> (Self::PrivateKey, Self::PublicKey) { Self::random_keypair(rng) } } diff --git a/kem/tests/kemtrait_p256.rs b/kem/tests/kemtrait_p256.rs index 127edf98d..4944a82b0 100644 --- a/kem/tests/kemtrait_p256.rs +++ b/kem/tests/kemtrait_p256.rs @@ -59,14 +59,15 @@ impl SecretBytes for Secret { } } +// use a generic SimpleKEM function to ensure correctness fn test_kemtrait_basic() where ::SharedSecret: SecretBytes, { let mut rng = rand::thread_rng(); let (sk, pk) = K::random_keypair(&mut rng); - let (ek, ss1) = pk.encapsulate(&mut rng).expect("never fails"); - let ss2 = sk.decapsulate(&ek).expect("never fails"); + let (ek, ss1) = K::encapsulate(&pk, &mut rng).expect("never fails"); + let ss2 = K::decapsulate(&sk, &ek).expect("never fails"); assert_eq!(ss1.as_slice(), ss2.as_slice()); } diff --git a/kem/tests/x3dh.rs b/kem/tests/x3dh.rs index b39a5adf8..857ad1cea 100644 --- a/kem/tests/x3dh.rs +++ b/kem/tests/x3dh.rs @@ -1,9 +1,12 @@ -use kem::{Decapsulate, Encapsulate}; +use kem::{Decapsulate, Encapsulate, FullKEM}; use p256::ecdsa::Signature; use rand_core::CryptoRngCore; use x3dh_ke::{x3dh_a, x3dh_b, EphemeralKey, IdentityKey, Key, OneTimePreKey, SignedPreKey}; +/// A struct representing the x3dh KEM +struct X3Dh; + /// The shared secret type defined by x3dh_ke type SharedSecret = [u8; 32]; @@ -92,6 +95,22 @@ impl Decapsulate for DecapContext { } } +impl FullKEM for X3Dh { + type PrivateKey = X3DhPrivkeyBundle; + type PublicKey = X3DhPubkeyBundle; + type DecapsulatingKey = DecapContext; + type EncapsulatingKey = EncapContext; + type EncapsulatedKey = EphemeralKey; + type SharedSecret = SharedSecret; + + fn random_keypair(_: &mut impl CryptoRngCore) -> (Self::PrivateKey, Self::PublicKey) { + let sk = Self::PrivateKey::gen(); + let pk = sk.as_pubkeys(); + + (sk, pk) + } +} + #[test] fn test_x3dh() { let mut rng = rand::thread_rng(); @@ -111,3 +130,23 @@ fn test_x3dh() { let ss2 = decap_context.decapsulate(&encapped_key).unwrap(); assert_eq!(ss1, ss2); } + +#[test] +fn test_kemtrait_x3dh() { + let mut rng = rand::thread_rng(); + + // We use _a and _b suffixes to denote whether a key belongs to Alice or Bob. Alice is the + // sender in this case. + let sk_ident_a = IdentityKey::default(); + let pk_ident_a = sk_ident_a.strip(); + let (sk_bundle_b, pk_bundle_b) = X3Dh::random_keypair(&mut rng); + + let encap_context = EncapContext(pk_bundle_b, sk_ident_a); + let decap_context = DecapContext(sk_bundle_b, pk_ident_a); + + // Now do an authenticated encap + let (encapped_key, ss1) = X3Dh::encapsulate(&encap_context, &mut rng).unwrap(); + let ss2 = X3Dh::decapsulate(&decap_context, &encapped_key).unwrap(); + + assert_eq!(ss1, ss2); +} From 2850d082e4dc6b218a4dc41c7dec6e43d2ebeef3 Mon Sep 17 00:00:00 2001 From: Will Song Date: Fri, 19 Apr 2024 01:38:57 -0400 Subject: [PATCH 5/5] use type aliases to satisfy clippy --- kem/src/lib.rs | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/kem/src/lib.rs b/kem/src/lib.rs index e8cc672a5..6731cef7d 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -34,6 +34,18 @@ pub trait Decapsulate { fn decapsulate(&self, encapsulated_key: &EK) -> Result; } +// Helper type alias for SimpleKEM encapsulate errors +type SimpleEncapError = <::EncapsulatingKey as Encapsulate< + ::EncapsulatedKey, + ::SharedSecret, +>>::Error; + +// Helper type alias for SimpleKEM decapsulate errors +type SimpleDecapError = <::DecapsulatingKey as Decapsulate< + ::EncapsulatedKey, + ::SharedSecret, +>>::Error; + /// This trait represents a simplified KEM model, where the encapsulating key and public key are the /// same type. pub trait SimpleKEM { @@ -58,10 +70,7 @@ pub trait SimpleKEM { fn encapsulate( ek: &Self::EncapsulatingKey, rng: &mut impl CryptoRngCore, - ) -> Result< - (Self::EncapsulatedKey, Self::SharedSecret), - >::Error, - > { + ) -> Result<(Self::EncapsulatedKey, Self::SharedSecret), SimpleEncapError> { ek.encapsulate(rng) } @@ -69,14 +78,23 @@ pub trait SimpleKEM { fn decapsulate( dk: &Self::DecapsulatingKey, ek: &Self::EncapsulatedKey, - ) -> Result< - Self::SharedSecret, - >::Error, - > { + ) -> Result> { dk.decapsulate(ek) } } +// Helper type alias for FullKEM encapsulate errors +type FullEncapError = <::EncapsulatingKey as Encapsulate< + ::EncapsulatedKey, + ::SharedSecret, +>>::Error; + +// Helper type alias for FullKEM decapsulate errors +type FullDecapError = <::DecapsulatingKey as Decapsulate< + ::EncapsulatedKey, + ::SharedSecret, +>>::Error; + /// This is a trait that all KEM models should implement. It represents all the stages and types /// necessary for a KEM. /// @@ -116,10 +134,7 @@ pub trait FullKEM { fn encapsulate( ek: &Self::EncapsulatingKey, rng: &mut impl CryptoRngCore, - ) -> Result< - (Self::EncapsulatedKey, Self::SharedSecret), - >::Error, - > { + ) -> Result<(Self::EncapsulatedKey, Self::SharedSecret), FullEncapError> { ek.encapsulate(rng) } @@ -127,10 +142,7 @@ pub trait FullKEM { fn decapsulate( dk: &Self::DecapsulatingKey, ek: &Self::EncapsulatedKey, - ) -> Result< - Self::SharedSecret, - >::Error, - > { + ) -> Result> { dk.decapsulate(ek) } }