feat: upgrade crypto ecosystem to latest RustCrypto stack (#1)
Rust CI / cargo audit (push) Successful in 6s
Rust CI / cargo fmt (push) Successful in 4s
Rust CI / test (1.90.0 / no backend / no frontend) (push) Successful in 2m25s
Rust CI / test (stable / no backend / no frontend) (push) Successful in 2m27s
Rust CI / cargo clippy (push) Successful in 1m25s
Rust CI / test (1.90.0 / no backend / --features argon2) (push) Successful in 2m35s
Rust CI / test (stable / no backend / --features argon2) (push) Successful in 2m34s
Rust CI / test (stable / no backend / --features serde) (push) Successful in 2m55s
Rust CI / test (stable / --features curve25519 / no frontend) (push) Successful in 2m31s
Rust CI / test (1.90.0 / no backend / --features serde) (push) Successful in 2m52s
Rust CI / test (1.90.0 / --features curve25519 / no frontend) (push) Successful in 2m29s
Rust CI / test (1.90.0 / --features curve25519 / --features argon2) (push) Successful in 2m37s
Rust CI / test (stable / --features curve25519 / --features argon2) (push) Successful in 2m36s
Rust CI / test (1.90.0 / --features curve25519 / --features serde) (push) Successful in 2m59s
Rust CI / test (stable / --features curve25519 / --features serde) (push) Successful in 3m1s
Rust CI / test (1.90.0 / --features ecdsa / no frontend) (push) Successful in 2m52s
Rust CI / test (stable / --features ecdsa / no frontend) (push) Successful in 2m51s
Rust CI / test (1.90.0 / --features ecdsa / --features argon2) (push) Successful in 2m57s
Rust CI / test (stable / --features ecdsa / --features argon2) (push) Successful in 2m58s
Rust CI / test (1.90.0 / --features ecdsa / --features serde) (push) Successful in 3m19s
Rust CI / test (1.90.0 / --features ristretto255 / no frontend) (push) Successful in 3m2s
Rust CI / test (stable / --features ecdsa / --features serde) (push) Successful in 3m19s
Rust CI / test (1.90.0 / --features ed25519 / no frontend) (push) Successful in 2m53s
Rust CI / test (stable / --features ed25519 / no frontend) (push) Successful in 2m54s
Rust CI / test (1.90.0 / --features ed25519 / --features argon2) (push) Successful in 3m3s
Rust CI / test (stable / --features ed25519 / --features argon2) (push) Successful in 3m0s
Rust CI / test (1.90.0 / --features ed25519 / --features serde) (push) Successful in 3m22s
Rust CI / test (stable / --features ed25519 / --features serde) (push) Successful in 3m22s
Rust CI / test (1.90.0 / --features ristretto255 / --features argon2) (push) Successful in 3m9s
Rust CI / test (stable / --features ristretto255 / no frontend) (push) Successful in 3m4s
Rust CI / test (stable / --features ristretto255 / --features argon2) (push) Successful in 3m11s
Rust CI / test (1.90.0 / --features ristretto255 / --features serde) (push) Successful in 3m28s
Rust CI / test (stable / --features ristretto255 / --features serde) (push) Successful in 3m32s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / no frontend) (push) Successful in 5m26s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / no frontend) (push) Successful in 5m17s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / --features argon2) (push) Successful in 5m27s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / --features serde) (push) Successful in 5m43s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / --features argon2) (push) Successful in 5m20s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / --features serde) (push) Successful in 6m1s
Rust CI / test (stable / --features ristretto255,kem / no frontend) (push) Successful in 4m0s
Rust CI / test (1.90.0 / --features ristretto255,kem / --features argon2) (push) Successful in 4m5s
Rust CI / test (1.90.0 / --features ristretto255,kem / no frontend) (push) Successful in 4m2s
Rust CI / test (stable / --features ristretto255,kem / --features argon2) (push) Successful in 4m3s
Rust CI / test (stable / --features ristretto255,kem / --features serde) (push) Successful in 4m32s
Rust CI / test (1.90.0 / --features ristretto255,kem / --features serde) (push) Successful in 4m31s
Rust CI / test simple_login example (push) Successful in 19s
Rust CI / test digital_locker example (push) Successful in 18s
Rust CI / cargo bench compilation () (push) Successful in 1m47s
Rust CI / cargo bench compilation (--features ristretto255) (push) Successful in 1m55s
Rust CI / cargo bench compilation (--features ristretto255,kem) (push) Successful in 2m35s
Rust CI / no-std (thumbv6m-none-eabi / no backend) (push) Successful in 28s
Rust CI / no-std (wasm32-unknown-unknown / no backend) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / curve25519) (push) Successful in 18s
Rust CI / no-std (wasm32-unknown-unknown / curve25519) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ecdsa) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ecdsa) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ed25519) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ed25519) (push) Successful in 30s
Rust CI / no-std (thumbv6m-none-eabi / ristretto255) (push) Successful in 28s
Rust CI / no-std (wasm32-unknown-unknown / ristretto255) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ristretto255,curve25519,ecdsa,ed25519) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ristretto255,curve25519,ecdsa,ed25519) (push) Successful in 19s
Rust CI / cargo audit (push) Successful in 6s
Rust CI / cargo fmt (push) Successful in 4s
Rust CI / test (1.90.0 / no backend / no frontend) (push) Successful in 2m25s
Rust CI / test (stable / no backend / no frontend) (push) Successful in 2m27s
Rust CI / cargo clippy (push) Successful in 1m25s
Rust CI / test (1.90.0 / no backend / --features argon2) (push) Successful in 2m35s
Rust CI / test (stable / no backend / --features argon2) (push) Successful in 2m34s
Rust CI / test (stable / no backend / --features serde) (push) Successful in 2m55s
Rust CI / test (stable / --features curve25519 / no frontend) (push) Successful in 2m31s
Rust CI / test (1.90.0 / no backend / --features serde) (push) Successful in 2m52s
Rust CI / test (1.90.0 / --features curve25519 / no frontend) (push) Successful in 2m29s
Rust CI / test (1.90.0 / --features curve25519 / --features argon2) (push) Successful in 2m37s
Rust CI / test (stable / --features curve25519 / --features argon2) (push) Successful in 2m36s
Rust CI / test (1.90.0 / --features curve25519 / --features serde) (push) Successful in 2m59s
Rust CI / test (stable / --features curve25519 / --features serde) (push) Successful in 3m1s
Rust CI / test (1.90.0 / --features ecdsa / no frontend) (push) Successful in 2m52s
Rust CI / test (stable / --features ecdsa / no frontend) (push) Successful in 2m51s
Rust CI / test (1.90.0 / --features ecdsa / --features argon2) (push) Successful in 2m57s
Rust CI / test (stable / --features ecdsa / --features argon2) (push) Successful in 2m58s
Rust CI / test (1.90.0 / --features ecdsa / --features serde) (push) Successful in 3m19s
Rust CI / test (1.90.0 / --features ristretto255 / no frontend) (push) Successful in 3m2s
Rust CI / test (stable / --features ecdsa / --features serde) (push) Successful in 3m19s
Rust CI / test (1.90.0 / --features ed25519 / no frontend) (push) Successful in 2m53s
Rust CI / test (stable / --features ed25519 / no frontend) (push) Successful in 2m54s
Rust CI / test (1.90.0 / --features ed25519 / --features argon2) (push) Successful in 3m3s
Rust CI / test (stable / --features ed25519 / --features argon2) (push) Successful in 3m0s
Rust CI / test (1.90.0 / --features ed25519 / --features serde) (push) Successful in 3m22s
Rust CI / test (stable / --features ed25519 / --features serde) (push) Successful in 3m22s
Rust CI / test (1.90.0 / --features ristretto255 / --features argon2) (push) Successful in 3m9s
Rust CI / test (stable / --features ristretto255 / no frontend) (push) Successful in 3m4s
Rust CI / test (stable / --features ristretto255 / --features argon2) (push) Successful in 3m11s
Rust CI / test (1.90.0 / --features ristretto255 / --features serde) (push) Successful in 3m28s
Rust CI / test (stable / --features ristretto255 / --features serde) (push) Successful in 3m32s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / no frontend) (push) Successful in 5m26s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / no frontend) (push) Successful in 5m17s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / --features argon2) (push) Successful in 5m27s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / --features serde) (push) Successful in 5m43s
Rust CI / test (stable / --features ristretto255,curve25519,ecdsa,ed25519 / --features argon2) (push) Successful in 5m20s
Rust CI / test (1.90.0 / --features ristretto255,curve25519,ecdsa,ed25519 / --features serde) (push) Successful in 6m1s
Rust CI / test (stable / --features ristretto255,kem / no frontend) (push) Successful in 4m0s
Rust CI / test (1.90.0 / --features ristretto255,kem / --features argon2) (push) Successful in 4m5s
Rust CI / test (1.90.0 / --features ristretto255,kem / no frontend) (push) Successful in 4m2s
Rust CI / test (stable / --features ristretto255,kem / --features argon2) (push) Successful in 4m3s
Rust CI / test (stable / --features ristretto255,kem / --features serde) (push) Successful in 4m32s
Rust CI / test (1.90.0 / --features ristretto255,kem / --features serde) (push) Successful in 4m31s
Rust CI / test simple_login example (push) Successful in 19s
Rust CI / test digital_locker example (push) Successful in 18s
Rust CI / cargo bench compilation () (push) Successful in 1m47s
Rust CI / cargo bench compilation (--features ristretto255) (push) Successful in 1m55s
Rust CI / cargo bench compilation (--features ristretto255,kem) (push) Successful in 2m35s
Rust CI / no-std (thumbv6m-none-eabi / no backend) (push) Successful in 28s
Rust CI / no-std (wasm32-unknown-unknown / no backend) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / curve25519) (push) Successful in 18s
Rust CI / no-std (wasm32-unknown-unknown / curve25519) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ecdsa) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ecdsa) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ed25519) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ed25519) (push) Successful in 30s
Rust CI / no-std (thumbv6m-none-eabi / ristretto255) (push) Successful in 28s
Rust CI / no-std (wasm32-unknown-unknown / ristretto255) (push) Successful in 28s
Rust CI / no-std (thumbv6m-none-eabi / ristretto255,curve25519,ecdsa,ed25519) (push) Successful in 29s
Rust CI / no-std (wasm32-unknown-unknown / ristretto255,curve25519,ecdsa,ed25519) (push) Successful in 19s
Upgrade all core cryptographic dependencies to their latest versions: Dependencies: - digest: 0.10 to 0.11 - elliptic-curve: 0.13 to 0.14 - hkdf: 0.12 to 0.13 - hmac: 0.12 to 0.13 - rand: 0.8 to 0.10 - rand_chacha: 0.3 to 0.10 - sha2: 0.10 to 0.11 - getrandom: 0.2 to 0.4 (WASM) - ml-kem: 0.3.0-rc.0 to 0.3 - ecdsa: 0.16 to 0.17.0-rc.23 - rfc6979: 0.4 to 0.6 (now internal to ecdsa) - p256/p384/p521: 0.13 to 0.14.0-rc.15 - curve25519-dalek: 4 to 5.0.0-rc - ed25519-dalek: 2 to 3.0.0-rc - cryptoki: 0.9 to 0.12 - rustyline: 17 to 18 - scrypt: 0.11 to 0.12 - voprf replaced by voprf-vx 1.0.0-pre.0 Migration changes: - generic-array 0.14 to 1.4 with hybrid-array 0.4 interop - ArrayLength<u8> to ArrayLength (generic-array 1.x) - Added ConcatExt trait to disambiguate from [T]::concat - Replaced Hmac with SimpleHmac for digest 0.11 compatibility - Added OutputSize<H>: ArrayLength bounds throughout Hash trait - Converted hybrid_array::Array between GenericArray at API boundaries - Updated GroupEncoding Repr bound to hybrid_array::Array - ECDSA sign now uses ecdsa::hazmat::sign_prehashed_rfc6979 - Removed direct rfc6979 dependency (handled by ecdsa internally) - Replaced bincode with postcard for no_std serialization - Re-exported hybrid_array from crate root Other changes: - Renamed crate to opaque-vx - Increased MSRV to 1.89 - Added cryptography to Cargo.toml categories - Removed Facebook-specific contributions from CONTRIBUTING.md - Removed v3 to v4 migration test - Removed unstable rustfmt configurations for stable compatibility Reviewed-on: #1 Co-authored-by: UneBaguette <[email protected]> Co-committed-by: UneBaguette <[email protected]>
This commit was merged in pull request #1.
This commit is contained in:
@@ -14,7 +14,7 @@ use curve25519_dalek::scalar;
|
||||
use curve25519_dalek::traits::IsIdentity;
|
||||
use generic_array::GenericArray;
|
||||
use generic_array::typenum::U32;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use subtle::ConstantTimeEq;
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
@@ -43,7 +43,7 @@ impl Group for Curve25519 {
|
||||
.and_then(|bytes| NonIdentity::from_bytes(bytes.into()))
|
||||
}
|
||||
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
fn random_sk<R: Rng + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
// Sample 32 random bytes and then clamp, as described in https://cr.yp.to/ecdh.html
|
||||
let mut scalar_bytes = [0u8; 32];
|
||||
rng.fill_bytes(&mut scalar_bytes);
|
||||
|
||||
@@ -18,9 +18,8 @@ pub use ed25519_dalek;
|
||||
use ed25519_dalek::hazmat::ExpandedSecretKey;
|
||||
use ed25519_dalek::{SecretKey, Sha512};
|
||||
use generic_array::GenericArray;
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{U32, U64};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
use super::Group;
|
||||
@@ -30,7 +29,7 @@ use crate::key_exchange::sigma_i::hash_eddsa::implementation::HashEddsaImpl;
|
||||
use crate::key_exchange::sigma_i::pure_eddsa::implementation::PureEddsaImpl;
|
||||
pub use crate::key_exchange::sigma_i::shared::PreHash;
|
||||
use crate::key_exchange::sigma_i::{CachedMessage, Message, MessageBuilder};
|
||||
use crate::serialization::{SliceExt, UpdateExt};
|
||||
use crate::serialization::{ConcatExt, SliceExt, UpdateExt};
|
||||
|
||||
/// Implementation for Ed25519.
|
||||
pub struct Ed25519;
|
||||
@@ -46,12 +45,12 @@ impl Group for Ed25519 {
|
||||
}
|
||||
|
||||
fn deserialize_take_pk(bytes: &mut &[u8]) -> Result<Self::Pk, ProtocolError> {
|
||||
let bytes = bytes.take_array("public key")?;
|
||||
let bytes = bytes.take_array::<U32>("public key")?;
|
||||
|
||||
VerifyingKey::from_bytes(bytes.into())
|
||||
}
|
||||
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
fn random_sk<R: Rng + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
let mut sk = <[u8; 32]>::default();
|
||||
rng.fill_bytes(&mut sk);
|
||||
|
||||
@@ -72,7 +71,7 @@ impl Group for Ed25519 {
|
||||
|
||||
fn deserialize_take_sk(bytes: &mut &[u8]) -> Result<Self::Sk, ProtocolError> {
|
||||
Ok(SigningKey::from_bytes(
|
||||
bytes.take_array("secret key")?.into(),
|
||||
bytes.take_array::<U32>("secret key")?.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -399,7 +398,7 @@ pub struct Signature {
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
/// Expects the `R` and `s` components of a Ed25519 signature with no added
|
||||
/// Expects the `R` and `s` components of an Ed25519 signature with no added
|
||||
/// framing.
|
||||
pub fn from_slice(mut bytes: &[u8]) -> Result<Self, ProtocolError> {
|
||||
Self::deserialize_take(&mut bytes)
|
||||
@@ -407,9 +406,9 @@ impl Signature {
|
||||
|
||||
fn deserialize_take(bytes: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
#[allow(non_snake_case)]
|
||||
let R = CompressedEdwardsY(bytes.take_array("signature R")?.into());
|
||||
let R = CompressedEdwardsY(bytes.take_array::<U32>("signature R")?.into());
|
||||
|
||||
let s = Scalar::from_canonical_bytes(bytes.take_array("signature s")?.into())
|
||||
let s = Scalar::from_canonical_bytes(bytes.take_array::<U32>("signature s")?.into())
|
||||
.into_option()
|
||||
.ok_or(ProtocolError::SerializationError)?;
|
||||
|
||||
@@ -417,7 +416,8 @@ impl Signature {
|
||||
}
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, U64> {
|
||||
GenericArray::from(self.R.0).concat(GenericArray::from(self.s.to_bytes()))
|
||||
GenericArray::<u8, U32>::from(self.R.0)
|
||||
.cat(GenericArray::<u8, U32>::from(self.s.to_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,17 +433,18 @@ mod test {
|
||||
use std::iter;
|
||||
|
||||
use ed25519_dalek::{Signer, SigningKey, Verifier, VerifyingKey};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::rngs::SysRng;
|
||||
use rand_core::UnwrapErr;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pure_eddsa() {
|
||||
let mut message = [0; 1024];
|
||||
OsRng.fill_bytes(&mut message);
|
||||
UnwrapErr(SysRng).fill_bytes(&mut message);
|
||||
|
||||
let mut sk = SecretKey::default();
|
||||
OsRng.fill_bytes(&mut sk);
|
||||
UnwrapErr(SysRng).fill_bytes(&mut sk);
|
||||
let signing_key = SigningKey::from_bytes(&sk);
|
||||
|
||||
let signature = signing_key.sign(&message);
|
||||
@@ -472,12 +473,12 @@ mod test {
|
||||
#[test]
|
||||
fn hash_eddsa() {
|
||||
let mut message = [0; 1024];
|
||||
OsRng.fill_bytes(&mut message);
|
||||
UnwrapErr(SysRng).fill_bytes(&mut message);
|
||||
let message = Sha512::new_with_prefix(message);
|
||||
let pre_hash = message.clone().finalize();
|
||||
|
||||
let mut sk = SecretKey::default();
|
||||
OsRng.fill_bytes(&mut sk);
|
||||
UnwrapErr(SysRng).fill_bytes(&mut sk);
|
||||
let signing_key = SigningKey::from_bytes(&sk);
|
||||
|
||||
let signature = signing_key.sign_prehashed(message.clone(), None).unwrap();
|
||||
|
||||
@@ -8,17 +8,18 @@
|
||||
|
||||
//! Implementation for EC curves via [`elliptic_curve`] traits.
|
||||
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
|
||||
use derive_where::derive_where;
|
||||
use core::ops::Mul;
|
||||
use digest::OutputSizeUser;
|
||||
use digest::block_api::BlockSizeUser;
|
||||
use elliptic_curve::group::GroupEncoding;
|
||||
use elliptic_curve::ops::MulByGenerator;
|
||||
use elliptic_curve::sec1::{ModulusSize, ToEncodedPoint};
|
||||
use elliptic_curve::point::NonIdentity;
|
||||
use elliptic_curve::sec1::{ModulusSize, ToSec1Point};
|
||||
use elliptic_curve::{
|
||||
CurveArithmetic, FieldBytesSize, NonZeroScalar, ProjectivePoint, Scalar, SecretKey, point,
|
||||
CurveArithmetic, FieldBytesSize, Generate, NonZeroScalar, ProjectivePoint, Scalar, SecretKey,
|
||||
};
|
||||
use generic_array::GenericArray;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use generic_array::typenum::{IsGreaterOrEqual, IsLess, IsLessOrEqual, Prod, True, U2, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use voprf::Mode;
|
||||
|
||||
use super::{Group, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
|
||||
@@ -29,15 +30,27 @@ use crate::serialization::SliceExt;
|
||||
impl<G> Group for G
|
||||
where
|
||||
Self: CurveArithmetic + voprf::CipherSuite<Group = Self> + voprf::Group<Scalar = Scalar<Self>>,
|
||||
FieldBytesSize<Self>: ModulusSize,
|
||||
FieldBytesSize<Self>: ModulusSize + ArrayLength,
|
||||
<FieldBytesSize<Self> as ModulusSize>::CompressedPointSize: ArrayLength,
|
||||
ProjectivePoint<Self>: GroupEncoding<
|
||||
Repr = GenericArray<u8, <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize>,
|
||||
> + ToEncodedPoint<Self>,
|
||||
Repr = hybrid_array::Array<
|
||||
u8,
|
||||
<FieldBytesSize<Self> as ModulusSize>::CompressedPointSize,
|
||||
>,
|
||||
> + ToSec1Point<Self>,
|
||||
// Bounds required by voprf::CipherSuite
|
||||
<Self as voprf::Group>::SecurityLevel: Mul<U2>,
|
||||
<<Self as voprf::CipherSuite>::Hash as OutputSizeUser>::OutputSize: ArrayLength
|
||||
+ IsLess<U256>
|
||||
+ IsLessOrEqual<
|
||||
<<Self as voprf::CipherSuite>::Hash as BlockSizeUser>::BlockSize,
|
||||
Output = True,
|
||||
> + IsGreaterOrEqual<Prod<<Self as voprf::Group>::SecurityLevel, U2>, Output = True>,
|
||||
{
|
||||
// We don't use `elliptic_curve::PublicKey` because it stores its internals in a
|
||||
// format ideal for serialization and not computation. This is inconsistent with
|
||||
// our other implementations.
|
||||
type Pk = NonIdentity<Self>;
|
||||
type Pk = NonIdentity<ProjectivePoint<Self>>;
|
||||
|
||||
type PkLen = <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize;
|
||||
|
||||
@@ -46,18 +59,19 @@ where
|
||||
type SkLen = FieldBytesSize<Self>;
|
||||
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
GenericArray::clone_from_slice(pk.0.to_encoded_point(true).as_bytes())
|
||||
GenericArray::from_slice(pk.to_sec1_point(true).as_bytes()).clone()
|
||||
}
|
||||
|
||||
fn deserialize_take_pk(bytes: &mut &[u8]) -> Result<Self::Pk, ProtocolError> {
|
||||
point::NonIdentity::<ProjectivePoint<Self>>::from_bytes(&bytes.take_array("public key")?)
|
||||
.into_option()
|
||||
.map(NonIdentity)
|
||||
.ok_or(ProtocolError::SerializationError)
|
||||
NonIdentity::<ProjectivePoint<Self>>::from_bytes(
|
||||
&bytes.take_array("public key")?.into_ha0_4(),
|
||||
)
|
||||
.into_option()
|
||||
.ok_or(ProtocolError::SerializationError)
|
||||
}
|
||||
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
SecretKey::<Self>::random(rng)
|
||||
fn random_sk<R: Rng + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
SecretKey::<Self>::generate_from_rng(rng)
|
||||
}
|
||||
|
||||
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError> {
|
||||
@@ -70,21 +84,15 @@ where
|
||||
}
|
||||
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk {
|
||||
// Non-panicking version in https://github.com/RustCrypto/traits/pull/1833.
|
||||
NonIdentity(
|
||||
point::NonIdentity::new(ProjectivePoint::<Self>::mul_by_generator(
|
||||
&sk.to_nonzero_scalar(),
|
||||
))
|
||||
.expect("multiplying with a non-zero scalar can never yield the identity element"),
|
||||
)
|
||||
NonIdentity::<ProjectivePoint<Self>>::mul_by_generator(&sk.to_nonzero_scalar())
|
||||
}
|
||||
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.to_bytes()
|
||||
GenericArray::from(sk.to_bytes())
|
||||
}
|
||||
|
||||
fn deserialize_take_sk(bytes: &mut &[u8]) -> Result<Self::Sk, ProtocolError> {
|
||||
SecretKey::<Self>::from_bytes(&bytes.take_array("secret key")?)
|
||||
SecretKey::<Self>::from_bytes(&bytes.take_array("secret key")?.into_ha0_4())
|
||||
.map_err(|_| ProtocolError::SerializationError)
|
||||
}
|
||||
}
|
||||
@@ -92,51 +100,26 @@ where
|
||||
impl<G> DiffieHellman<G> for SecretKey<G>
|
||||
where
|
||||
G: CurveArithmetic + voprf::CipherSuite<Group = G> + voprf::Group<Scalar = Scalar<G>>,
|
||||
FieldBytesSize<G>: ModulusSize,
|
||||
FieldBytesSize<G>: ModulusSize + ArrayLength,
|
||||
<FieldBytesSize<G> as ModulusSize>::CompressedPointSize: ArrayLength,
|
||||
ProjectivePoint<G>: GroupEncoding<
|
||||
Repr = GenericArray<u8, <FieldBytesSize<G> as ModulusSize>::CompressedPointSize>,
|
||||
> + ToEncodedPoint<G>,
|
||||
Repr = hybrid_array::Array<u8, <FieldBytesSize<G> as ModulusSize>::CompressedPointSize>,
|
||||
> + ToSec1Point<G>,
|
||||
<G as voprf::Group>::SecurityLevel: Mul<U2>,
|
||||
<<G as voprf::CipherSuite>::Hash as OutputSizeUser>::OutputSize: ArrayLength
|
||||
+ IsLess<U256>
|
||||
+ IsLessOrEqual<<<G as voprf::CipherSuite>::Hash as BlockSizeUser>::BlockSize, Output = True>
|
||||
+ IsGreaterOrEqual<Prod<<G as voprf::Group>::SecurityLevel, U2>, Output = True>,
|
||||
{
|
||||
fn diffie_hellman(
|
||||
&self,
|
||||
pk: &NonIdentity<G>,
|
||||
pk: &NonIdentity<ProjectivePoint<G>>,
|
||||
) -> GenericArray<u8, <FieldBytesSize<G> as ModulusSize>::CompressedPointSize> {
|
||||
GenericArray::clone_from_slice(
|
||||
(pk.0 * self.to_nonzero_scalar())
|
||||
.to_encoded_point(true)
|
||||
GenericArray::from_slice(
|
||||
(pk * self.to_nonzero_scalar())
|
||||
.to_sec1_point(true)
|
||||
.as_bytes(),
|
||||
)
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper around [`NonIdentity`](point::NonIdentity) to [`Eq`].
|
||||
// TODO: remove after https://github.com/RustCrypto/traits/pull/1834.
|
||||
#[derive_where(Clone, Copy)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(
|
||||
bound(
|
||||
deserialize = "point::NonIdentity<ProjectivePoint<G>>: serde::Deserialize<'de>",
|
||||
serialize = "point::NonIdentity<ProjectivePoint<G>>: serde::Serialize"
|
||||
),
|
||||
transparent
|
||||
)
|
||||
)]
|
||||
pub struct NonIdentity<G: CurveArithmetic>(pub point::NonIdentity<ProjectivePoint<G>>);
|
||||
|
||||
impl<G: CurveArithmetic> Debug for NonIdentity<G> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("NonIdentity")
|
||||
.field(&self.0.to_point())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: CurveArithmetic> PartialEq for NonIdentity<G> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.to_point().eq(&other.0.to_point())
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: CurveArithmetic> Eq for NonIdentity<G> {}
|
||||
|
||||
@@ -17,7 +17,8 @@ pub mod elliptic_curve;
|
||||
pub mod ristretto255;
|
||||
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use hybrid_array::ArraySize;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
use crate::errors::{InternalError, ProtocolError};
|
||||
@@ -29,11 +30,11 @@ pub trait Group {
|
||||
/// Public key
|
||||
type Pk: Clone;
|
||||
/// Length of the public key
|
||||
type PkLen: ArrayLength<u8>;
|
||||
type PkLen: ArrayLength + ArraySize;
|
||||
/// Secret key
|
||||
type Sk: Clone + ZeroizeOnDrop;
|
||||
/// Length of the secret key
|
||||
type SkLen: ArrayLength<u8>;
|
||||
type SkLen: ArrayLength + ArraySize;
|
||||
|
||||
/// Serializes `self`
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen>;
|
||||
@@ -44,7 +45,7 @@ pub trait Group {
|
||||
fn deserialize_take_pk(bytes: &mut &[u8]) -> Result<Self::Pk, ProtocolError>;
|
||||
|
||||
/// Generate a random secret key
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk;
|
||||
fn random_sk<R: Rng + CryptoRng>(rng: &mut R) -> Self::Sk;
|
||||
|
||||
/// Deterministically derive a [`Self::Sk`] from `seed`.
|
||||
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError>;
|
||||
|
||||
@@ -13,11 +13,12 @@ use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
|
||||
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::IsIdentity;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::block_api::BlockSizeUser;
|
||||
use digest::{FixedOutput, HashMarker};
|
||||
use generic_array::GenericArray;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U32, U256};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use generic_array::typenum::{IsGreaterOrEqual, IsLess, IsLessOrEqual, Prod, True, U2, U32, U256};
|
||||
use hybrid_array::Array;
|
||||
use rand::{CryptoRng, Rng, TryCryptoRng, TryRng};
|
||||
use voprf::Mode;
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
@@ -42,15 +43,19 @@ impl Group for Ristretto255 {
|
||||
}
|
||||
|
||||
fn deserialize_take_pk(bytes: &mut &[u8]) -> Result<Self::Pk, ProtocolError> {
|
||||
CompressedRistretto(bytes.take_array("public key")?.into())
|
||||
CompressedRistretto(bytes.take_array::<U32>("public key")?.into())
|
||||
.decompress()
|
||||
.ok_or(ProtocolError::SerializationError)
|
||||
.and_then(NonIdentity::from_point)
|
||||
}
|
||||
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
fn random_sk<R: Rng + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
loop {
|
||||
let scalar = Scalar::random(rng);
|
||||
let mut bytes = [0u8; 64];
|
||||
|
||||
rng.fill_bytes(&mut bytes);
|
||||
|
||||
let scalar = Scalar::from_bytes_mod_order_wide(&bytes);
|
||||
|
||||
if scalar != Scalar::ZERO {
|
||||
break NonZeroScalar(scalar);
|
||||
@@ -73,7 +78,7 @@ impl Group for Ristretto255 {
|
||||
}
|
||||
|
||||
fn deserialize_take_sk(bytes: &mut &[u8]) -> Result<Self::Sk, ProtocolError> {
|
||||
Scalar::from_canonical_bytes(bytes.take_array("secret key")?.into())
|
||||
Scalar::from_canonical_bytes(bytes.take_array::<U32>("secret key")?.into())
|
||||
.into_option()
|
||||
.ok_or(ProtocolError::SerializationError)
|
||||
.and_then(NonZeroScalar::from_scalar)
|
||||
@@ -149,7 +154,7 @@ where
|
||||
}
|
||||
|
||||
impl voprf::CipherSuite for Ristretto255 {
|
||||
const ID: &'static str = voprf::Ristretto255::ID;
|
||||
const ID: &'static [u8] = voprf::Ristretto255::ID;
|
||||
|
||||
type Group = <voprf::Ristretto255 as voprf::CipherSuite>::Group;
|
||||
|
||||
@@ -165,13 +170,17 @@ impl voprf::Group for Ristretto255 {
|
||||
|
||||
type ScalarLen = <voprf::Ristretto255 as voprf::Group>::ScalarLen;
|
||||
|
||||
type SecurityLevel = <voprf::Ristretto255 as voprf::Group>::SecurityLevel;
|
||||
|
||||
fn hash_to_curve<H>(
|
||||
input: &[&[u8]],
|
||||
dst: &[&[u8]],
|
||||
) -> voprf::Result<Self::Elem, voprf::InternalError>
|
||||
where
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
H::OutputSize: IsLess<U256>
|
||||
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||
+ IsGreaterOrEqual<Prod<<Self as voprf::Group>::SecurityLevel, U2>, Output = True>,
|
||||
{
|
||||
<voprf::Ristretto255 as voprf::Group>::hash_to_curve::<H>(input, dst)
|
||||
}
|
||||
@@ -182,7 +191,9 @@ impl voprf::Group for Ristretto255 {
|
||||
) -> voprf::Result<Self::Scalar, voprf::InternalError>
|
||||
where
|
||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize>,
|
||||
H::OutputSize: IsLess<U256>
|
||||
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||
+ IsGreaterOrEqual<Prod<<Self as voprf::Group>::SecurityLevel, U2>, Output = True>,
|
||||
{
|
||||
<voprf::Ristretto255 as voprf::Group>::hash_to_scalar::<H>(input, dst)
|
||||
}
|
||||
@@ -195,7 +206,7 @@ impl voprf::Group for Ristretto255 {
|
||||
<voprf::Ristretto255 as voprf::Group>::identity_elem()
|
||||
}
|
||||
|
||||
fn serialize_elem(elem: Self::Elem) -> GenericArray<u8, Self::ElemLen> {
|
||||
fn serialize_elem(elem: Self::Elem) -> Array<u8, Self::ElemLen> {
|
||||
<voprf::Ristretto255 as voprf::Group>::serialize_elem(elem)
|
||||
}
|
||||
|
||||
@@ -203,7 +214,7 @@ impl voprf::Group for Ristretto255 {
|
||||
<voprf::Ristretto255 as voprf::Group>::deserialize_elem(element_bits)
|
||||
}
|
||||
|
||||
fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
|
||||
fn random_scalar<R: TryRng + TryCryptoRng>(rng: &mut R) -> voprf::Result<Self::Scalar> {
|
||||
<voprf::Ristretto255 as voprf::Group>::random_scalar(rng)
|
||||
}
|
||||
|
||||
@@ -215,7 +226,7 @@ impl voprf::Group for Ristretto255 {
|
||||
<voprf::Ristretto255 as voprf::Group>::is_zero_scalar(scalar)
|
||||
}
|
||||
|
||||
fn serialize_scalar(scalar: Self::Scalar) -> GenericArray<u8, Self::ScalarLen> {
|
||||
fn serialize_scalar(scalar: Self::Scalar) -> Array<u8, Self::ScalarLen> {
|
||||
<voprf::Ristretto255 as voprf::Group>::serialize_scalar(scalar)
|
||||
}
|
||||
|
||||
|
||||
+32
-22
@@ -21,11 +21,12 @@ use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::Output;
|
||||
use digest::core_api::{BlockSizeUser, CoreProxy};
|
||||
use digest::block_api::{CoreProxy, SmallBlockSizeUser};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, Le, NonZero, Sum, U2, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use hybrid_array::Array;
|
||||
use rand::{CryptoRng, Rng};
|
||||
use voprf::{BlindedElement, EvaluationElement};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
@@ -33,7 +34,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use crate::ciphersuite::KeHash;
|
||||
use crate::ciphersuite::{CipherSuite, OprfGroup};
|
||||
use crate::errors::ProtocolError;
|
||||
use crate::hash::{Hash, ProxyHash};
|
||||
use crate::hash::{Hash, OutputSize, ProxyHash};
|
||||
use crate::key_exchange::group::Group;
|
||||
use crate::key_exchange::shared::{NonceLen, STR_CONTEXT};
|
||||
use crate::keypair::{PrivateKey, PublicKey};
|
||||
@@ -44,8 +45,9 @@ use crate::serialization::{SliceExt, i2osp};
|
||||
pub trait KeyExchange
|
||||
where
|
||||
<Self::Hash as CoreProxy>::Core: ProxyHash,
|
||||
<<Self::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<<Self::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<Self::Hash as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<Self::Hash as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<Self::Hash>: ArrayLength,
|
||||
{
|
||||
/// The group used for the key exchange.
|
||||
type Group: Group;
|
||||
@@ -71,12 +73,12 @@ where
|
||||
|
||||
/// Client generates [`KE1Message`](Self::KE1Message) and
|
||||
/// [`KE1State`](Self::KE1State).
|
||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||
fn generate_ke1<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<GenerateKe1Result<Self>, ProtocolError>;
|
||||
|
||||
/// Server generates [`KE2Builder`](Self::KE2Builder).
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -92,7 +94,7 @@ where
|
||||
) -> Self::KE2BuilderData<'a, CS>;
|
||||
|
||||
/// Server generates the input without a remote key.
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
builder: &Self::KE2Builder<'_, CS>,
|
||||
rng: &mut R,
|
||||
server_s_sk: &PrivateKey<Self::Group>,
|
||||
@@ -107,7 +109,7 @@ where
|
||||
|
||||
/// Client generates [`KE3Message`](Self::KE3Message) and the session key.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -137,7 +139,7 @@ where
|
||||
)]
|
||||
#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize)]
|
||||
pub struct SerializedCredentialRequest<CS: CipherSuite>(
|
||||
GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||
Array<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||
);
|
||||
|
||||
impl<CS: CipherSuite> SerializedCredentialRequest<CS> {
|
||||
@@ -154,17 +156,20 @@ impl<CS: CipherSuite> SerializedCredentialRequest<CS> {
|
||||
/// Returns a [`SerializedCredentialRequest`] deserialized from the given
|
||||
/// `bytes`.
|
||||
pub fn deserialize_take(bytes: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self(bytes.take_array("blinded element")?))
|
||||
Ok(Self(bytes.take_array("blinded element")?.into_ha0_4()))
|
||||
}
|
||||
}
|
||||
|
||||
type SerializedCredentialRequestLen<CS: CipherSuite> = <OprfGroup<CS> as voprf::Group>::ElemLen;
|
||||
|
||||
impl<CS: CipherSuite> Serialize for SerializedCredentialRequest<CS> {
|
||||
impl<CS: CipherSuite> Serialize for SerializedCredentialRequest<CS>
|
||||
where
|
||||
<OprfGroup<CS> as voprf::Group>::ElemLen: ArrayLength,
|
||||
{
|
||||
type Len = SerializedCredentialRequestLen<CS>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.0.clone()
|
||||
GenericArray::from_slice(self.0.as_slice()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +181,7 @@ impl<CS: CipherSuite> Serialize for SerializedCredentialRequest<CS> {
|
||||
)]
|
||||
#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
pub struct SerializedCredentialResponse<CS: CipherSuite> {
|
||||
evaluation_element: GenericArray<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||
evaluation_element: Array<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>,
|
||||
masking_nonce: GenericArray<u8, NonceLen>,
|
||||
masked_response: MaskedResponse<CS>,
|
||||
}
|
||||
@@ -207,7 +212,7 @@ impl<CS: CipherSuite> SerializedCredentialResponse<CS> {
|
||||
/// `bytes`.
|
||||
pub fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
evaluation_element: input.take_array("evaluation element")?,
|
||||
evaluation_element: input.take_array("evaluation element")?.into_ha0_4(),
|
||||
masking_nonce: input.take_array("masking nonce")?,
|
||||
masked_response: MaskedResponse::deserialize_take(input)?,
|
||||
})
|
||||
@@ -221,16 +226,21 @@ impl<CS: CipherSuite> Serialize for SerializedCredentialResponse<CS>
|
||||
where
|
||||
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
||||
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
||||
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
||||
SerializedCredentialResponseLen<CS>: ArrayLength<u8>,
|
||||
ArrayLength + Add<MaskedResponseLen<CS>>,
|
||||
SerializedCredentialResponseLen<CS>: ArrayLength,
|
||||
{
|
||||
type Len = SerializedCredentialResponseLen<CS>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.evaluation_element
|
||||
.clone()
|
||||
.concat(self.masking_nonce)
|
||||
.concat(self.masked_response.serialize())
|
||||
let elem = GenericArray::<u8, <OprfGroup<CS> as voprf::Group>::ElemLen>::from_slice(
|
||||
self.evaluation_element.as_slice(),
|
||||
)
|
||||
.clone();
|
||||
|
||||
Concat::concat(
|
||||
Concat::concat(elem, self.masking_nonce),
|
||||
self.masked_response.serialize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +369,7 @@ pub trait Deserialize: Sized {
|
||||
/// Serialization trait for key exchange types.
|
||||
pub trait Serialize {
|
||||
/// The length of the serialized types.
|
||||
type Len: ArrayLength<u8>;
|
||||
type Len: ArrayLength;
|
||||
|
||||
/// Serialize [`Self`] to a fixed-length byte array.
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len>;
|
||||
|
||||
+45
-34
@@ -9,14 +9,15 @@
|
||||
use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::block_api::{CoreProxy, SmallBlockSizeUser};
|
||||
use digest::{Digest, Mac, Output, OutputSizeUser, Update};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, Le, NonZero, Sum, U1, U2, U32, U256, Unsigned};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use hkdf::{Hkdf, HkdfExtract};
|
||||
use hmac::Hmac;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use hkdf::SimpleHkdf as Hkdf;
|
||||
use hkdf::SimpleHkdfExtract as HkdfExtract;
|
||||
use hmac::{KeyInit, SimpleHmac};
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
use super::{
|
||||
Deserialize, GenerateKe1Result, KeyExchange, Serialize, SerializedContext,
|
||||
@@ -106,8 +107,9 @@ pub(super) struct DerivedKeys<H: OutputSizeUser> {
|
||||
pub(super) struct Ke2BuilderCommon<G: Group, H: Hash>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
G::Sk: DiffieHellman<G>,
|
||||
{
|
||||
pub(super) server_nonce: GenericArray<u8, NonceLen>,
|
||||
@@ -126,7 +128,7 @@ where
|
||||
// Helper functions
|
||||
|
||||
pub(super) fn generate_ke1<
|
||||
R: RngCore + CryptoRng,
|
||||
R: Rng + CryptoRng,
|
||||
KE: KeyExchange<KE1State = Ke1State<G>, KE1Message = Ke1Message<G>>,
|
||||
G: Group,
|
||||
>(
|
||||
@@ -150,7 +152,7 @@ pub(super) fn generate_ke1<
|
||||
}
|
||||
|
||||
// Generate a random nonce up to NonceLen::USIZE bytes.
|
||||
pub(super) fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, NonceLen> {
|
||||
pub(super) fn generate_nonce<R: Rng + CryptoRng>(rng: &mut R) -> GenericArray<u8, NonceLen> {
|
||||
let mut nonce_bytes = GenericArray::default();
|
||||
rng.fill_bytes(&mut nonce_bytes);
|
||||
nonce_bytes
|
||||
@@ -190,11 +192,12 @@ pub(super) fn ke2_builder_common<'a, G, H, CS, R>(
|
||||
where
|
||||
G: Group,
|
||||
H: Hash,
|
||||
R: RngCore + CryptoRng,
|
||||
R: Rng + CryptoRng,
|
||||
CS: CipherSuite,
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
G::Sk: DiffieHellman<G>,
|
||||
CS::KeyExchange: KeyExchange<Group = G, Hash = H>,
|
||||
{
|
||||
@@ -238,8 +241,9 @@ pub(super) fn derive_keys<'a, H: Hash>(
|
||||
) -> Result<DerivedKeys<H>, ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
let mut hkdf = HkdfExtract::<H>::new(None);
|
||||
|
||||
@@ -280,19 +284,20 @@ pub(super) fn compute_ke2_macs<H: Hash>(
|
||||
) -> Result<(Output<H>, Output<H>), ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
let mut mac_hasher =
|
||||
Hmac::<H>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
SimpleHmac::<H>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
Mac::update(&mut mac_hasher, transcript_digest);
|
||||
let mac = mac_hasher.finalize().into_bytes();
|
||||
|
||||
transcript_hasher.update(&mac);
|
||||
Update::update(transcript_hasher, &mac);
|
||||
let finalized_transcript = transcript_hasher.clone().finalize();
|
||||
|
||||
let mut expected_mac_hasher =
|
||||
Hmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
SimpleHmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
Mac::update(&mut expected_mac_hasher, &finalized_transcript);
|
||||
let expected_mac = expected_mac_hasher.finalize().into_bytes();
|
||||
|
||||
@@ -311,23 +316,24 @@ pub(super) fn finalize_ke3_transcript<'a, H: Hash>(
|
||||
) -> Result<(DerivedKeys<H>, Output<H>), ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
let transcript_digest = transcript_hasher.clone().finalize();
|
||||
let derived_keys = derive_keys::<H>(shared_secrets, &transcript_digest)?;
|
||||
let mut server_mac_hasher =
|
||||
Hmac::<H>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
SimpleHmac::<H>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
Mac::update(&mut server_mac_hasher, &transcript_digest);
|
||||
server_mac_hasher
|
||||
.verify(server_mac)
|
||||
.map_err(|_| ProtocolError::InvalidLoginError)?;
|
||||
|
||||
transcript_hasher.update(server_mac.as_slice());
|
||||
Update::update(transcript_hasher, server_mac);
|
||||
let finalized_transcript = transcript_hasher.clone().finalize();
|
||||
|
||||
let mut client_mac_hasher =
|
||||
Hmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
SimpleHmac::<H>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
Mac::update(&mut client_mac_hasher, &finalized_transcript);
|
||||
|
||||
let client_mac = client_mac_hasher.finalize().into_bytes();
|
||||
@@ -342,8 +348,9 @@ fn hkdf_expand_label<H: Hash>(
|
||||
) -> Result<Output<H>, ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
let h = Hkdf::<H>::from_prk(secret).map_err(|_| InternalError::HkdfError)?;
|
||||
hkdf_expand_label_extracted(&h, label, context)
|
||||
@@ -356,10 +363,11 @@ fn hkdf_expand_label_extracted<H: Hash>(
|
||||
) -> Result<Output<H>, ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
let mut okm = GenericArray::default();
|
||||
let mut okm = GenericArray::default().into_ha0_4();
|
||||
|
||||
let length = i2osp::<U2>(OutputSize::<H>::USIZE)?;
|
||||
let label_length = i2osp::<U1>(STR_OPAQUE.len() + label.len())?;
|
||||
@@ -386,8 +394,9 @@ fn derive_secrets<H: Hash>(
|
||||
) -> Result<Output<H>, ProtocolError>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
hkdf_expand_label_extracted::<H>(hkdf, label, hashed_derivation_transcript)
|
||||
}
|
||||
@@ -407,12 +416,14 @@ impl<G: Group> Serialize for Ke1State<G>
|
||||
where
|
||||
// Ke1State: KeSk + Nonce
|
||||
G::SkLen: Add<NonceLen>,
|
||||
Sum<G::SkLen, NonceLen>: ArrayLength<u8>,
|
||||
Sum<G::SkLen, NonceLen>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<G::SkLen, NonceLen>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.client_e_sk.serialize().concat(self.client_nonce)
|
||||
let a = self.client_e_sk.serialize();
|
||||
|
||||
GenericArray::concat(a, self.client_nonce)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +440,7 @@ impl<G: Group> Serialize for Ke1Message<G>
|
||||
where
|
||||
// Ke1Message: Nonce + KePk
|
||||
NonceLen: Add<G::PkLen>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength<u8>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<NonceLen, G::PkLen>;
|
||||
|
||||
@@ -476,7 +487,7 @@ impl<G: Group> Ke1MessageIter<G> {
|
||||
impl<G: Group> Ke1MessageIter<G>
|
||||
where
|
||||
NonceLen: Add<G::PkLen>,
|
||||
Ke1MessageIterLen<G>: ArrayLength<u8>,
|
||||
Ke1MessageIterLen<G>: ArrayLength,
|
||||
{
|
||||
pub(crate) fn serialize(&self) -> GenericArray<u8, Ke1MessageIterLen<G>> {
|
||||
self.client_nonce.concat(self.client_e_pk.clone())
|
||||
|
||||
@@ -11,23 +11,19 @@
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{FixedOutputReset, HashMarker};
|
||||
use ecdsa::{PrimeCurve, SignatureSize, hazmat};
|
||||
use elliptic_curve::{
|
||||
CurveArithmetic, Field, FieldBytes, FieldBytesEncoding, FieldBytesSize, PrimeField, Scalar,
|
||||
SecretKey,
|
||||
};
|
||||
use digest::block_api::{BlockSizeUser, EagerHash};
|
||||
use digest::{Digest, FixedOutputReset, HashMarker};
|
||||
use ecdsa::{EcdsaCurve, SignatureSize};
|
||||
use elliptic_curve::point::NonIdentity;
|
||||
use elliptic_curve::{CurveArithmetic, FieldBytes, ProjectivePoint, SecretKey};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use zeroize::Zeroize;
|
||||
use hybrid_array::ArraySize;
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
use super::{Message, MessageBuilder, SignatureProtocol};
|
||||
use crate::ciphersuite::CipherSuite;
|
||||
use crate::errors::ProtocolError;
|
||||
use crate::key_exchange::group::Group;
|
||||
use crate::key_exchange::group::elliptic_curve::NonIdentity;
|
||||
pub use crate::key_exchange::sigma_i::shared::PreHash;
|
||||
use crate::serialization::SliceExt;
|
||||
|
||||
@@ -39,23 +35,21 @@ pub struct Ecdsa<G, H>(PhantomData<(G, H)>);
|
||||
|
||||
impl<G, H> SignatureProtocol for Ecdsa<G, H>
|
||||
where
|
||||
G: CurveArithmetic + Group<Sk = SecretKey<G>, Pk = NonIdentity<G>> + PrimeCurve,
|
||||
SignatureSize<G>: ArrayLength<u8>,
|
||||
H: Clone
|
||||
+ Default
|
||||
+ BlockSizeUser
|
||||
+ FixedOutputReset<OutputSize = FieldBytesSize<G>>
|
||||
+ HashMarker,
|
||||
G: CurveArithmetic
|
||||
+ Group<Sk = SecretKey<G>, Pk = NonIdentity<ProjectivePoint<G>>>
|
||||
+ EcdsaCurve,
|
||||
SignatureSize<G>: ArrayLength + ArraySize,
|
||||
H: EagerHash + FixedOutputReset + BlockSizeUser + HashMarker + Digest + Clone + Default,
|
||||
{
|
||||
type Group = G;
|
||||
type Signature = Signature<G>;
|
||||
type Signature = ecdsa::Signature<G>;
|
||||
type SignatureLen = SignatureSize<G>;
|
||||
type VerifyState<CS: CipherSuite, KE: Group> = PreHash<H>;
|
||||
|
||||
// We use a manual implementation of `RandomizedPrehashSigner` to use the same
|
||||
// hash for the message as for generating `k`. See
|
||||
// https://github.com/RustCrypto/signatures/issues/949.
|
||||
fn sign<'a, R: CryptoRng + RngCore, CS: CipherSuite, KE: Group>(
|
||||
fn sign<'a, R: CryptoRng + Rng, CS: CipherSuite, KE: Group>(
|
||||
sk: &<Self::Group as Group>::Sk,
|
||||
rng: &mut R,
|
||||
message: &Message<CS, KE>,
|
||||
@@ -63,7 +57,7 @@ where
|
||||
let hash = message.hash::<H>();
|
||||
|
||||
(
|
||||
Signature(sign::<_, G, H>(sk, rng, &hash.sign.finalize_fixed())),
|
||||
sign::<_, G, H>(sk, rng, &hash.sign.finalize_fixed()),
|
||||
PreHash(hash.verify.finalize_fixed()),
|
||||
)
|
||||
}
|
||||
@@ -74,96 +68,55 @@ where
|
||||
state: Self::VerifyState<CS, KE>,
|
||||
signature: &Self::Signature,
|
||||
) -> Result<(), ProtocolError> {
|
||||
verify(pk, &state.0, &signature.0)
|
||||
verify(pk, &state.0, signature)
|
||||
}
|
||||
|
||||
fn serialize_signature(signature: &Self::Signature) -> GenericArray<u8, Self::SignatureLen> {
|
||||
signature.0.to_bytes()
|
||||
GenericArray::from_slice(signature.to_bytes().as_slice()).clone()
|
||||
}
|
||||
|
||||
fn deserialize_take_signature(bytes: &mut &[u8]) -> Result<Self::Signature, ProtocolError> {
|
||||
ecdsa::Signature::from_bytes(&bytes.take_array("signature")?)
|
||||
.map(Signature)
|
||||
ecdsa::Signature::from_bytes(&bytes.take_array("signature")?.into_ha0_4())
|
||||
.map_err(|_| ProtocolError::SerializationError)
|
||||
}
|
||||
}
|
||||
|
||||
fn sign<R, C, H>(sk: &SecretKey<C>, rng: &mut R, pre_hash: &[u8]) -> ecdsa::Signature<C>
|
||||
where
|
||||
R: CryptoRng + RngCore,
|
||||
C: CurveArithmetic + PrimeCurve,
|
||||
SignatureSize<C>: ArrayLength<u8>,
|
||||
H: Default + BlockSizeUser + FixedOutputReset<OutputSize = FieldBytesSize<C>> + HashMarker,
|
||||
R: CryptoRng + Rng,
|
||||
C: CurveArithmetic + EcdsaCurve,
|
||||
SignatureSize<C>: ArraySize,
|
||||
H: Digest + BlockSizeUser + FixedOutputReset,
|
||||
{
|
||||
let repr = sk.to_bytes();
|
||||
let order = C::ORDER.encode_field_bytes();
|
||||
let z =
|
||||
hazmat::bits2field::<C>(pre_hash).expect("hash output can not be shorter than a scalar");
|
||||
|
||||
// This can only fail if the computed `r` or `s` are zero, in which case we just
|
||||
// retry with a new `k`. See https://github.com/RustCrypto/signatures/pull/951.
|
||||
loop {
|
||||
let mut ad = FieldBytes::<C>::default();
|
||||
rng.fill_bytes(&mut ad);
|
||||
|
||||
let k =
|
||||
Scalar::<C>::from_repr(rfc6979::generate_k::<H, _>(&repr, &order, &z, &ad)).unwrap();
|
||||
|
||||
if let Ok((signature, _)) = hazmat::sign_prehashed::<C, _>(&sk.to_nonzero_scalar(), k, &z) {
|
||||
break signature;
|
||||
}
|
||||
}
|
||||
let mut ad = FieldBytes::<C>::default();
|
||||
rng.fill_bytes(&mut ad);
|
||||
ecdsa::hazmat::sign_prehashed_rfc6979::<C, H>(&sk.to_nonzero_scalar(), pre_hash, &ad).0
|
||||
}
|
||||
|
||||
fn verify<C>(
|
||||
pk: &NonIdentity<C>,
|
||||
pk: &NonIdentity<ProjectivePoint<C>>,
|
||||
pre_hash: &[u8],
|
||||
signature: &ecdsa::Signature<C>,
|
||||
) -> Result<(), ProtocolError>
|
||||
where
|
||||
C: CurveArithmetic + PrimeCurve,
|
||||
SignatureSize<C>: ArrayLength<u8>,
|
||||
C: CurveArithmetic + EcdsaCurve,
|
||||
SignatureSize<C>: ArraySize,
|
||||
{
|
||||
let z =
|
||||
hazmat::bits2field::<C>(pre_hash).expect("hash output can not be shorter than a scalar");
|
||||
hazmat::verify_prehashed(&pk.0.to_point(), &z, signature)
|
||||
ecdsa::hazmat::verify_prehashed(&pk.to_point(), pre_hash, signature)
|
||||
.map_err(|_| ProtocolError::InvalidLoginError)
|
||||
}
|
||||
|
||||
/// Wrapper around [`ecdsa::Signature`] to implement [`Zeroize`].
|
||||
// TODO: remove after https://github.com/RustCrypto/signatures/pull/948.
|
||||
#[derive_where(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound = "", transparent)
|
||||
)]
|
||||
pub struct Signature<G: CurveArithmetic + PrimeCurve>(pub ecdsa::Signature<G>)
|
||||
where
|
||||
SignatureSize<G>: ArrayLength<u8>;
|
||||
|
||||
impl<G: CurveArithmetic + PrimeCurve> Zeroize for Signature<G>
|
||||
where
|
||||
SignatureSize<G>: ArrayLength<u8>,
|
||||
{
|
||||
fn zeroize(&mut self) {
|
||||
self.0 = ecdsa::Signature::from_scalars(
|
||||
Into::<FieldBytes<G>>::into(Scalar::<G>::ONE),
|
||||
Into::<FieldBytes<G>>::into(Scalar::<G>::ONE),
|
||||
)
|
||||
.expect("failed to create `Signature` with non-zero `Scalar`s");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ecdsa() {
|
||||
use std::vec;
|
||||
|
||||
use digest::Digest;
|
||||
use p256::ecdsa::signature::{DigestVerifier, RandomizedDigestSigner};
|
||||
use ecdsa::signature::hazmat::PrehashVerifier;
|
||||
use p256::ecdsa::signature::RandomizedDigestSigner;
|
||||
use p256::ecdsa::{Signature, SigningKey, VerifyingKey};
|
||||
use p256::{NistP256, PublicKey};
|
||||
use rand::rngs::OsRng;
|
||||
use rand::rngs::SysRng;
|
||||
use rand_core::UnwrapErr;
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::tests::mock_rng::CycleRng;
|
||||
@@ -171,22 +124,24 @@ fn ecdsa() {
|
||||
let mut rng = CycleRng::new(vec![1; 32]);
|
||||
|
||||
let mut message = [0; 1024];
|
||||
OsRng.fill_bytes(&mut message);
|
||||
UnwrapErr(SysRng).fill_bytes(&mut message);
|
||||
let hash = Sha256::new_with_prefix(message);
|
||||
|
||||
let sk = NistP256::random_sk(&mut OsRng);
|
||||
let sk = NistP256::random_sk(&mut UnwrapErr(SysRng));
|
||||
let signing_key = SigningKey::from(sk.clone());
|
||||
|
||||
let signature: Signature = signing_key.sign_digest_with_rng(&mut rng, hash.clone());
|
||||
let signature: Signature = signing_key.sign_digest_with_rng(&mut rng, |d: &mut Sha256| {
|
||||
d.update(message);
|
||||
});
|
||||
let custom_signature = sign::<_, _, Sha256>(&sk, &mut rng, &hash.clone().finalize());
|
||||
|
||||
assert_eq!(signature, custom_signature);
|
||||
|
||||
let pk = NistP256::public_key(&sk);
|
||||
let verifying_key = VerifyingKey::from(PublicKey::from(pk.0));
|
||||
let verifying_key = VerifyingKey::from(PublicKey::from(&pk));
|
||||
|
||||
verifying_key
|
||||
.verify_digest(hash.clone(), &signature)
|
||||
.verify_prehash(&hash.clone().finalize(), &signature)
|
||||
.unwrap();
|
||||
verify(&pk, &hash.finalize(), &custom_signature).unwrap();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use generic_array::GenericArray;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use self::implementation::HashEddsaImpl;
|
||||
@@ -33,7 +33,7 @@ impl<G: HashEddsaImpl> SignatureProtocol for HashEddsa<G> {
|
||||
type SignatureLen = G::SignatureLen;
|
||||
type VerifyState<CS: CipherSuite, KE: Group> = G::VerifyState<CS, KE>;
|
||||
|
||||
fn sign<'a, R: CryptoRng + RngCore, CS: CipherSuite, KE: Group>(
|
||||
fn sign<'a, R: CryptoRng + Rng, CS: CipherSuite, KE: Group>(
|
||||
sk: &<Self::Group as Group>::Sk,
|
||||
_: &mut R,
|
||||
message: &Message<CS, KE>,
|
||||
@@ -66,7 +66,7 @@ pub(in super::super) mod implementation {
|
||||
|
||||
pub trait HashEddsaImpl: Group {
|
||||
type Signature: Clone + Zeroize;
|
||||
type SignatureLen: ArrayLength<u8>;
|
||||
type SignatureLen: ArrayLength;
|
||||
type VerifyState<CS: CipherSuite, KE: Group>: Clone + Zeroize;
|
||||
|
||||
fn sign<CS: CipherSuite, KE: Group>(
|
||||
|
||||
@@ -10,7 +10,6 @@ use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::{FixedOutput, Output, Update};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::Sum;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use zeroize::Zeroize;
|
||||
@@ -26,7 +25,7 @@ use crate::key_exchange::{
|
||||
SerializedIdentifier, SerializedIdentifiers,
|
||||
};
|
||||
use crate::opaque::MaskedResponseLen;
|
||||
use crate::serialization::{SliceExt, UpdateExt};
|
||||
use crate::serialization::{ConcatExt, SliceExt, UpdateExt};
|
||||
|
||||
/// This holds the message to be signed and the message to be verified.
|
||||
///
|
||||
@@ -242,7 +241,7 @@ impl<CS: CipherSuite, KE: Group> Deserialize for CachedMessage<CS, KE> {
|
||||
credential_response: SerializedCredentialResponse::deserialize_take(input)?,
|
||||
server_nonce: input.take_array("server nonce")?,
|
||||
server_e_pk: input.take_array("serialized server ephemeral key")?,
|
||||
server_mac: input.take_array("server mac")?,
|
||||
server_mac: input.take_array("server mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -264,20 +263,20 @@ type CachedMessageLen<CS: CipherSuite, KE: Group> = Sum<
|
||||
|
||||
impl<CS: CipherSuite, KE: Group> Serialize for CachedMessage<CS, KE>
|
||||
where
|
||||
SerializedCredentialRequestLen<CS>: ArrayLength<u8> + Add<Ke1MessageIterLen<KE>>,
|
||||
SerializedCredentialRequestLen<CS>: ArrayLength + Add<Ke1MessageIterLen<KE>>,
|
||||
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>:
|
||||
ArrayLength<u8> + Add<SerializedCredentialResponseLen<CS>>,
|
||||
ArrayLength + Add<SerializedCredentialResponseLen<CS>>,
|
||||
Sum<
|
||||
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||
SerializedCredentialResponseLen<CS>,
|
||||
>: ArrayLength<u8> + Add<NonceLen>,
|
||||
>: ArrayLength + Add<NonceLen>,
|
||||
Sum<
|
||||
Sum<
|
||||
Sum<SerializedCredentialRequestLen<CS>, Ke1MessageIterLen<KE>>,
|
||||
SerializedCredentialResponseLen<CS>,
|
||||
>,
|
||||
NonceLen,
|
||||
>: ArrayLength<u8> + Add<KE::PkLen>,
|
||||
>: ArrayLength + Add<KE::PkLen>,
|
||||
Sum<
|
||||
Sum<
|
||||
Sum<
|
||||
@@ -287,26 +286,26 @@ where
|
||||
NonceLen,
|
||||
>,
|
||||
KE::PkLen,
|
||||
>: ArrayLength<u8> + Add<OutputSize<KeHash<CS>>>,
|
||||
CachedMessageLen<CS, KE>: ArrayLength<u8>,
|
||||
>: ArrayLength + Add<OutputSize<KeHash<CS>>>,
|
||||
CachedMessageLen<CS, KE>: ArrayLength,
|
||||
// Ke1MessageIter
|
||||
NonceLen: Add<KE::PkLen>,
|
||||
Ke1MessageIterLen<KE>: ArrayLength<u8>,
|
||||
Ke1MessageIterLen<KE>: ArrayLength,
|
||||
// CredentialResponseParts
|
||||
<OprfGroup<CS> as voprf::Group>::ElemLen: Add<NonceLen>,
|
||||
Sum<<OprfGroup<CS> as voprf::Group>::ElemLen, NonceLen>:
|
||||
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
|
||||
SerializedCredentialResponseLen<CS>: ArrayLength<u8>,
|
||||
ArrayLength + Add<MaskedResponseLen<CS>>,
|
||||
SerializedCredentialResponseLen<CS>: ArrayLength,
|
||||
{
|
||||
type Len = CachedMessageLen<CS, KE>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.credential_request
|
||||
.serialize()
|
||||
.concat(self.ke1_message.serialize())
|
||||
.concat(self.credential_response.serialize())
|
||||
.concat(self.server_nonce)
|
||||
.concat(self.server_e_pk.clone())
|
||||
.concat(self.server_mac.clone())
|
||||
.cat(self.ke1_message.serialize())
|
||||
.cat(self.credential_response.serialize())
|
||||
.cat(self.server_nonce)
|
||||
.cat(self.server_e_pk.clone())
|
||||
.cat(GenericArray::from_slice(self.server_mac.as_slice()).clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ use core::marker::PhantomData;
|
||||
use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, Mac, Output, OutputSizeUser};
|
||||
use digest::block_api::{BlockSizeUser, CoreProxy, SmallBlockSizeUser};
|
||||
use digest::{Mac, Output, OutputSizeUser};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, Le, NonZero, Sum, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use hmac::Hmac;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use hmac::{KeyInit, SimpleHmac};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use subtle::{ConstantTimeEq, CtOption};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@@ -49,7 +49,7 @@ pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State};
|
||||
use crate::key_exchange::shared::{derive_keys, generate_ke1, generate_nonce, transcript};
|
||||
use crate::keypair::{KeyPair, PrivateKey, PublicKey};
|
||||
use crate::opaque::Identifiers;
|
||||
use crate::serialization::{SliceExt, UpdateExt};
|
||||
use crate::serialization::{ConcatExt, SliceExt, UpdateExt};
|
||||
|
||||
/// The SIGMA-I key exchange implementation
|
||||
///
|
||||
@@ -95,7 +95,7 @@ pub trait SignatureProtocol {
|
||||
/// The signature.
|
||||
type Signature: Clone + Zeroize;
|
||||
/// Length of a serialized [`Signature`](Self::Signature).
|
||||
type SignatureLen: ArrayLength<u8>;
|
||||
type SignatureLen: ArrayLength;
|
||||
/// The state required to run the verification. This is used to cache the
|
||||
/// pre-hash for curves that support that, otherwise the [`Message`] to
|
||||
/// verify is stored via [`CachedMessage`].
|
||||
@@ -111,7 +111,7 @@ pub trait SignatureProtocol {
|
||||
/// The returned [`VerifyState`](Self::VerifyState) will be passed to
|
||||
/// [`verify()`](Self::verify) and must contain the necessary
|
||||
/// information to verify the incoming signature.
|
||||
fn sign<R: CryptoRng + RngCore, CS: CipherSuite, KE: Group>(
|
||||
fn sign<R: CryptoRng + Rng, CS: CipherSuite, KE: Group>(
|
||||
sk: &<Self::Group as Group>::Sk,
|
||||
rng: &mut R,
|
||||
message: &Message<CS, KE>,
|
||||
@@ -202,8 +202,9 @@ pub struct Ke2State<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> {
|
||||
pub struct Ke2Message<SIG: SignatureProtocol, KE: Group, KEH: Hash>
|
||||
where
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
{
|
||||
server_nonce: GenericArray<u8, NonceLen>,
|
||||
#[derive_where(skip(Zeroize))]
|
||||
@@ -223,37 +224,42 @@ where
|
||||
)]
|
||||
#[derive_where(Clone, ZeroizeOnDrop)]
|
||||
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; SIG::Signature)]
|
||||
pub struct Ke3Message<SIG: SignatureProtocol, KEH: OutputSizeUser> {
|
||||
pub struct Ke3Message<SIG: SignatureProtocol, KEH: OutputSizeUser>
|
||||
where
|
||||
<KEH as OutputSizeUser>::OutputSize: ArrayLength,
|
||||
{
|
||||
signature: SIG::Signature,
|
||||
mac: Output<KEH>,
|
||||
}
|
||||
|
||||
impl<SIG: SignatureProtocol, KE: 'static + Group, KEH: Hash> KeyExchange for SigmaI<SIG, KE, KEH>
|
||||
impl<SIG: SignatureProtocol, KE: 'static + Group, KEH: Hash + BlockSizeUser> KeyExchange
|
||||
for SigmaI<SIG, KE, KEH>
|
||||
where
|
||||
KE::Sk: DiffieHellman<KE>,
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
{
|
||||
type Group = SIG::Group;
|
||||
type Hash = KEH;
|
||||
|
||||
type KE1State = Ke1State<KE>;
|
||||
type KE2State<CS: CipherSuite> = Ke2State<CS, SIG, KE>;
|
||||
type KE1Message = Ke1Message<KE>;
|
||||
type KE2Builder<'a, CS: CipherSuite<KeyExchange = Self>> = Ke2Builder<'a, CS, KE>;
|
||||
type KE2BuilderData<'a, CS: 'static + CipherSuite> = &'a Message<'a, CS, KE>;
|
||||
type KE2BuilderInput<CS: CipherSuite> = (SIG::Signature, SIG::VerifyState<CS, KE>);
|
||||
type KE2State<CS: CipherSuite> = Ke2State<CS, SIG, KE>;
|
||||
type KE2Message = Ke2Message<SIG, KE, KEH>;
|
||||
type KE3Message = Ke3Message<SIG, KEH>;
|
||||
|
||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||
fn generate_ke1<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<GenerateKe1Result<Self>, ProtocolError> {
|
||||
generate_ke1(rng)
|
||||
}
|
||||
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -287,13 +293,13 @@ where
|
||||
&transcript_hasher.finalize(),
|
||||
)?;
|
||||
|
||||
let mut server_mac =
|
||||
Hmac::<KEH>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
let mut server_mac = SimpleHmac::<KEH>::new_from_slice(&derived_keys.km2)
|
||||
.map_err(|_| InternalError::HmacError)?;
|
||||
server_mac.update_iter(identifiers.server.iter());
|
||||
let server_mac = server_mac.finalize().into_bytes();
|
||||
|
||||
let mut client_mac =
|
||||
Hmac::<KEH>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
let mut client_mac = SimpleHmac::<KEH>::new_from_slice(&derived_keys.km3)
|
||||
.map_err(|_| InternalError::HmacError)?;
|
||||
client_mac.update_iter(identifiers.client.iter());
|
||||
let client_mac = client_mac.finalize().into_bytes();
|
||||
|
||||
@@ -331,7 +337,7 @@ where
|
||||
&builder.transcript
|
||||
}
|
||||
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
builder: &Self::KE2Builder<'_, CS>,
|
||||
rng: &mut R,
|
||||
server_s_sk: &PrivateKey<Self::Group>,
|
||||
@@ -363,7 +369,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -397,8 +403,8 @@ where
|
||||
&transcript_hasher.finalize(),
|
||||
)?;
|
||||
|
||||
let mut server_mac =
|
||||
Hmac::<KEH>::new_from_slice(&derived_keys.km2).map_err(|_| InternalError::HmacError)?;
|
||||
let mut server_mac = SimpleHmac::<KEH>::new_from_slice(&derived_keys.km2)
|
||||
.map_err(|_| InternalError::HmacError)?;
|
||||
server_mac.update_iter(identifiers.server.iter());
|
||||
let server_mac = server_mac.finalize().into_bytes();
|
||||
|
||||
@@ -406,8 +412,8 @@ where
|
||||
.then_some(())
|
||||
.ok_or(ProtocolError::InvalidLoginError)?;
|
||||
|
||||
let mut client_mac =
|
||||
Hmac::<KEH>::new_from_slice(&derived_keys.km3).map_err(|_| InternalError::HmacError)?;
|
||||
let mut client_mac = SimpleHmac::<KEH>::new_from_slice(&derived_keys.km3)
|
||||
.map_err(|_| InternalError::HmacError)?;
|
||||
client_mac.update_iter(identifiers.client.iter());
|
||||
let client_mac = client_mac.finalize().into_bytes();
|
||||
|
||||
@@ -481,13 +487,14 @@ where
|
||||
impl<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> Deserialize for Ke2State<CS, SIG, KE>
|
||||
where
|
||||
SIG::VerifyState<CS, KE>: Deserialize,
|
||||
OutputSize<KeHash<CS>>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
client_s_pk: PublicKey::deserialize_take(input)?,
|
||||
session_key: input.take_array("session key")?,
|
||||
verify_state: SIG::VerifyState::deserialize_take(input)?,
|
||||
expected_mac: input.take_array("expected mac")?,
|
||||
session_key: input.take_array("session key")?.into_ha0_4(),
|
||||
verify_state: SIG::VerifyState::<CS, KE>::deserialize_take(input)?,
|
||||
expected_mac: input.take_array("expected mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -502,37 +509,44 @@ type VerifyStateLen<CS, SIG: SignatureProtocol, KE> = <SIG::VerifyState<CS, KE>
|
||||
impl<CS: CipherSuite, SIG: SignatureProtocol, KE: Group> Serialize for Ke2State<CS, SIG, KE>
|
||||
where
|
||||
SIG::VerifyState<CS, KE>: Serialize,
|
||||
OutputSize<KeHash<CS>>: ArrayLength,
|
||||
// Ke2State: ((SigPk + Hash) + VerifyState) + Hash
|
||||
<SIG::Group as Group>::PkLen: Add<OutputSize<KeHash<CS>>>,
|
||||
Sum<<SIG::Group as Group>::PkLen, OutputSize<KeHash<CS>>>:
|
||||
ArrayLength<u8> + Add<VerifyStateLen<CS, SIG, KE>>,
|
||||
ArrayLength + Add<VerifyStateLen<CS, SIG, KE>>,
|
||||
Sum<Sum<<SIG::Group as Group>::PkLen, OutputSize<KeHash<CS>>>, VerifyStateLen<CS, SIG, KE>>:
|
||||
ArrayLength<u8> + Add<OutputSize<KeHash<CS>>>,
|
||||
Ke2StateLen<CS, SIG, KE>: ArrayLength<u8>,
|
||||
ArrayLength + Add<OutputSize<KeHash<CS>>>,
|
||||
Ke2StateLen<CS, SIG, KE>: ArrayLength,
|
||||
{
|
||||
type Len = Ke2StateLen<CS, SIG, KE>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.client_s_pk
|
||||
.serialize()
|
||||
.concat(self.session_key.clone())
|
||||
.concat(self.verify_state.serialize())
|
||||
.concat(self.expected_mac.clone())
|
||||
Concat::concat(
|
||||
Concat::concat(
|
||||
Concat::concat(
|
||||
self.client_s_pk.serialize(),
|
||||
GenericArray::from_slice(self.session_key.as_slice()).clone(),
|
||||
),
|
||||
self.verify_state.serialize(),
|
||||
),
|
||||
GenericArray::from_slice(self.expected_mac.as_slice()).clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SIG: SignatureProtocol, KE: Group, KEH: Hash> Deserialize for Ke2Message<SIG, KE, KEH>
|
||||
where
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
server_nonce: input.take_array("server nonce")?,
|
||||
server_e_pk: PublicKey::deserialize_take(input)?,
|
||||
signature: SIG::deserialize_take_signature(input)?,
|
||||
mac: input.take_array("mac")?,
|
||||
mac: input.take_array("mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -540,34 +554,36 @@ where
|
||||
impl<SIG: SignatureProtocol, KE: Group, KEH: Hash> Serialize for Ke2Message<SIG, KE, KEH>
|
||||
where
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
// Ke2Message: ((Nonce + KePk) + Signature) + Hash
|
||||
NonceLen: Add<KE::PkLen>,
|
||||
Sum<NonceLen, KE::PkLen>: ArrayLength<u8> + Add<SIG::SignatureLen>,
|
||||
Sum<Sum<NonceLen, KE::PkLen>, SIG::SignatureLen>: ArrayLength<u8> + Add<OutputSize<KEH>>,
|
||||
Sum<Sum<Sum<NonceLen, KE::PkLen>, SIG::SignatureLen>, OutputSize<KEH>>: ArrayLength<u8>,
|
||||
Sum<NonceLen, KE::PkLen>: ArrayLength + Add<SIG::SignatureLen>,
|
||||
Sum<Sum<NonceLen, KE::PkLen>, SIG::SignatureLen>: ArrayLength + Add<OutputSize<KEH>>,
|
||||
Sum<Sum<Sum<NonceLen, KE::PkLen>, SIG::SignatureLen>, OutputSize<KEH>>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<Sum<Sum<NonceLen, KE::PkLen>, SIG::SignatureLen>, OutputSize<KEH>>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.server_nonce
|
||||
.concat(self.server_e_pk.serialize())
|
||||
.concat(SIG::serialize_signature(&self.signature))
|
||||
.concat(self.mac.clone())
|
||||
.cat(self.server_e_pk.serialize())
|
||||
.cat(SIG::serialize_signature(&self.signature))
|
||||
.cat(GenericArray::from_slice(self.mac.as_slice()).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<SIG: SignatureProtocol, KEH: Hash> Deserialize for Ke3Message<SIG, KEH>
|
||||
where
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
signature: SIG::deserialize_take_signature(input)?,
|
||||
mac: input.take_array("mac")?,
|
||||
mac: input.take_array("mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -575,15 +591,19 @@ where
|
||||
impl<SIG: SignatureProtocol, KEH: Hash> Serialize for Ke3Message<SIG, KEH>
|
||||
where
|
||||
KEH::Core: ProxyHash,
|
||||
<KEH::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<KEH::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<KEH as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<KEH>: ArrayLength,
|
||||
// Ke2Message: Signature + Hash
|
||||
SIG::SignatureLen: Add<OutputSize<KEH>>,
|
||||
Sum<SIG::SignatureLen, OutputSize<KEH>>: ArrayLength<u8>,
|
||||
Sum<SIG::SignatureLen, OutputSize<KEH>>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<SIG::SignatureLen, OutputSize<KEH>>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
SIG::serialize_signature(&self.signature).concat(self.mac.clone())
|
||||
Concat::concat(
|
||||
SIG::serialize_signature(&self.signature),
|
||||
GenericArray::from_slice(self.mac.as_slice()).clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use generic_array::GenericArray;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use self::implementation::PureEddsaImpl;
|
||||
@@ -34,7 +34,7 @@ impl<G: PureEddsaImpl> SignatureProtocol for PureEddsa<G> {
|
||||
type SignatureLen = G::SignatureLen;
|
||||
type VerifyState<CS: CipherSuite, KE: Group> = CachedMessage<CS, KE>;
|
||||
|
||||
fn sign<'a, R: CryptoRng + RngCore, CS: CipherSuite, KE: Group>(
|
||||
fn sign<'a, R: CryptoRng + Rng, CS: CipherSuite, KE: Group>(
|
||||
sk: &G::Sk,
|
||||
_: &mut R,
|
||||
message: &Message<CS, KE>,
|
||||
@@ -51,13 +51,13 @@ impl<G: PureEddsaImpl> SignatureProtocol for PureEddsa<G> {
|
||||
G::verify(pk, message_builder, state, signature)
|
||||
}
|
||||
|
||||
fn deserialize_take_signature(bytes: &mut &[u8]) -> Result<Self::Signature, ProtocolError> {
|
||||
G::deserialize_take_signature(bytes)
|
||||
}
|
||||
|
||||
fn serialize_signature(signature: &Self::Signature) -> GenericArray<u8, Self::SignatureLen> {
|
||||
G::serialize_signature(signature)
|
||||
}
|
||||
|
||||
fn deserialize_take_signature(bytes: &mut &[u8]) -> Result<Self::Signature, ProtocolError> {
|
||||
G::deserialize_take_signature(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) mod implementation {
|
||||
@@ -67,7 +67,7 @@ pub(in super::super) mod implementation {
|
||||
|
||||
pub trait PureEddsaImpl: Group {
|
||||
type Signature: Clone + Zeroize;
|
||||
type SignatureLen: ArrayLength<u8>;
|
||||
type SignatureLen: ArrayLength;
|
||||
|
||||
fn sign<CS: CipherSuite, KE: Group>(
|
||||
sk: &Self::Sk,
|
||||
|
||||
@@ -16,24 +16,30 @@ use crate::serialization::SliceExt;
|
||||
|
||||
/// Pre-hash of the message to be verified.
|
||||
#[derive_where(Clone, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[derive_where(Copy; <H::OutputSize as ArrayLength<u8>>::ArrayType)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
derive(serde::Deserialize, serde::Serialize),
|
||||
serde(bound = "")
|
||||
)]
|
||||
#[allow(dead_code)]
|
||||
pub struct PreHash<H: OutputSizeUser>(pub Output<H>);
|
||||
|
||||
impl<H: OutputSizeUser> Deserialize for PreHash<H> {
|
||||
impl<H: OutputSizeUser> Deserialize for PreHash<H>
|
||||
where
|
||||
H::OutputSize: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self(input.take_array("pre-hash")?))
|
||||
Ok(Self(input.take_array("pre-hash")?.into_ha0_4()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: OutputSizeUser> Serialize for PreHash<H> {
|
||||
impl<H: OutputSizeUser> Serialize for PreHash<H>
|
||||
where
|
||||
H::OutputSize: ArrayLength,
|
||||
{
|
||||
type Len = H::OutputSize;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.0.clone()
|
||||
GenericArray::from_slice(self.0.as_slice()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,11 @@ use core::marker::PhantomData;
|
||||
use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, Output, OutputSizeUser};
|
||||
use generic_array::sequence::Concat;
|
||||
use digest::block_api::{CoreProxy, SmallBlockSizeUser};
|
||||
use digest::{Output, OutputSizeUser};
|
||||
use generic_array::typenum::{IsLess, Le, NonZero, Sum, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use subtle::{ConstantTimeEq, CtOption};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
@@ -34,7 +33,7 @@ use crate::key_exchange::shared::{self, NonceLen};
|
||||
pub use crate::key_exchange::shared::{DiffieHellman, Ke1Message, Ke1State};
|
||||
use crate::keypair::{PrivateKey, PublicKey};
|
||||
use crate::opaque::Identifiers;
|
||||
use crate::serialization::SliceExt;
|
||||
use crate::serialization::{ConcatExt, SliceExt};
|
||||
|
||||
////////////////////////////
|
||||
// High-level API Structs //
|
||||
@@ -79,8 +78,9 @@ pub struct Ke2State<H: OutputSizeUser> {
|
||||
pub struct Ke2Builder<G: Group, H: Hash>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
server_nonce: GenericArray<u8, NonceLen>,
|
||||
transcript_hasher: H,
|
||||
@@ -104,8 +104,9 @@ where
|
||||
pub struct Ke2Message<G: Group, H: Hash>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
pub(super) server_nonce: GenericArray<u8, NonceLen>,
|
||||
#[derive_where(skip(Zeroize))]
|
||||
@@ -123,8 +124,9 @@ where
|
||||
pub struct Ke3Message<H: Hash>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
pub(super) mac: Output<H>,
|
||||
}
|
||||
@@ -138,8 +140,9 @@ impl<G: Group + 'static, H: Hash> KeyExchange for TripleDh<G, H>
|
||||
where
|
||||
G::Sk: DiffieHellman<G>,
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
type Group = G;
|
||||
type Hash = H;
|
||||
@@ -153,13 +156,13 @@ where
|
||||
type KE2Message = Ke2Message<G, H>;
|
||||
type KE3Message = Ke3Message<H>;
|
||||
|
||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||
fn generate_ke1<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<GenerateKe1Result<Self>, ProtocolError> {
|
||||
shared::generate_ke1(rng)
|
||||
}
|
||||
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -201,7 +204,7 @@ where
|
||||
&builder.client_e_pk
|
||||
}
|
||||
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
builder: &Self::KE2Builder<'_, CS>,
|
||||
_: &mut R,
|
||||
server_s_sk: &PrivateKey<G>,
|
||||
@@ -247,7 +250,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
_: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -319,13 +322,14 @@ where
|
||||
impl<H: Hash> Deserialize for Ke2State<H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
session_key: input.take_array("session key")?,
|
||||
expected_mac: input.take_array("expected mac")?,
|
||||
session_key: input.take_array("session key")?.into_ha0_4(),
|
||||
expected_mac: input.take_array("expected mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -333,26 +337,32 @@ where
|
||||
impl<H: Hash> Serialize for Ke2State<H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
// Ke2State: Hash + Hash
|
||||
OutputSize<H>: Add<OutputSize<H>>,
|
||||
Sum<OutputSize<H>, OutputSize<H>>: ArrayLength<u8>,
|
||||
Sum<OutputSize<H>, OutputSize<H>>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<OutputSize<H>, OutputSize<H>>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.session_key.clone().concat(self.expected_mac.clone())
|
||||
let sk: GenericArray<u8, OutputSize<H>> =
|
||||
GenericArray::from_slice(self.session_key.as_slice()).clone();
|
||||
let mac: GenericArray<u8, OutputSize<H>> =
|
||||
GenericArray::from_slice(self.expected_mac.as_slice()).clone();
|
||||
|
||||
sk.cat(mac)
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: implement via derive after hash crates get `Zeroize` support in
|
||||
/// `digest` v11.
|
||||
/// TODO: implement via derive after `Hash` gets `Zeroize` support.
|
||||
impl<G: Group, H: Hash> Drop for Ke2Builder<G, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
let Self {
|
||||
@@ -365,7 +375,7 @@ where
|
||||
} = self;
|
||||
|
||||
server_nonce.zeroize();
|
||||
transcript_hasher.reset();
|
||||
digest::Reset::reset(transcript_hasher);
|
||||
shared_secret_1.zeroize();
|
||||
shared_secret_3.zeroize();
|
||||
}
|
||||
@@ -374,22 +384,24 @@ where
|
||||
impl<G: Group, H: Hash> ZeroizeOnDrop for Ke2Builder<G, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
}
|
||||
|
||||
impl<G: Group, H: Hash> Deserialize for Ke2Message<G, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
server_nonce: input.take_array("server nonce")?,
|
||||
server_e_pk: PublicKey::deserialize_take(input)?,
|
||||
mac: input.take_array("mac")?,
|
||||
mac: input.take_array("mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -397,31 +409,33 @@ where
|
||||
impl<H: Hash, G: Group> Serialize for Ke2Message<G, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
// Ke2Message: (Nonce + KePk) + Hash
|
||||
NonceLen: Add<G::PkLen>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength<u8> + Add<OutputSize<H>>,
|
||||
Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>: ArrayLength<u8>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength + Add<OutputSize<H>>,
|
||||
Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.server_nonce
|
||||
.concat(self.server_e_pk.serialize())
|
||||
.concat(self.mac.clone())
|
||||
.cat(self.server_e_pk.serialize())
|
||||
.cat(GenericArray::from_slice(self.mac.as_slice()).clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hash> Deserialize for Ke3Message<H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(bytes: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
mac: bytes.take_array("mac")?,
|
||||
mac: bytes.take_array("mac")?.into_ha0_4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -429,12 +443,13 @@ where
|
||||
impl<H: Hash> Serialize for Ke3Message<H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
type Len = OutputSize<H>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.mac.clone()
|
||||
GenericArray::from_slice(self.mac.as_slice()).clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,18 +23,18 @@ use core::marker::PhantomData;
|
||||
use core::ops::Add;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use digest::core_api::BlockSizeUser;
|
||||
use digest::{Digest, Output};
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{IsLess, Le, NonZero, Sum, U256};
|
||||
use digest::Output;
|
||||
use digest::block_api::{CoreProxy, SmallBlockSizeUser};
|
||||
use generic_array::typenum::{Cmp, IsLess, Le, NonZero, Sum, U256};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use hybrid_array::ArraySize;
|
||||
#[allow(deprecated)]
|
||||
use ml_kem::ExpandedKeyEncoding;
|
||||
use ml_kem::kem::{
|
||||
Ciphertext as MlKemCiphertext, Decapsulate, Encapsulate, Kem as MlKemTrait, KeyExport,
|
||||
KeySizeUser, TryKeyInit,
|
||||
};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use rand::{CryptoRng, Rng};
|
||||
use subtle::{ConstantTimeEq, CtOption};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
@@ -50,7 +50,7 @@ use crate::hash::{Hash, OutputSize, ProxyHash};
|
||||
use crate::key_exchange::group::Group;
|
||||
use crate::keypair::{PrivateKey, PublicKey};
|
||||
use crate::opaque::Identifiers;
|
||||
use crate::serialization::SliceExt;
|
||||
use crate::serialization::{ConcatExt, SliceExt};
|
||||
|
||||
/// Adapter trait that augments the `ml-kem` core traits with the metadata
|
||||
/// required by OPAQUE (e.g. fixed lengths and serialization hooks).
|
||||
@@ -62,16 +62,16 @@ pub trait KemCoreWrapper {
|
||||
type DecapsulationKey: Clone + ZeroizeOnDrop;
|
||||
|
||||
/// Length (in bytes) of the serialized public key.
|
||||
type EncapsulationKeyLen: ArrayLength<u8>;
|
||||
type EncapsulationKeyLen: ArrayLength + ArraySize;
|
||||
/// Length (in bytes) of the serialized secret key.
|
||||
type DecapsulationKeyLen: ArrayLength<u8>;
|
||||
type DecapsulationKeyLen: ArrayLength + ArraySize;
|
||||
/// Length (in bytes) of the encapsulated ciphertext.
|
||||
type CiphertextLen: ArrayLength<u8>;
|
||||
type CiphertextLen: ArrayLength + ArraySize;
|
||||
/// Length (in bytes) of the shared secret output by the KEM.
|
||||
type SharedSecretLen: ArrayLength<u8>;
|
||||
type SharedSecretLen: ArrayLength + ArraySize;
|
||||
|
||||
/// Generates a fresh KEM key pair.
|
||||
fn generate<R: RngCore + CryptoRng>(
|
||||
fn generate<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<(Self::DecapsulationKey, Self::EncapsulationKey), ProtocolError>;
|
||||
|
||||
@@ -98,7 +98,7 @@ pub trait KemCoreWrapper {
|
||||
/// Encapsulates to the given public key, returning the ciphertext and
|
||||
/// shared secret.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn encapsulate<R: RngCore + CryptoRng>(
|
||||
fn encapsulate<R: Rng + CryptoRng>(
|
||||
key: &Self::EncapsulationKey,
|
||||
rng: &mut R,
|
||||
) -> Result<
|
||||
@@ -120,7 +120,7 @@ pub trait KemCoreWrapper {
|
||||
/// which is required by `ml-kem 0.3.x`.
|
||||
struct RngCompat<'a, R>(&'a mut R);
|
||||
|
||||
impl<R: RngCore> rand_core_10::TryRng for RngCompat<'_, R> {
|
||||
impl<R: Rng> rand_core::TryRng for RngCompat<'_, R> {
|
||||
type Error = core::convert::Infallible;
|
||||
|
||||
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
|
||||
@@ -137,7 +137,7 @@ impl<R: RngCore> rand_core_10::TryRng for RngCompat<'_, R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> rand_core_10::TryCryptoRng for RngCompat<'_, R> {}
|
||||
impl<R: Rng + CryptoRng> rand_core::TryCryptoRng for RngCompat<'_, R> {}
|
||||
|
||||
type RcEncapsulationKeyLen<K> = <<K as MlKemTrait>::EncapsulationKey as KeySizeUser>::KeySize;
|
||||
#[allow(deprecated)]
|
||||
@@ -152,10 +152,10 @@ where
|
||||
K: MlKemTrait,
|
||||
K::EncapsulationKey: Encapsulate<Kem = K> + KeyExport + TryKeyInit + Clone,
|
||||
K::DecapsulationKey: Decapsulate<Kem = K> + ExpandedKeyEncoding + Clone + ZeroizeOnDrop,
|
||||
RcEncapsulationKeyLen<K>: ArrayLength<u8>,
|
||||
RcDecapsulationKeyLen<K>: ArrayLength<u8>,
|
||||
RcCiphertextLen<K>: ArrayLength<u8>,
|
||||
RcSharedSecretLen<K>: ArrayLength<u8>,
|
||||
RcEncapsulationKeyLen<K>: ArrayLength + ArraySize,
|
||||
RcDecapsulationKeyLen<K>: ArrayLength + ArraySize,
|
||||
RcCiphertextLen<K>: ArrayLength + ArraySize,
|
||||
RcSharedSecretLen<K>: ArrayLength + ArraySize,
|
||||
{
|
||||
type EncapsulationKey = K::EncapsulationKey;
|
||||
type DecapsulationKey = K::DecapsulationKey;
|
||||
@@ -164,7 +164,7 @@ where
|
||||
type CiphertextLen = RcCiphertextLen<K>;
|
||||
type SharedSecretLen = RcSharedSecretLen<K>;
|
||||
|
||||
fn generate<R: RngCore + CryptoRng>(
|
||||
fn generate<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<(Self::DecapsulationKey, Self::EncapsulationKey), ProtocolError> {
|
||||
Ok(K::generate_keypair_from_rng(&mut RngCompat(rng)))
|
||||
@@ -173,7 +173,7 @@ where
|
||||
fn serialize_encapsulation_key(
|
||||
key: &Self::EncapsulationKey,
|
||||
) -> GenericArray<u8, Self::EncapsulationKeyLen> {
|
||||
GenericArray::clone_from_slice(key.to_bytes().as_slice())
|
||||
GenericArray::from_slice(key.to_bytes().as_slice()).clone()
|
||||
}
|
||||
|
||||
fn deserialize_encapsulation_key(
|
||||
@@ -189,7 +189,7 @@ where
|
||||
fn serialize_decapsulation_key(
|
||||
key: &Self::DecapsulationKey,
|
||||
) -> GenericArray<u8, Self::DecapsulationKeyLen> {
|
||||
GenericArray::clone_from_slice(key.to_expanded_bytes().as_slice())
|
||||
GenericArray::from_slice(key.to_expanded_bytes().as_slice()).clone()
|
||||
}
|
||||
|
||||
fn deserialize_decapsulation_key(
|
||||
@@ -203,7 +203,7 @@ where
|
||||
.map_err(|_| ProtocolError::SerializationError)
|
||||
}
|
||||
|
||||
fn encapsulate<R: RngCore + CryptoRng>(
|
||||
fn encapsulate<R: Rng + CryptoRng>(
|
||||
key: &Self::EncapsulationKey,
|
||||
rng: &mut R,
|
||||
) -> Result<
|
||||
@@ -215,8 +215,8 @@ where
|
||||
> {
|
||||
let (ciphertext, shared) = key.encapsulate_with_rng(&mut RngCompat(rng));
|
||||
Ok((
|
||||
GenericArray::clone_from_slice(ciphertext.as_slice()),
|
||||
GenericArray::clone_from_slice(shared.as_slice()),
|
||||
GenericArray::from_slice(ciphertext.as_slice()).clone(),
|
||||
GenericArray::from_slice(shared.as_slice()).clone(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ where
|
||||
let ciphertext = MlKemCiphertext::<K>::try_from(encapsulated_key.as_slice())
|
||||
.map_err(|_| ProtocolError::SerializationError)?;
|
||||
let shared = key.decapsulate(&ciphertext);
|
||||
Ok(GenericArray::clone_from_slice(shared.as_slice()))
|
||||
Ok(GenericArray::from_slice(shared.as_slice()).clone())
|
||||
}
|
||||
}
|
||||
/// Triple Diffie-Hellman-style key exchange that offloads the second hop to a
|
||||
@@ -281,8 +281,10 @@ pub struct KemKe1Message<G: Group, K: KemCoreWrapper> {
|
||||
pub struct KemKe2State<K: KemCoreWrapper, H: Hash>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
base_state: super::tripledh::Ke2State<H>,
|
||||
kem_encapsulation_key: GenericArray<u8, K::EncapsulationKeyLen>,
|
||||
@@ -295,8 +297,10 @@ where
|
||||
pub struct KemKe2Builder<G: Group, H: Hash, K: KemCoreWrapper>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
server_nonce: GenericArray<u8, NonceLen>,
|
||||
transcript_hasher: H,
|
||||
@@ -323,8 +327,10 @@ where
|
||||
pub struct KemKe2Message<G: Group, H: Hash, K: KemCoreWrapper>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
dh_message: super::tripledh::Ke2Message<G, H>,
|
||||
kem_ciphertext: GenericArray<u8, K::CiphertextLen>,
|
||||
@@ -338,13 +344,15 @@ where
|
||||
G: Group,
|
||||
H: Hash,
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
K: KemCoreWrapper,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.server_nonce.zeroize();
|
||||
self.transcript_hasher.reset();
|
||||
digest::Digest::reset(&mut self.transcript_hasher);
|
||||
self.shared_secret_1.zeroize();
|
||||
self.shared_secret_3.zeroize();
|
||||
self.kem_shared_secret.zeroize();
|
||||
@@ -357,8 +365,10 @@ where
|
||||
G: Group,
|
||||
H: Hash,
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
K: KemCoreWrapper,
|
||||
{
|
||||
}
|
||||
@@ -369,11 +379,13 @@ where
|
||||
G::Sk: shared::DiffieHellman<G>,
|
||||
H: Hash,
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
K: KemCoreWrapper,
|
||||
NonceLen: Add<K::EncapsulationKeyLen>,
|
||||
Sum<NonceLen, K::EncapsulationKeyLen>: ArrayLength<u8>,
|
||||
Sum<NonceLen, K::EncapsulationKeyLen>: ArrayLength,
|
||||
{
|
||||
type Group = G;
|
||||
type Hash = H;
|
||||
@@ -390,7 +402,7 @@ where
|
||||
type KE2Message = KemKe2Message<G, H, K>;
|
||||
type KE3Message = KemKe3Message<H>;
|
||||
|
||||
fn generate_ke1<R: RngCore + CryptoRng>(
|
||||
fn generate_ke1<R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
) -> Result<GenerateKe1Result<Self>, ProtocolError> {
|
||||
let base = super::tripledh::TripleDh::<G, H>::generate_ke1(rng)?;
|
||||
@@ -409,7 +421,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: RngCore + CryptoRng>(
|
||||
fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: Rng + CryptoRng>(
|
||||
rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -440,8 +452,11 @@ where
|
||||
let (kem_ciphertext, kem_shared_secret) = K::encapsulate(&encapsulation_key, rng)?;
|
||||
|
||||
let mut transcript_hasher = transcript_hasher;
|
||||
transcript_hasher.update(ke1_message.kem_encapsulation_key.as_slice());
|
||||
transcript_hasher.update(kem_ciphertext.as_slice());
|
||||
digest::Digest::update(
|
||||
&mut transcript_hasher,
|
||||
ke1_message.kem_encapsulation_key.as_slice(),
|
||||
);
|
||||
digest::Digest::update(&mut transcript_hasher, kem_ciphertext.as_slice());
|
||||
|
||||
Ok(KemKe2Builder {
|
||||
server_nonce,
|
||||
@@ -462,7 +477,7 @@ where
|
||||
(&builder.client_e_pk, &builder.kem_encapsulation_key)
|
||||
}
|
||||
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
builder: &Self::KE2Builder<'_, CS>,
|
||||
_: &mut R,
|
||||
server_s_sk: &PrivateKey<G>,
|
||||
@@ -516,7 +531,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + RngCore>(
|
||||
fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
|
||||
_rng: &mut R,
|
||||
credential_request: SerializedCredentialRequest<CS>,
|
||||
ke1_message: Self::KE1Message,
|
||||
@@ -537,8 +552,14 @@ where
|
||||
ke2_message.dh_message.server_nonce,
|
||||
&ke2_message.dh_message.server_e_pk.serialize(),
|
||||
);
|
||||
transcript_hasher.update(ke1_message.kem_encapsulation_key.as_slice());
|
||||
transcript_hasher.update(ke2_message.kem_ciphertext.as_slice());
|
||||
digest::Digest::update(
|
||||
&mut transcript_hasher,
|
||||
ke1_message.kem_encapsulation_key.as_slice(),
|
||||
);
|
||||
digest::Digest::update(
|
||||
&mut transcript_hasher,
|
||||
ke2_message.kem_ciphertext.as_slice(),
|
||||
);
|
||||
|
||||
let shared_secret_1 = ke1_state
|
||||
.dh_state
|
||||
@@ -606,14 +627,14 @@ impl<G: Group, K: KemCoreWrapper> Serialize for KemKe1State<G, K>
|
||||
where
|
||||
Ke1State<G>: Serialize,
|
||||
<Ke1State<G> as Serialize>::Len: Add<K::DecapsulationKeyLen>,
|
||||
Sum<<Ke1State<G> as Serialize>::Len, K::DecapsulationKeyLen>: ArrayLength<u8>,
|
||||
Sum<<Ke1State<G> as Serialize>::Len, K::DecapsulationKeyLen>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<<Ke1State<G> as Serialize>::Len, K::DecapsulationKeyLen>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.dh_state
|
||||
.serialize()
|
||||
.concat(K::serialize_decapsulation_key(&self.kem_decapsulation_key))
|
||||
.cat(K::serialize_decapsulation_key(&self.kem_decapsulation_key))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,22 +651,24 @@ impl<G: Group, K: KemCoreWrapper> Serialize for KemKe1Message<G, K>
|
||||
where
|
||||
Ke1Message<G>: Serialize,
|
||||
<Ke1Message<G> as Serialize>::Len: Add<K::EncapsulationKeyLen>,
|
||||
Sum<<Ke1Message<G> as Serialize>::Len, K::EncapsulationKeyLen>: ArrayLength<u8>,
|
||||
Sum<<Ke1Message<G> as Serialize>::Len, K::EncapsulationKeyLen>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<<Ke1Message<G> as Serialize>::Len, K::EncapsulationKeyLen>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.dh_message
|
||||
.serialize()
|
||||
.concat(self.kem_encapsulation_key.clone())
|
||||
.cat(self.kem_encapsulation_key.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: KemCoreWrapper, H: Hash> Deserialize for KemKe2State<K, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
@@ -659,16 +682,18 @@ where
|
||||
impl<K: KemCoreWrapper, H: Hash> Serialize for KemKe2State<K, H>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
super::tripledh::Ke2State<H>: Serialize,
|
||||
<super::tripledh::Ke2State<H> as Serialize>::Len: Add<K::EncapsulationKeyLen>,
|
||||
Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>:
|
||||
ArrayLength<u8> + Add<K::CiphertextLen>,
|
||||
ArrayLength + Add<K::CiphertextLen>,
|
||||
Sum<
|
||||
Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>,
|
||||
K::CiphertextLen,
|
||||
>: ArrayLength<u8>,
|
||||
>: ArrayLength,
|
||||
{
|
||||
type Len = Sum<
|
||||
Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>,
|
||||
@@ -678,16 +703,18 @@ where
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.base_state
|
||||
.serialize()
|
||||
.concat(self.kem_encapsulation_key.clone())
|
||||
.concat(self.server_kem_ciphertext.clone())
|
||||
.cat(self.kem_encapsulation_key.clone())
|
||||
.cat(self.server_kem_ciphertext.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group, H: Hash, K: KemCoreWrapper> Deserialize for KemKe2Message<G, H, K>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
{
|
||||
fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
|
||||
Ok(Self {
|
||||
@@ -700,21 +727,21 @@ where
|
||||
impl<G: Group, H: Hash, K: KemCoreWrapper> Serialize for KemKe2Message<G, H, K>
|
||||
where
|
||||
H::Core: ProxyHash,
|
||||
<H::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
|
||||
Le<<H::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
|
||||
Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
|
||||
<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
|
||||
OutputSize<H>: ArrayLength,
|
||||
NonceLen: Add<G::PkLen>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength<u8> + Add<OutputSize<H>>,
|
||||
Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>: ArrayLength<u8>,
|
||||
Sum<NonceLen, G::PkLen>: ArrayLength + Add<OutputSize<H>>,
|
||||
Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>: ArrayLength,
|
||||
super::tripledh::Ke2Message<G, H>: Serialize,
|
||||
<super::tripledh::Ke2Message<G, H> as Serialize>::Len: Add<K::CiphertextLen>,
|
||||
<<super::tripledh::Ke2Message<G, H> as Serialize>::Len as Add<K::CiphertextLen>>::Output:
|
||||
ArrayLength<u8>,
|
||||
ArrayLength,
|
||||
{
|
||||
type Len = Sum<<super::tripledh::Ke2Message<G, H> as Serialize>::Len, K::CiphertextLen>;
|
||||
|
||||
fn serialize(&self) -> GenericArray<u8, Self::Len> {
|
||||
self.dh_message
|
||||
.serialize()
|
||||
.concat(self.kem_ciphertext.clone())
|
||||
self.dh_message.serialize().cat(self.kem_ciphertext.clone())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user