mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 06:23:08 -08:00
Address Feedback
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -2024,7 +2024,7 @@ dependencies = [
|
|||||||
"rosenpass-oqs",
|
"rosenpass-oqs",
|
||||||
"rosenpass-secret-memory",
|
"rosenpass-secret-memory",
|
||||||
"rosenpass-to",
|
"rosenpass-to",
|
||||||
"thiserror 2.0.11",
|
"thiserror 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ repository = "https://github.com/rosenpass/rosenpass"
|
|||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "2"
|
thiserror = { workspace = true }
|
||||||
rosenpass-to = { workspace = true }
|
rosenpass-to = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -1,77 +1,128 @@
|
|||||||
|
//! This module contains the traits for all the cryptographic algorithms used throughout Rosenpass.
|
||||||
|
//! These traits are marker traits that signal intent. They can also be used for trait objects.
|
||||||
|
|
||||||
|
/// Constants and trait for the Incorrect HMAC over Blake2b, with 256 key and hash length.
|
||||||
pub mod keyed_hash_incorrect_hmac_blake2b {
|
pub mod keyed_hash_incorrect_hmac_blake2b {
|
||||||
use crate::primitives::keyed_hash::*;
|
use crate::primitives::keyed_hash::*;
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
// These constants describe how they are used here, not what the algorithm defines.
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
pub const OUT_LEN: usize = 32;
|
|
||||||
|
|
||||||
pub trait KeyedHashIncorrectHmacBlake2b: KeyedHash<KEY_LEN, OUT_LEN> {}
|
/// The key length used in [`KeyedHashIncorrectHmacBlake2b`].
|
||||||
|
pub const KEY_LEN: usize = 32;
|
||||||
|
/// The hash length used in [`KeyedHashIncorrectHmacBlake2b`].
|
||||||
|
pub const HASH_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// A [`KeyedHash`] that is an incorrect HMAC over Blake2 (a custom Rosenpass construction)
|
||||||
|
pub trait KeyedHashIncorrectHmacBlake2b: KeyedHash<KEY_LEN, HASH_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for Blake2b, with 256 key and hash length.
|
||||||
pub mod keyed_hash_blake2b {
|
pub mod keyed_hash_blake2b {
|
||||||
use crate::primitives::keyed_hash::*;
|
use crate::primitives::keyed_hash::*;
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
// These constants describe how they are used here, not what the algorithm defines.
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
pub const OUT_LEN: usize = 32;
|
|
||||||
|
|
||||||
pub trait KeyedHashBlake2b: KeyedHash<KEY_LEN, OUT_LEN> {}
|
/// The key length used in [`KeyedHashBlake2b`].
|
||||||
|
pub const KEY_LEN: usize = 32;
|
||||||
|
/// The hash length used in [`KeyedHashBlake2b`].
|
||||||
|
pub const HASH_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// A [`KeyedHash`] that is Blake2b
|
||||||
|
pub trait KeyedHashBlake2b: KeyedHash<KEY_LEN, HASH_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for SHAKE256, with 256 key and hash length.
|
||||||
pub mod keyed_hash_shake256 {
|
pub mod keyed_hash_shake256 {
|
||||||
use crate::primitives::keyed_hash::*;
|
use crate::primitives::keyed_hash::*;
|
||||||
|
|
||||||
// These constants describe how they are used here, not what the algorithm defines.
|
// These constants describe how they are used here, not what the algorithm defines.
|
||||||
|
|
||||||
|
/// The key length used in [`KeyedHashShake256`].
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
|
/// The hash length used in [`KeyedHashShake256`].
|
||||||
pub const OUT_LEN: usize = 32;
|
pub const OUT_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// A [`KeyedHash`] that is SHAKE256.
|
||||||
pub trait KeyedHashShake256: KeyedHash<KEY_LEN, OUT_LEN> {}
|
pub trait KeyedHashShake256: KeyedHash<KEY_LEN, OUT_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for the ChaCha20Poly1305 AEAD
|
||||||
pub mod aead_chacha20poly1305 {
|
pub mod aead_chacha20poly1305 {
|
||||||
use crate::primitives::aead::*;
|
use crate::primitives::aead::*;
|
||||||
|
|
||||||
// See https://datatracker.ietf.org/doc/html/rfc7539#section-2.8
|
// See https://datatracker.ietf.org/doc/html/rfc7539#section-2.8
|
||||||
|
|
||||||
|
/// The key length used in [`AeadChaCha20Poly1305`].
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
|
/// The nonce length used in [`AeadChaCha20Poly1305`].
|
||||||
pub const NONCE_LEN: usize = 12;
|
pub const NONCE_LEN: usize = 12;
|
||||||
|
/// The tag length used in [`AeadChaCha20Poly1305`].
|
||||||
pub const TAG_LEN: usize = 16;
|
pub const TAG_LEN: usize = 16;
|
||||||
|
|
||||||
|
/// An [`Aead`] that is ChaCha20Poly1305.
|
||||||
pub trait AeadChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
pub trait AeadChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for the XChaCha20Poly1305 AEAD (i.e. ChaCha20Poly1305 with extended nonce
|
||||||
|
/// lengths)
|
||||||
pub mod aead_xchacha20poly1305 {
|
pub mod aead_xchacha20poly1305 {
|
||||||
use crate::primitives::aead::*;
|
use crate::primitives::aead::*;
|
||||||
|
|
||||||
// See https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03
|
// See https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03
|
||||||
|
|
||||||
|
/// The key length used in [`AeadXChaCha20Poly1305`].
|
||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
|
/// The nonce length used in [`AeadXChaCha20Poly1305`].
|
||||||
pub const NONCE_LEN: usize = 24;
|
pub const NONCE_LEN: usize = 24;
|
||||||
|
/// The tag length used in [`AeadXChaCha20Poly1305`].
|
||||||
pub const TAG_LEN: usize = 16;
|
pub const TAG_LEN: usize = 16;
|
||||||
|
|
||||||
|
/// An [`Aead`] that is XChaCha20Poly1305.
|
||||||
pub trait AeadXChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
pub trait AeadXChaCha20Poly1305: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for the Kyber512 KEM
|
||||||
pub mod kem_kyber512 {
|
pub mod kem_kyber512 {
|
||||||
use crate::primitives::kem::*;
|
use crate::primitives::kem::*;
|
||||||
|
|
||||||
// page 39 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
|
// page 39 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
|
||||||
// (which is ml-kem instead of kyber, but it's the same)
|
// (which is ml-kem instead of kyber, but it's the same)
|
||||||
|
|
||||||
|
/// The secret key length used in [`KemKyber512`].
|
||||||
pub const SK_LEN: usize = 1632;
|
pub const SK_LEN: usize = 1632;
|
||||||
|
|
||||||
|
/// The public key length used in [`KemKyber512`].
|
||||||
pub const PK_LEN: usize = 800;
|
pub const PK_LEN: usize = 800;
|
||||||
|
|
||||||
|
/// The ciphertext length used in [`KemKyber512`].
|
||||||
pub const CT_LEN: usize = 768;
|
pub const CT_LEN: usize = 768;
|
||||||
|
|
||||||
|
/// The shared key length used in [`KemKyber512`].
|
||||||
pub const SHK_LEN: usize = 32;
|
pub const SHK_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// A [`Kem`] that is Kyber512.
|
||||||
pub trait KemKyber512: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
pub trait KemKyber512: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constants and trait for the Classic McEliece 460896 KEM
|
||||||
pub mod kem_classic_mceliece460896 {
|
pub mod kem_classic_mceliece460896 {
|
||||||
use crate::primitives::kem::*;
|
use crate::primitives::kem::*;
|
||||||
|
|
||||||
// page 6 of https://classic.mceliece.org/mceliece-impl-20221023.pdf
|
// page 6 of https://classic.mceliece.org/mceliece-impl-20221023.pdf
|
||||||
|
|
||||||
|
/// The secret key length used in [`KemClassicMceliece460896`].
|
||||||
pub const SK_LEN: usize = 13608;
|
pub const SK_LEN: usize = 13608;
|
||||||
|
|
||||||
|
/// The public key length used in [`KemClassicMceliece460896`].
|
||||||
pub const PK_LEN: usize = 524160;
|
pub const PK_LEN: usize = 524160;
|
||||||
|
|
||||||
|
/// The ciphertext length used in [`KemClassicMceliece460896`].
|
||||||
pub const CT_LEN: usize = 156;
|
pub const CT_LEN: usize = 156;
|
||||||
|
|
||||||
|
/// The shared key length used in [`KemClassicMceliece460896`].
|
||||||
pub const SHK_LEN: usize = 32;
|
pub const SHK_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// A [`Kem`] that is ClassicMceliece460896.
|
||||||
pub trait KemClassicMceliece460896: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
pub trait KemClassicMceliece460896: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
|
//! This trait contains traits, constants and wrappers that provid= the interface between Rosenpass
|
||||||
|
//! as a consumer of cryptographic libraries and the implementations of cryptographic algorithms.
|
||||||
|
|
||||||
pub mod algorithms;
|
pub mod algorithms;
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
//! Traits for cryptographic primitives used in Rosenpass, specifically KEM, AEAD and keyed
|
||||||
|
//! hashing.
|
||||||
|
|
||||||
pub(crate) mod aead;
|
pub(crate) mod aead;
|
||||||
pub(crate) mod kem;
|
pub(crate) mod kem;
|
||||||
pub(crate) mod keyed_hash;
|
pub(crate) mod keyed_hash;
|
||||||
|
|||||||
@@ -1,11 +1,64 @@
|
|||||||
use rosenpass_to::{ops::copy_slice, To as _};
|
use rosenpass_to::{ops::copy_slice, To as _};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Models authenticated encryption with assiciated data (AEAD) functionality.
|
||||||
|
///
|
||||||
|
/// The methods of this trait take a `&self` argument as a receiver. This has two reasons:
|
||||||
|
/// 1. It makes type inference a lot smoother
|
||||||
|
/// 2. It allows to use the functionality through a trait object or having an enum that has
|
||||||
|
/// variants for multiple options (like e.g. the `KeyedHash` enum in `rosenpass-ciphers`).
|
||||||
|
///
|
||||||
|
/// Since the caller needs an instance of the type to use the functionality, implementors are
|
||||||
|
/// adviced to implement the [`Default`] trait where possible.
|
||||||
|
///
|
||||||
|
/// Example for encrypting a message with a specific [`Aead`] instance:
|
||||||
|
/// ```
|
||||||
|
/// use rosenpass_cipher_traits::primitives::Aead;
|
||||||
|
///
|
||||||
|
/// const KEY_LEN: usize = 32;
|
||||||
|
/// const NONCE_LEN: usize = 12;
|
||||||
|
/// const TAG_LEN: usize = 16;
|
||||||
|
///
|
||||||
|
/// fn encrypt_message_given_an_aead<AeadImpl>(
|
||||||
|
/// aead: &AeadImpl,
|
||||||
|
/// msg: &str,
|
||||||
|
/// nonce: &[u8; NONCE_LEN],
|
||||||
|
/// encrypted: &mut [u8]
|
||||||
|
/// ) where AeadImpl: Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {
|
||||||
|
/// let key = [0u8; KEY_LEN]; // This is not a secure key!
|
||||||
|
/// let ad = b""; // we don't need associated data here
|
||||||
|
/// aead.encrypt(encrypted, &key, nonce, ad, msg.as_bytes()).unwrap();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If only the type (but no instance) is available, then we can still encrypt, as long as the type
|
||||||
|
/// also is [`Default`]:
|
||||||
|
/// ```
|
||||||
|
/// use rosenpass_cipher_traits::primitives::Aead;
|
||||||
|
///
|
||||||
|
/// const KEY_LEN: usize = 32;
|
||||||
|
/// const NONCE_LEN: usize = 12;
|
||||||
|
/// const TAG_LEN: usize = 16;
|
||||||
|
///
|
||||||
|
/// fn encrypt_message_without_aead<AeadImpl>(
|
||||||
|
/// msg: &str,
|
||||||
|
/// nonce: &[u8; NONCE_LEN],
|
||||||
|
/// encrypted: &mut [u8]
|
||||||
|
/// ) where AeadImpl: Default + Aead<KEY_LEN, NONCE_LEN, TAG_LEN> {
|
||||||
|
/// let key = [0u8; KEY_LEN]; // This is not a secure key!
|
||||||
|
/// let ad = b""; // we don't need associated data here
|
||||||
|
/// AeadImpl::default().encrypt(encrypted, &key, nonce, ad, msg.as_bytes()).unwrap();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize> {
|
pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize> {
|
||||||
const KEY_LEN: usize = KEY_LEN;
|
const KEY_LEN: usize = KEY_LEN;
|
||||||
const NONCE_LEN: usize = NONCE_LEN;
|
const NONCE_LEN: usize = NONCE_LEN;
|
||||||
const TAG_LEN: usize = TAG_LEN;
|
const TAG_LEN: usize = TAG_LEN;
|
||||||
|
|
||||||
|
/// Encrypts `plaintext` using the given `key` and `nonce`, taking into account the additional
|
||||||
|
/// data `ad` and writes the result into `ciphertext`.
|
||||||
|
///
|
||||||
|
/// `ciphertext` must be exactly `TAG_LEN` longer than `plaintext`.
|
||||||
fn encrypt(
|
fn encrypt(
|
||||||
&self,
|
&self,
|
||||||
ciphertext: &mut [u8],
|
ciphertext: &mut [u8],
|
||||||
@@ -15,6 +68,10 @@ pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usiz
|
|||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Decrypts `ciphertexttext` using the given `key` and `nonce`, taking into account the additional
|
||||||
|
/// data `ad` and writes the result into `plaintext`.
|
||||||
|
///
|
||||||
|
/// `ciphertext` must be exactly `TAG_LEN` longer than `plaintext`.
|
||||||
fn decrypt(
|
fn decrypt(
|
||||||
&self,
|
&self,
|
||||||
plaintext: &mut [u8],
|
plaintext: &mut [u8],
|
||||||
@@ -25,15 +82,21 @@ pub trait Aead<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usiz
|
|||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The API of XChaCha was a bit weird and moved the nonce into the ciphertext. Instead of changing
|
/// Provides an AEAD API where the nonce is part of the ciphertext.
|
||||||
/// the protocol code, we recreate that API on top of the more normal API, but move it into a
|
///
|
||||||
/// separate crate.
|
/// The old xaead API had the ciphertext begin with the `nonce`. In order to not having to change
|
||||||
|
/// the calling code too much, we add a wrapper trait that provides this API and implement it for
|
||||||
|
/// all AEAD.
|
||||||
pub trait AeadWithNonceInCiphertext<
|
pub trait AeadWithNonceInCiphertext<
|
||||||
const KEY_LEN: usize,
|
const KEY_LEN: usize,
|
||||||
const NONCE_LEN: usize,
|
const NONCE_LEN: usize,
|
||||||
const TAG_LEN: usize,
|
const TAG_LEN: usize,
|
||||||
>: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>
|
>: Aead<KEY_LEN, NONCE_LEN, TAG_LEN>
|
||||||
{
|
{
|
||||||
|
/// Encrypts `plaintext` using the given `key` and `nonce`, taking into account the additional
|
||||||
|
/// data `ad` and writes the result into `ciphertext`.
|
||||||
|
///
|
||||||
|
/// `ciphertext` must be exactly `TAG_LEN` + `NONCE_LEN` longer than `plaintext`.
|
||||||
fn encrypt_with_nonce_in_ctxt(
|
fn encrypt_with_nonce_in_ctxt(
|
||||||
&self,
|
&self,
|
||||||
ciphertext: &mut [u8],
|
ciphertext: &mut [u8],
|
||||||
@@ -56,6 +119,10 @@ pub trait AeadWithNonceInCiphertext<
|
|||||||
self.encrypt(rest, key, nonce, ad, plaintext)
|
self.encrypt(rest, key, nonce, ad, plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrypts `ciphertexttext` using the given `key` and `nonce`, taking into account the additional
|
||||||
|
/// data `ad` and writes the result into `plaintext`.
|
||||||
|
///
|
||||||
|
/// `ciphertext` must be exactly `TAG_LEN` + `NONCE_LEN` longer than `plaintext`.
|
||||||
fn decrypt_with_nonce_in_ctxt(
|
fn decrypt_with_nonce_in_ctxt(
|
||||||
&self,
|
&self,
|
||||||
plaintext: &mut [u8],
|
plaintext: &mut [u8],
|
||||||
@@ -89,12 +156,20 @@ impl<
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The error returned by AEAD operations
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// An internal error occurred. This should never be happen and indicates an error in the
|
||||||
|
/// AEAD implementation.
|
||||||
#[error("internal error")]
|
#[error("internal error")]
|
||||||
InternalError,
|
InternalError,
|
||||||
|
|
||||||
|
/// Could not decrypt a message because the message is not a valid ciphertext for the given
|
||||||
|
/// key.
|
||||||
#[error("decryption error")]
|
#[error("decryption error")]
|
||||||
DecryptError,
|
DecryptError,
|
||||||
|
|
||||||
|
/// The provided buffers have the wrong lengths.
|
||||||
#[error("buffers have invalid length")]
|
#[error("buffers have invalid length")]
|
||||||
InvalidLengths,
|
InvalidLengths,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,54 @@ use thiserror::Error;
|
|||||||
///
|
///
|
||||||
/// The KEM interface defines three operations: Key generation, key encapsulation and key
|
/// The KEM interface defines three operations: Key generation, key encapsulation and key
|
||||||
/// decapsulation. The parameters are made available as associated constants for convenience.
|
/// decapsulation. The parameters are made available as associated constants for convenience.
|
||||||
|
///
|
||||||
|
/// The methods of this trait take a `&self` argument as a receiver. This has two reasons:
|
||||||
|
/// 1. It makes type inference a lot smoother
|
||||||
|
/// 2. It allows to use the functionality through a trait object or having an enum that has
|
||||||
|
/// variants for multiple options (like e.g. the `KeyedHash` enum in `rosenpass-ciphers`).
|
||||||
|
///
|
||||||
|
/// Since the caller needs an instance of the type to use the functionality, implementors are
|
||||||
|
/// adviced to implement the [`Default`] trait where possible.
|
||||||
|
///
|
||||||
|
/// Example for encrypting a message with a specific [`Kem`] instance:
|
||||||
|
/// ```
|
||||||
|
/// use rosenpass_cipher_traits::primitives::Kem;
|
||||||
|
///
|
||||||
|
/// const SK_LEN: usize = 1632;
|
||||||
|
/// const PK_LEN: usize = 800;
|
||||||
|
/// const CT_LEN: usize = 768;
|
||||||
|
/// const SHK_LEN: usize = 32;
|
||||||
|
///
|
||||||
|
/// fn encaps_given_a_kem<KemImpl>(
|
||||||
|
/// kem: &KemImpl,
|
||||||
|
/// pk: &[u8l PK_LEN],
|
||||||
|
/// ct: &mut [u8; CT_LEN]
|
||||||
|
/// ) where KemImpl: Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> -> [u8; SHK_LEN]{
|
||||||
|
/// let mut shk = [0u8; SHK_LEN];
|
||||||
|
/// kem.encaps(&mut shk, ct, pk).unwrap();
|
||||||
|
/// shk
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If only the type (but no instance) is available, then we can still use the trait, as long as
|
||||||
|
/// the type also is [`Default`]:
|
||||||
|
/// ```
|
||||||
|
/// use rosenpass_cipher_traits::primitives::Kem;
|
||||||
|
///
|
||||||
|
/// const SK_LEN: usize = 1632;
|
||||||
|
/// const PK_LEN: usize = 800;
|
||||||
|
/// const CT_LEN: usize = 768;
|
||||||
|
/// const SHK_LEN: usize = 32;
|
||||||
|
///
|
||||||
|
/// fn encaps_without_kem<KemImpl>(
|
||||||
|
/// pk: &[u8l PK_LEN],
|
||||||
|
/// ct: &mut [u8; CT_LEN]
|
||||||
|
/// ) where KemImpl: Default + Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> -> [u8; SHK_LEN]{
|
||||||
|
/// let mut shk = [0u8; SHK_LEN];
|
||||||
|
/// KemImpl::default().encaps(&mut shk, ct, pk).unwrap();
|
||||||
|
/// shk
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub trait Kem<const SK_LEN: usize, const PK_LEN: usize, const CT_LEN: usize, const SHK_LEN: usize> {
|
pub trait Kem<const SK_LEN: usize, const PK_LEN: usize, const CT_LEN: usize, const SHK_LEN: usize> {
|
||||||
/// The length of the secret (decapsulation) key.
|
/// The length of the secret (decapsulation) key.
|
||||||
const SK_LEN: usize = SK_LEN;
|
const SK_LEN: usize = SK_LEN;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Models a keyed hash function using an associated function (i.e. without `&self` receiver).
|
||||||
pub trait KeyedHash<const KEY_LEN: usize, const HASH_LEN: usize> {
|
pub trait KeyedHash<const KEY_LEN: usize, const HASH_LEN: usize> {
|
||||||
|
/// The error type used to signal what went wrong.
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
|
/// Performs a keyed hash using `key` and `data` and writes the output to `out`
|
||||||
fn keyed_hash(
|
fn keyed_hash(
|
||||||
key: &[u8; KEY_LEN],
|
key: &[u8; KEY_LEN],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
@@ -8,9 +13,15 @@ pub trait KeyedHash<const KEY_LEN: usize, const HASH_LEN: usize> {
|
|||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Models a keyed hash function using using a method (i.e. with a `&self` receiver).
|
||||||
|
///
|
||||||
|
/// This makes type inference easier, but also requires having a [`KeyedHashInstance`] value,
|
||||||
|
/// instead of just the [`KeyedHash`] type.
|
||||||
pub trait KeyedHashInstance<const KEY_LEN: usize, const HASH_LEN: usize> {
|
pub trait KeyedHashInstance<const KEY_LEN: usize, const HASH_LEN: usize> {
|
||||||
|
/// The error type used to signal what went wrong.
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
|
/// Performs a keyed hash using `key` and `data` and writes the output to `out`
|
||||||
fn keyed_hash(
|
fn keyed_hash(
|
||||||
&self,
|
&self,
|
||||||
key: &[u8; KEY_LEN],
|
key: &[u8; KEY_LEN],
|
||||||
@@ -19,8 +30,6 @@ pub trait KeyedHashInstance<const KEY_LEN: usize, const HASH_LEN: usize> {
|
|||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
/// This is a helper to allow for type parameter inference when calling functions
|
/// This is a helper to allow for type parameter inference when calling functions
|
||||||
/// that need a [KeyedHash].
|
/// that need a [KeyedHash].
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -13,10 +13,15 @@ readme = "readme.md"
|
|||||||
experiment_libcrux_all = [
|
experiment_libcrux_all = [
|
||||||
"experiment_libcrux_blake2",
|
"experiment_libcrux_blake2",
|
||||||
"experiment_libcrux_chachapoly",
|
"experiment_libcrux_chachapoly",
|
||||||
|
"experiment_libcrux_chachapoly_test",
|
||||||
"experiment_libcrux_kyber",
|
"experiment_libcrux_kyber",
|
||||||
]
|
]
|
||||||
experiment_libcrux_blake2 = ["dep:libcrux-blake2", "dep:thiserror"]
|
experiment_libcrux_blake2 = ["dep:libcrux-blake2", "dep:thiserror"]
|
||||||
experiment_libcrux_chachapoly = ["dep:libcrux-chacha20poly1305", "dep:libcrux"]
|
experiment_libcrux_chachapoly = ["dep:libcrux-chacha20poly1305"]
|
||||||
|
experiment_libcrux_chachapoly_test = [
|
||||||
|
"experiment_libcrux_chachapoly",
|
||||||
|
"dep:libcrux",
|
||||||
|
]
|
||||||
experiment_libcrux_kyber = ["dep:libcrux-ml-kem", "dep:rand"]
|
experiment_libcrux_kyber = ["dep:libcrux-ml-kem", "dep:rand"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -31,13 +36,16 @@ static_assertions = { workspace = true }
|
|||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
chacha20poly1305 = { workspace = true }
|
chacha20poly1305 = { workspace = true }
|
||||||
blake2 = { workspace = true }
|
blake2 = { workspace = true }
|
||||||
libcrux = { workspace = true, optional = true }
|
|
||||||
libcrux-chacha20poly1305 = { workspace = true, optional = true }
|
|
||||||
libcrux-blake2 = { workspace = true, optional = true }
|
|
||||||
libcrux-ml-kem = { workspace = true, optional = true, features = ["kyber"] }
|
|
||||||
sha3 = { workspace = true }
|
sha3 = { workspace = true }
|
||||||
rand = { workspace = true, optional = true }
|
rand = { workspace = true, optional = true }
|
||||||
thiserror = { workspace = true, optional = true }
|
thiserror = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
libcrux-chacha20poly1305 = { workspace = true, optional = true }
|
||||||
|
libcrux-blake2 = { workspace = true, optional = true }
|
||||||
|
libcrux-ml-kem = { workspace = true, optional = true, features = ["kyber"] }
|
||||||
|
|
||||||
|
# this one is only used in testing, so it requires the `experiment_libcrux_chachapoly_test` feature.
|
||||||
|
libcrux = { workspace = true, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
|
|||||||
@@ -1,16 +1,31 @@
|
|||||||
|
//! This module provides types that enabling choosing the keyed hash building block to be used at
|
||||||
|
//! runtime (using enums) instead of at compile time (using generics).
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
use rosenpass_cipher_traits::primitives::KeyedHashInstance;
|
||||||
|
|
||||||
pub const KEY_LEN: usize = 32;
|
use crate::subtle::{
|
||||||
pub const HASH_LEN: usize = 32;
|
custom::incorrect_hmac_blake2b::IncorrectHmacBlake2b, rust_crypto::keyed_shake256::SHAKE256_32,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Length of symmetric key throughout Rosenpass.
|
||||||
|
pub const KEY_LEN: usize = 32;
|
||||||
|
|
||||||
|
/// The hash is used as a symmetric key and should have the same length.
|
||||||
|
pub const HASH_LEN: usize = KEY_LEN;
|
||||||
|
|
||||||
|
/// Provides a way to pick which keyed hash to use at runtime.
|
||||||
|
/// Implements [`KeyedHashInstance`] to allow hashing using the respective algorithm.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub enum KeyedHash {
|
pub enum KeyedHash {
|
||||||
KeyedShake256(super::rust_crypto::keyed_shake256::SHAKE256<KEY_LEN, HASH_LEN>),
|
/// A hasher backed by [`SHAKE256_32`].
|
||||||
IncorrectHmacBlake2b(super::custom::incorrect_hmac_blake2b::IncorrectHmacBlake2b),
|
KeyedShake256(SHAKE256_32),
|
||||||
|
/// A hasher backed by [`IncorrectHmacBlake2b`].
|
||||||
|
IncorrectHmacBlake2b(IncorrectHmacBlake2b),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyedHash {
|
impl KeyedHash {
|
||||||
|
/// Creates an [`KeyedHash`] backed by SHAKE256.
|
||||||
pub fn keyed_shake256() -> Self {
|
pub fn keyed_shake256() -> Self {
|
||||||
Self::KeyedShake256(Default::default())
|
Self::KeyedShake256(Default::default())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
use rosenpass_cipher_traits::algorithms::KeyedHashBlake2b;
|
//! Implementation of the [`KeyedHashBlake2b`] trait based on the [`libcrux_blake2`] crate.
|
||||||
use rosenpass_cipher_traits::primitives::KeyedHash;
|
|
||||||
|
|
||||||
use libcrux_blake2::Blake2bBuilder;
|
use libcrux_blake2::Blake2bBuilder;
|
||||||
|
|
||||||
|
use rosenpass_cipher_traits::algorithms::KeyedHashBlake2b;
|
||||||
|
use rosenpass_cipher_traits::primitives::KeyedHash;
|
||||||
|
|
||||||
|
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::HASH_LEN;
|
||||||
|
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::KEY_LEN;
|
||||||
|
|
||||||
|
/// Describles which error occurred
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// An unexpected internal error occurred. Should never be returned and points to a bug in the
|
||||||
|
/// implementation.
|
||||||
#[error("internal error")]
|
#[error("internal error")]
|
||||||
InternalError,
|
InternalError,
|
||||||
|
|
||||||
|
/// Indicates that the provided data was too long.
|
||||||
#[error("data is too long")]
|
#[error("data is too long")]
|
||||||
DataTooLong,
|
DataTooLong,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hasher for the given `data` with the Blake2b hash function.
|
||||||
pub struct Blake2b;
|
pub struct Blake2b;
|
||||||
|
|
||||||
pub const KEY_LEN: usize = 32;
|
|
||||||
pub const HASH_LEN: usize = 32;
|
|
||||||
|
|
||||||
impl KeyedHash<KEY_LEN, HASH_LEN> for Blake2b {
|
impl KeyedHash<KEY_LEN, HASH_LEN> for Blake2b {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
|
//! Implementation of the [`AeadChaCha20Poly1305`] trait based on the [`libcrux_chacha20poly1305`] crate.
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::AeadChaCha20Poly1305;
|
use rosenpass_cipher_traits::algorithms::AeadChaCha20Poly1305;
|
||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
pub use rosenpass_cipher_traits::algorithms::aead_chacha20poly1305::{KEY_LEN, NONCE_LEN, TAG_LEN};
|
||||||
pub const KEY_LEN: usize = 32; // Grrrr! Libcrux, please provide me these constants.
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = 16;
|
|
||||||
/// The nonce length is 12 bytes or 96 bits.
|
|
||||||
pub const NONCE_LEN: usize = 12;
|
|
||||||
|
|
||||||
/// An implementation of the ChaCha20Poly1305 AEAD from libcrux
|
/// An implementation of the ChaCha20Poly1305 AEAD based on libcrux
|
||||||
pub struct ChaCha20Poly1305;
|
pub struct ChaCha20Poly1305;
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
||||||
@@ -64,53 +61,7 @@ mod equivalence_tests {
|
|||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fuzz_equivalence_libcrux_old_new() {
|
fn proptest_equivalence_libcrux_rustcrypto() {
|
||||||
let ptxts: [&[u8]; 3] = [
|
|
||||||
b"".as_slice(),
|
|
||||||
b"test".as_slice(),
|
|
||||||
b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
|
||||||
];
|
|
||||||
let mut key = [0; KEY_LEN];
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
|
|
||||||
let mut ctxt_left = [0; 64 + TAG_LEN];
|
|
||||||
let mut ctxt_right = [0; 64 + TAG_LEN];
|
|
||||||
|
|
||||||
let mut ptxt_left = [0; 64];
|
|
||||||
let mut ptxt_right = [0; 64];
|
|
||||||
|
|
||||||
let nonce = [0; NONCE_LEN];
|
|
||||||
let ad = b"";
|
|
||||||
|
|
||||||
for ptxt in ptxts {
|
|
||||||
for _ in 0..1000 {
|
|
||||||
rng.fill_bytes(&mut key);
|
|
||||||
let ctxt_left = &mut ctxt_left[..ptxt.len() + TAG_LEN];
|
|
||||||
let ctxt_right = &mut ctxt_right[..ptxt.len() + TAG_LEN];
|
|
||||||
|
|
||||||
let ptxt_left = &mut ptxt_left[..ptxt.len()];
|
|
||||||
let ptxt_right = &mut ptxt_right[..ptxt.len()];
|
|
||||||
|
|
||||||
encrypt(ctxt_left, &key, &nonce, ad, ptxt).unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.encrypt(ctxt_right, &key, &nonce, ad, ptxt)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ctxt_left, ctxt_right);
|
|
||||||
|
|
||||||
decrypt(ptxt_left, &key, &nonce, ad, ctxt_left).unwrap();
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.decrypt(ptxt_right, &key, &nonce, ad, ctxt_right)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ptxt_left, ptxt);
|
|
||||||
assert_eq!(ptxt_right, ptxt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn fuzz_equivalence_libcrux_rustcrypto() {
|
|
||||||
use crate::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305 as RustCryptoChaCha20Poly1305;
|
use crate::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305 as RustCryptoChaCha20Poly1305;
|
||||||
let ptxts: [&[u8]; 3] = [
|
let ptxts: [&[u8]; 3] = [
|
||||||
b"".as_slice(),
|
b"".as_slice(),
|
||||||
@@ -160,6 +111,54 @@ mod equivalence_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "experiment_libcrux_chachapoly_test")]
|
||||||
|
fn proptest_equivalence_libcrux_old_new() {
|
||||||
|
let ptxts: [&[u8]; 3] = [
|
||||||
|
b"".as_slice(),
|
||||||
|
b"test".as_slice(),
|
||||||
|
b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
||||||
|
];
|
||||||
|
let mut key = [0; KEY_LEN];
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let mut ctxt_left = [0; 64 + TAG_LEN];
|
||||||
|
let mut ctxt_right = [0; 64 + TAG_LEN];
|
||||||
|
|
||||||
|
let mut ptxt_left = [0; 64];
|
||||||
|
let mut ptxt_right = [0; 64];
|
||||||
|
|
||||||
|
let nonce = [0; NONCE_LEN];
|
||||||
|
let ad = b"";
|
||||||
|
|
||||||
|
for ptxt in ptxts {
|
||||||
|
for _ in 0..1000 {
|
||||||
|
rng.fill_bytes(&mut key);
|
||||||
|
let ctxt_left = &mut ctxt_left[..ptxt.len() + TAG_LEN];
|
||||||
|
let ctxt_right = &mut ctxt_right[..ptxt.len() + TAG_LEN];
|
||||||
|
|
||||||
|
let ptxt_left = &mut ptxt_left[..ptxt.len()];
|
||||||
|
let ptxt_right = &mut ptxt_right[..ptxt.len()];
|
||||||
|
|
||||||
|
encrypt(ctxt_left, &key, &nonce, ad, ptxt).unwrap();
|
||||||
|
ChaCha20Poly1305
|
||||||
|
.encrypt(ctxt_right, &key, &nonce, ad, ptxt)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(ctxt_left, ctxt_right);
|
||||||
|
|
||||||
|
decrypt(ptxt_left, &key, &nonce, ad, ctxt_left).unwrap();
|
||||||
|
ChaCha20Poly1305
|
||||||
|
.decrypt(ptxt_right, &key, &nonce, ad, ctxt_right)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(ptxt_left, ptxt);
|
||||||
|
assert_eq!(ptxt_right, ptxt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The old libcrux functions:
|
||||||
|
|
||||||
// The functions below are from the old libcrux backend. I am keeping them around so we can
|
// The functions below are from the old libcrux backend. I am keeping them around so we can
|
||||||
// check if they behave the same.
|
// check if they behave the same.
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
@@ -272,3 +271,4 @@ mod equivalence_tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
use libcrux_ml_kem::kyber512;
|
//! Implementation of the [`KemKyber512`] trait based on the [`libcrux_ml_kem`] crate.
|
||||||
|
|
||||||
|
use libcrux_ml_kem::kyber512;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::algorithms::kem_kyber512::*;
|
use rosenpass_cipher_traits::algorithms::KemKyber512;
|
||||||
use rosenpass_cipher_traits::primitives::{Kem, KemError};
|
use rosenpass_cipher_traits::primitives::{Kem, KemError};
|
||||||
|
|
||||||
|
pub use rosenpass_cipher_traits::algorithms::kem_kyber512::{CT_LEN, PK_LEN, SHK_LEN, SK_LEN};
|
||||||
|
|
||||||
|
/// An implementation of the Kyber512 KEM based on libcrux
|
||||||
pub struct Kyber512;
|
pub struct Kyber512;
|
||||||
|
|
||||||
impl Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for Kyber512 {
|
impl Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for Kyber512 {
|
||||||
@@ -60,3 +64,70 @@ impl Default for Kyber512 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KemKyber512 for Kyber512 {}
|
impl KemKyber512 for Kyber512 {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod equivalence_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Test that libcrux and OQS produce the same results
|
||||||
|
#[test]
|
||||||
|
fn proptest_equivalence_libcrux_oqs() {
|
||||||
|
use rosenpass_oqs::Kyber512 as OqsKyber512;
|
||||||
|
|
||||||
|
let (mut sk1, mut pk1) = ([0; SK_LEN], [0; PK_LEN]);
|
||||||
|
let (mut sk2, mut pk2) = ([0; SK_LEN], [0; PK_LEN]);
|
||||||
|
|
||||||
|
let mut ct_left = [0; CT_LEN];
|
||||||
|
let mut ct_right = [0; CT_LEN];
|
||||||
|
|
||||||
|
let mut shk_enc_left = [0; SHK_LEN];
|
||||||
|
let mut shk_enc_right = [0; SHK_LEN];
|
||||||
|
|
||||||
|
// naming schema: shk_dec_{encapsing lib}_{decapsing lib}
|
||||||
|
// should be the same if the encapsing lib was the same.
|
||||||
|
let mut shk_dec_left_left = [0; SHK_LEN];
|
||||||
|
let mut shk_dec_left_right = [0; SHK_LEN];
|
||||||
|
let mut shk_dec_right_left = [0; SHK_LEN];
|
||||||
|
let mut shk_dec_right_right = [0; SHK_LEN];
|
||||||
|
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let sk1 = &mut sk1;
|
||||||
|
let pk1 = &mut pk1;
|
||||||
|
let sk2 = &mut sk2;
|
||||||
|
let pk2 = &mut pk2;
|
||||||
|
|
||||||
|
let ct_left = &mut ct_left;
|
||||||
|
let ct_right = &mut ct_right;
|
||||||
|
|
||||||
|
let shk_enc_left = &mut shk_enc_left;
|
||||||
|
let shk_enc_right = &mut shk_enc_right;
|
||||||
|
|
||||||
|
let shk_dec_left_left = &mut shk_dec_left_left;
|
||||||
|
let shk_dec_left_right = &mut shk_dec_left_right;
|
||||||
|
let shk_dec_right_left = &mut shk_dec_right_left;
|
||||||
|
let shk_dec_right_right = &mut shk_dec_right_right;
|
||||||
|
|
||||||
|
Kyber512.keygen(sk1, pk1).unwrap();
|
||||||
|
Kyber512.keygen(sk2, pk2).unwrap();
|
||||||
|
|
||||||
|
Kyber512.encaps(shk_enc_left, ct_left, pk2).unwrap();
|
||||||
|
OqsKyber512.encaps(shk_enc_right, ct_right, pk2).unwrap();
|
||||||
|
|
||||||
|
Kyber512.decaps(shk_dec_left_left, sk2, ct_left).unwrap();
|
||||||
|
Kyber512.decaps(shk_dec_right_left, sk2, ct_right).unwrap();
|
||||||
|
|
||||||
|
OqsKyber512
|
||||||
|
.decaps(shk_dec_left_right, sk2, ct_left)
|
||||||
|
.unwrap();
|
||||||
|
OqsKyber512
|
||||||
|
.decaps(shk_dec_right_right, sk2, ct_right)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(shk_enc_left, shk_dec_left_left);
|
||||||
|
assert_eq!(shk_enc_left, shk_dec_left_right);
|
||||||
|
|
||||||
|
assert_eq!(shk_enc_right, shk_dec_right_left);
|
||||||
|
assert_eq!(shk_enc_right, shk_dec_right_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
//! Implementations backed by libcrux, a verified crypto library
|
//! Implementations backed by libcrux, a verified crypto library.
|
||||||
|
//!
|
||||||
|
//! [Website](https://cryspen.com/libcrux/)
|
||||||
|
//!
|
||||||
|
//! [Github](https://github.com/cryspen/libcrux)
|
||||||
|
|
||||||
#[cfg(feature = "experiment_libcrux_blake2")]
|
#[cfg(feature = "experiment_libcrux_blake2")]
|
||||||
pub mod blake2b;
|
pub mod blake2b;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//! Contains the implementations of the crypto algorithms used throughout Rosenpass.
|
||||||
|
|
||||||
pub mod keyed_hash;
|
pub mod keyed_hash;
|
||||||
|
|
||||||
pub use custom::incorrect_hmac_blake2b;
|
pub use custom::incorrect_hmac_blake2b;
|
||||||
|
|||||||
@@ -8,26 +8,24 @@ use blake2::Blake2bMac;
|
|||||||
use rosenpass_cipher_traits::primitives::KeyedHash;
|
use rosenpass_cipher_traits::primitives::KeyedHash;
|
||||||
use rosenpass_to::{ops::copy_slice, To};
|
use rosenpass_to::{ops::copy_slice, To};
|
||||||
|
|
||||||
|
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::HASH_LEN;
|
||||||
|
pub use rosenpass_cipher_traits::algorithms::keyed_hash_blake2b::KEY_LEN;
|
||||||
|
|
||||||
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
/// Specify that the used implementation of BLAKE2b is the MAC version of BLAKE2b
|
||||||
/// with output and key length of 32 bytes (see [Blake2bMac]).
|
/// with output and key length of 32 bytes (see [Blake2bMac]).
|
||||||
type Impl = Blake2bMac<U32>;
|
type Impl = Blake2bMac<U32>;
|
||||||
|
|
||||||
/// The key length for BLAKE2b supported by this API. Currently 32 Bytes.
|
|
||||||
const KEY_LEN: usize = 32;
|
|
||||||
/// The output length for BLAKE2b supported by this API. Currently 32 Bytes.
|
|
||||||
const OUT_LEN: usize = 32;
|
|
||||||
|
|
||||||
/// Hashes the given `data` with the [Blake2bMac] hash function under the given `key`.
|
/// Hashes the given `data` with the [Blake2bMac] hash function under the given `key`.
|
||||||
/// The both the length of the output the length of the key 32 bytes (or 256 bits).
|
/// The both the length of the output the length of the key 32 bytes (or 256 bits).
|
||||||
pub struct Blake2b;
|
pub struct Blake2b;
|
||||||
|
|
||||||
impl KeyedHash<KEY_LEN, OUT_LEN> for Blake2b {
|
impl KeyedHash<KEY_LEN, HASH_LEN> for Blake2b {
|
||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
fn keyed_hash(
|
fn keyed_hash(
|
||||||
key: &[u8; KEY_LEN],
|
key: &[u8; KEY_LEN],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
out: &mut [u8; OUT_LEN],
|
out: &mut [u8; HASH_LEN],
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
let mut h = Impl::new_from_slice(key)?;
|
let mut h = Impl::new_from_slice(key)?;
|
||||||
h.update(data);
|
h.update(data);
|
||||||
@@ -36,7 +34,7 @@ impl KeyedHash<KEY_LEN, OUT_LEN> for Blake2b {
|
|||||||
// but it introduces a ton of complexity. This cost me half an hour just to figure
|
// but it introduces a ton of complexity. This cost me half an hour just to figure
|
||||||
// out the right way to use the imports while allowing for zeroization.
|
// out the right way to use the imports while allowing for zeroization.
|
||||||
// An API based on slices might actually be simpler.
|
// An API based on slices might actually be simpler.
|
||||||
let mut tmp = Zeroizing::new([0u8; OUT_LEN]);
|
let mut tmp = Zeroizing::new([0u8; HASH_LEN]);
|
||||||
let tmp = GenericArray::from_mut_slice(tmp.as_mut());
|
let tmp = GenericArray::from_mut_slice(tmp.as_mut());
|
||||||
h.finalize_into(tmp);
|
h.finalize_into(tmp);
|
||||||
copy_slice(tmp.as_ref()).to(out);
|
copy_slice(tmp.as_ref()).to(out);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
use rosenpass_util::typenum2const;
|
|
||||||
|
use rosenpass_cipher_traits::algorithms::AeadChaCha20Poly1305;
|
||||||
|
use rosenpass_cipher_traits::primitives::{Aead, AeadError};
|
||||||
|
|
||||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||||
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
|
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
|
||||||
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
use chacha20poly1305::{AeadInPlace, KeyInit};
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
pub use rosenpass_cipher_traits::algorithms::aead_chacha20poly1305::{KEY_LEN, NONCE_LEN, TAG_LEN};
|
||||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|
||||||
/// The nonce length is 12 bytes or 96 bits.
|
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
|
||||||
|
|
||||||
|
/// Implements the [`Aead`] and [`AeadChaCha20Poly1305`] traits backed by the RustCrypto
|
||||||
|
/// implementation.
|
||||||
pub struct ChaCha20Poly1305;
|
pub struct ChaCha20Poly1305;
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
||||||
@@ -78,81 +76,4 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for ChaCha20Poly1305 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encrypts using ChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
impl AeadChaCha20Poly1305 for ChaCha20Poly1305 {}
|
||||||
/// `key` MUST be chosen (pseudo-)randomly and `nonce` MOST NOT be reused. The `key` slice MUST have
|
|
||||||
/// a length of [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN]. The last [TAG_LEN] bytes
|
|
||||||
/// written in `ciphertext` are the tag guaranteeing integrity. `ciphertext` MUST have a capacity of
|
|
||||||
/// `plaintext.len()` + [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::rust_crypto::chacha20poly1305_ietf::{encrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
///
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// let plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN, plaintext.len());
|
|
||||||
/// let key: &[u8; KEY_LEN] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8; NONCE_LEN] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut ciphertext_buffer = [0u8;PLAINTEXT_LEN + TAG_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = encrypt(&mut ciphertext_buffer, key, nonce, additional_data, plaintext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// # let expected_ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// # 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// # 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// # 8, 114, 85, 4, 25];
|
|
||||||
/// # assert_eq!(expected_ciphertext, &ciphertext_buffer);
|
|
||||||
///```
|
|
||||||
#[inline]
|
|
||||||
pub fn encrypt(
|
|
||||||
ciphertext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
plaintext: &[u8],
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.encrypt(ciphertext, key, nonce, ad, plaintext)
|
|
||||||
.map_err(anyhow::Error::from)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decrypts a `ciphertext` and verifies the integrity of the `ciphertext` and the additional data
|
|
||||||
/// `ad`. using ChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
|
||||||
///
|
|
||||||
/// The `key` slice MUST have a length of [KEY_LEN]. The `nonce` slice MUST have a length of
|
|
||||||
/// [NONCE_LEN]. The plaintext buffer must have a capacity of `ciphertext.len()` - [TAG_LEN].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///```rust
|
|
||||||
/// # use rosenpass_ciphers::subtle::rust_crypto::chacha20poly1305_ietf::{decrypt, TAG_LEN, KEY_LEN, NONCE_LEN};
|
|
||||||
/// let ciphertext: &[u8] = &[239, 104, 148, 202, 120, 32, 77, 27, 246, 206, 226, 17,
|
|
||||||
/// 83, 78, 122, 116, 187, 123, 70, 199, 58, 130, 21, 1, 107, 230, 58, 77, 18, 152, 31, 159, 80,
|
|
||||||
/// 151, 72, 27, 236, 137, 60, 55, 180, 31, 71, 97, 199, 12, 60, 155, 70, 221, 225, 110, 132, 191,
|
|
||||||
/// 8, 114, 85, 4, 25]; // this is the ciphertext generated by the example for the encryption
|
|
||||||
/// const PLAINTEXT_LEN: usize = 43;
|
|
||||||
/// assert_eq!(PLAINTEXT_LEN + TAG_LEN, ciphertext.len());
|
|
||||||
///
|
|
||||||
/// let key: &[u8; KEY_LEN] = &[0u8; KEY_LEN]; // THIS IS NOT A SECURE KEY
|
|
||||||
/// let nonce: &[u8; NONCE_LEN] = &[0u8; NONCE_LEN]; // THIS IS NOT A SECURE NONCE
|
|
||||||
/// let additional_data: &[u8] = "the encrypted message is very important".as_bytes();
|
|
||||||
/// let mut plaintext_buffer = [0u8; PLAINTEXT_LEN];
|
|
||||||
///
|
|
||||||
/// let res: anyhow::Result<()> = decrypt(&mut plaintext_buffer, key, nonce, additional_data, ciphertext);
|
|
||||||
/// assert!(res.is_ok());
|
|
||||||
/// let expected_plaintext = "post-quantum cryptography is very important".as_bytes();
|
|
||||||
/// assert_eq!(expected_plaintext, plaintext_buffer);
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
#[inline]
|
|
||||||
pub fn decrypt(
|
|
||||||
plaintext: &mut [u8],
|
|
||||||
key: &[u8; KEY_LEN],
|
|
||||||
nonce: &[u8; NONCE_LEN],
|
|
||||||
ad: &[u8],
|
|
||||||
ciphertext: &[u8],
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
ChaCha20Poly1305
|
|
||||||
.decrypt(plaintext, key, nonce, ad, ciphertext)
|
|
||||||
.map_err(anyhow::Error::from)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use rosenpass_cipher_traits::primitives::{InferKeyedHash, KeyedHash};
|
|||||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
||||||
use sha3::Shake256;
|
use sha3::Shake256;
|
||||||
|
|
||||||
|
/// An implementation of the [`KeyedHash`] trait backed by the RustCrypto implementation of SHAKE256.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct SHAKE256Core<const KEY_LEN: usize, const HASH_LEN: usize>;
|
pub struct SHAKE256Core<const KEY_LEN: usize, const HASH_LEN: usize>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
use rosenpass_cipher_traits::primitives::{Aead, AeadError, AeadWithNonceInCiphertext};
|
|
||||||
use rosenpass_to::ops::copy_slice;
|
use rosenpass_to::ops::copy_slice;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
use rosenpass_util::typenum2const;
|
|
||||||
|
use rosenpass_cipher_traits::algorithms::aead_xchacha20poly1305::{
|
||||||
|
AeadXChaCha20Poly1305, KEY_LEN, NONCE_LEN, TAG_LEN,
|
||||||
|
};
|
||||||
|
use rosenpass_cipher_traits::primitives::{Aead, AeadError, AeadWithNonceInCiphertext};
|
||||||
|
|
||||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||||
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
|
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
|
||||||
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
use chacha20poly1305::{AeadInPlace, KeyInit};
|
||||||
|
|
||||||
/// The key length is 32 bytes or 256 bits.
|
|
||||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
|
||||||
/// The MAC tag length is 16 bytes or 128 bits.
|
|
||||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
|
||||||
/// The nonce length is 24 bytes or 192 bits.
|
|
||||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
|
||||||
|
|
||||||
|
/// Implements the [`Aead`] and [`AeadXChaCha20Poly1305`] traits backed by the RustCrypto
|
||||||
|
/// implementation.
|
||||||
pub struct XChaCha20Poly1305;
|
pub struct XChaCha20Poly1305;
|
||||||
|
|
||||||
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
|
impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
|
||||||
@@ -77,6 +75,8 @@ impl Aead<KEY_LEN, NONCE_LEN, TAG_LEN> for XChaCha20Poly1305 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AeadXChaCha20Poly1305 for XChaCha20Poly1305 {}
|
||||||
|
|
||||||
/// Encrypts using XChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
/// Encrypts using XChaCha20Poly1305 as implemented in [RustCrypto](https://github.com/RustCrypto/AEADs/tree/master/chacha20poly1305).
|
||||||
/// `key` and `nonce` MUST be chosen (pseudo-)randomly. The `key` slice MUST have a length of
|
/// `key` and `nonce` MUST be chosen (pseudo-)randomly. The `key` slice MUST have a length of
|
||||||
/// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN].
|
/// [KEY_LEN]. The `nonce` slice MUST have a length of [NONCE_LEN].
|
||||||
|
|||||||
@@ -3337,35 +3337,18 @@ impl HandshakeState {
|
|||||||
const KEM_PK_LEN: usize,
|
const KEM_PK_LEN: usize,
|
||||||
const KEM_CT_LEN: usize,
|
const KEM_CT_LEN: usize,
|
||||||
const KEM_SHK_LEN: usize,
|
const KEM_SHK_LEN: usize,
|
||||||
T: Default + Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
KemImpl: Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
kem: &KemImpl,
|
||||||
ct: &mut [u8; KEM_CT_LEN],
|
ct: &mut [u8; KEM_CT_LEN],
|
||||||
pk: &[u8; KEM_PK_LEN],
|
pk: &[u8; KEM_PK_LEN],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
||||||
T::default().encaps(shk.secret_mut(), ct, pk)?;
|
kem.encaps(shk.secret_mut(), ct, pk)?;
|
||||||
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls [`Self::encaps_and_mix`] with the generic parameters that match [`StaticKem`].
|
|
||||||
pub fn encaps_and_mix_static(
|
|
||||||
&mut self,
|
|
||||||
ct: &mut [u8; StaticKem::CT_LEN],
|
|
||||||
pk: &[u8; StaticKem::PK_LEN],
|
|
||||||
) -> Result<&mut Self> {
|
|
||||||
self.encaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(ct, pk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calls [`Self::encaps_and_mix`] with the generic parameters that match [`EphemeralKem`].
|
|
||||||
pub fn encaps_and_mix_ephemeral(
|
|
||||||
&mut self,
|
|
||||||
ct: &mut [u8; EphemeralKem::CT_LEN],
|
|
||||||
pk: &[u8; EphemeralKem::PK_LEN],
|
|
||||||
) -> Result<&mut Self> {
|
|
||||||
self.encaps_and_mix::<{EphemeralKem::SK_LEN},{ EphemeralKem::PK_LEN}, {EphemeralKem::CT_LEN}, {EphemeralKem::SHK_LEN}, EphemeralKem>(ct, pk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decapsulation (decryption) counterpart to [Self::encaps_and_mix].
|
/// Decapsulation (decryption) counterpart to [Self::encaps_and_mix].
|
||||||
///
|
///
|
||||||
/// Makes sure that the same values are mixed into the chaining that where mixed in on the
|
/// Makes sure that the same values are mixed into the chaining that where mixed in on the
|
||||||
@@ -3375,38 +3358,19 @@ impl HandshakeState {
|
|||||||
const KEM_PK_LEN: usize,
|
const KEM_PK_LEN: usize,
|
||||||
const KEM_CT_LEN: usize,
|
const KEM_CT_LEN: usize,
|
||||||
const KEM_SHK_LEN: usize,
|
const KEM_SHK_LEN: usize,
|
||||||
T: Default + Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
KemImpl: Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
kem: &KemImpl,
|
||||||
sk: &[u8; KEM_SK_LEN],
|
sk: &[u8; KEM_SK_LEN],
|
||||||
pk: &[u8; KEM_PK_LEN],
|
pk: &[u8; KEM_PK_LEN],
|
||||||
ct: &[u8; KEM_CT_LEN],
|
ct: &[u8; KEM_CT_LEN],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
||||||
T::default().decaps(shk.secret_mut(), sk, ct)?;
|
kem.decaps(shk.secret_mut(), sk, ct)?;
|
||||||
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls [`Self::decaps_and_mix`] with the generic parameters that match [`StaticKem`].
|
|
||||||
pub fn decaps_and_mix_static(
|
|
||||||
&mut self,
|
|
||||||
sk: &[u8; StaticKem::SK_LEN],
|
|
||||||
pk: &[u8; StaticKem::PK_LEN],
|
|
||||||
ct: &[u8; StaticKem::CT_LEN],
|
|
||||||
) -> Result<&mut Self> {
|
|
||||||
self.decaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(sk, pk, ct)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calls [`Self::decaps_and_mix`] with the generic parameters that match [`EphemeralKem`].
|
|
||||||
pub fn decaps_and_mix_ephemeral(
|
|
||||||
&mut self,
|
|
||||||
sk: &[u8; EphemeralKem::SK_LEN],
|
|
||||||
pk: &[u8; EphemeralKem::PK_LEN],
|
|
||||||
ct: &[u8; EphemeralKem::CT_LEN],
|
|
||||||
) -> Result<&mut Self> {
|
|
||||||
self.decaps_and_mix::<{EphemeralKem::SK_LEN},{ EphemeralKem::PK_LEN}, {EphemeralKem::CT_LEN}, {EphemeralKem::SHK_LEN}, EphemeralKem>(sk, pk, ct)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Store the chaining key inside a cookie value called a "biscuit".
|
/// Store the chaining key inside a cookie value called a "biscuit".
|
||||||
///
|
///
|
||||||
/// This biscuit can be transmitted to the other party and must be returned
|
/// This biscuit can be transmitted to the other party and must be returned
|
||||||
@@ -3595,7 +3559,7 @@ impl CryptoServer {
|
|||||||
|
|
||||||
// IHI5
|
// IHI5
|
||||||
hs.core
|
hs.core
|
||||||
.encaps_and_mix_static(&mut ih.sctr, peer.get(self).spkt.deref())?;
|
.encaps_and_mix(&StaticKem, &mut ih.sctr, peer.get(self).spkt.deref())?;
|
||||||
|
|
||||||
// IHI6
|
// IHI6
|
||||||
hs.core.encrypt_and_mix(
|
hs.core.encrypt_and_mix(
|
||||||
@@ -3638,7 +3602,7 @@ impl CryptoServer {
|
|||||||
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
||||||
|
|
||||||
// IHR5
|
// IHR5
|
||||||
core.decaps_and_mix_static(self.sskm.secret(), self.spkm.deref(), &ih.sctr)?;
|
core.decaps_and_mix(&StaticKem, self.sskm.secret(), self.spkm.deref(), &ih.sctr)?;
|
||||||
|
|
||||||
// IHR6
|
// IHR6
|
||||||
let peer = {
|
let peer = {
|
||||||
@@ -3664,10 +3628,10 @@ impl CryptoServer {
|
|||||||
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
||||||
|
|
||||||
// RHR4
|
// RHR4
|
||||||
core.encaps_and_mix_ephemeral(&mut rh.ecti, &ih.epki)?;
|
core.encaps_and_mix(&EphemeralKem, &mut rh.ecti, &ih.epki)?;
|
||||||
|
|
||||||
// RHR5
|
// RHR5
|
||||||
core.encaps_and_mix_static(&mut rh.scti, peer.get(self).spkt.deref())?;
|
core.encaps_and_mix(&StaticKem, &mut rh.scti, peer.get(self).spkt.deref())?;
|
||||||
|
|
||||||
// RHR6
|
// RHR6
|
||||||
core.store_biscuit(self, peer, &mut rh.biscuit)?;
|
core.store_biscuit(self, peer, &mut rh.biscuit)?;
|
||||||
@@ -3727,10 +3691,15 @@ impl CryptoServer {
|
|||||||
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
||||||
|
|
||||||
// RHI4
|
// RHI4
|
||||||
core.decaps_and_mix_ephemeral(hs!().eski.secret(), hs!().epki.deref(), &rh.ecti)?;
|
core.decaps_and_mix(
|
||||||
|
&EphemeralKem,
|
||||||
|
hs!().eski.secret(),
|
||||||
|
hs!().epki.deref(),
|
||||||
|
&rh.ecti,
|
||||||
|
)?;
|
||||||
|
|
||||||
// RHI5
|
// RHI5
|
||||||
core.decaps_and_mix_static(self.sskm.secret(), self.spkm.deref(), &rh.scti)?;
|
core.decaps_and_mix(&StaticKem, self.sskm.secret(), self.spkm.deref(), &rh.scti)?;
|
||||||
|
|
||||||
// RHI6
|
// RHI6
|
||||||
core.mix(&rh.biscuit)?;
|
core.mix(&rh.biscuit)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user