Reorganize the ciphers crate

This commit is contained in:
Jan Winkelmann (keks)
2025-02-25 11:50:43 +01:00
parent 46ebb6f46c
commit a1f41953b7
20 changed files with 217 additions and 218 deletions

View File

@@ -1,14 +1,13 @@
//!
//!```rust
//! # use rosenpass_ciphers::hash_domain::{HashDomain, HashDomainNamespace, SecretHashDomain, SecretHashDomainNamespace};
//! use rosenpass_ciphers::subtle::either_hash::EitherShakeOrBlake;
//! use rosenpass_ciphers::subtle::keyed_shake256::SHAKE256Core;
//! use rosenpass_ciphers::keyed_hash::KeyedHash;
//! use rosenpass_secret_memory::Secret;
//! # rosenpass_secret_memory::secret_policy_use_only_malloc_secrets();
//!
//! const PROTOCOL_IDENTIFIER: &str = "MY_PROTOCOL:IDENTIFIER";
//! // create use once hash domain for the protocol identifier
//! let mut hash_domain = HashDomain::zero(EitherShakeOrBlake::Left(SHAKE256Core));
//! let mut hash_domain = HashDomain::zero(KeyedHash::keyed_shake256());
//! hash_domain = hash_domain.mix(PROTOCOL_IDENTIFIER.as_bytes())?;
//! // upgrade to reusable hash domain
//! let hash_domain_namespace: HashDomainNamespace = hash_domain.dup();
@@ -30,12 +29,9 @@
use anyhow::Result;
use rosenpass_secret_memory::Secret;
use rosenpass_to::To;
use crate::keyed_hash as hash;
pub use crate::keyed_hash::{KeyedHash, KEY_LEN};
use crate::subtle::either_hash::KeyedHash;
pub use hash::KEY_LEN;
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
// TODO Use a proper Dec interface
@@ -120,6 +116,8 @@ impl HashDomainNamespace {
}
impl SecretHashDomain {
// XXX: Why is the old hash still used unconditionally?
//
/// Create a new [SecretHashDomain] with the given key `k` and data `d` by calling
/// [hash::hash] with `k` as the `key` and `d` s the `data`, and using the result
/// as the content for the new [SecretHashDomain].
@@ -133,7 +131,7 @@ impl SecretHashDomain {
let mut new_secret_key = Secret::zero();
hash_choice.keyed_hash(k.try_into()?, d, new_secret_key.secret_mut())?;
let mut r = SecretHashDomain(new_secret_key, hash_choice);
hash::hash(k, d).to(r.0.secret_mut())?;
KeyedHash::incorrect_hmac_blake2b().keyed_hash(k.try_into()?, d, r.0.secret_mut())?;
Ok(r)
}
@@ -177,13 +175,23 @@ impl SecretHashDomain {
self.0
}
/// Evaluate [hash::hash] with this [SecretHashDomain]'s data as the `key` and
/// `dst` as the `data` and stores the result as the new data for this [SecretHashDomain].
///
/// It requires that both `v` and `d` consist of exactly [KEY_LEN] many bytes.
pub fn into_secret_slice(mut self, v: &[u8], dst: &[u8]) -> Result<()> {
hash::hash(v, dst).to(self.0.secret_mut())
}
/* XXX: This code was calling the specific hmac-blake2b code as well as the new KeyedHash enum
* (f.k.a. EitherHash). I was confused by the way the code used the local variables, because it
* didn't match the code. I made the code match the documentation, but I'm not sure that is
* correct. Either way, it doesn't look like this is used anywhere. Maybe just remove it?
*
* /// Evaluate [hash::hash] with this [SecretHashDomain]'s data as the `key` and
* /// `dst` as the `data` and stores the result as the new data for this [SecretHashDomain].
* pub fn into_secret_slice(mut self, v: &[u8; KEY_LEN], dst: &[u8; KEY_LEN]) -> Result<()> {
* let SecretHashDomain(secret, hash_choice) = &self;
*
* let mut new_secret = Secret::zero();
* hash_choice.keyed_hash(secret.secret(), dst, new_secret.secret_mut())?;
* self.0 = new_secret;
*
* Ok(())
* }
*/
}
impl SecretHashDomainNamespace {

View File

@@ -13,19 +13,18 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN);
/// This should only be used for implementation details; anything with relevance
/// to the cryptographic protocol should use the facilities in [hash_domain], (though
/// hash domain uses this module internally)
pub mod keyed_hash {
pub use crate::subtle::incorrect_hmac_blake2b::{
hash, KEY_LEN, KEY_MAX, KEY_MIN, OUT_MAX, OUT_MIN,
};
}
pub use crate::subtle::keyed_hash;
/// Authenticated encryption with associated data
/// Chacha20poly1305 is used.
pub mod aead {
#[cfg(not(feature = "experiment_libcrux"))]
pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN};
#[cfg(feature = "experiment_libcrux")]
pub use crate::subtle::chacha20poly1305_ietf_libcrux::{
pub use crate::subtle::libcrux::chacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
#[cfg(not(feature = "experiment_libcrux"))]
pub use crate::subtle::rust_crypto::chacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}
@@ -33,7 +32,7 @@ pub mod aead {
/// Authenticated encryption with associated data with a constant nonce
/// XChacha20poly1305 is used.
pub mod xaead {
pub use crate::subtle::xchacha20poly1305_ietf::{
pub use crate::subtle::rust_crypto::xchacha20poly1305_ietf::{
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
};
}

View File

@@ -1,22 +1,16 @@
use anyhow::ensure;
use rosenpass_cipher_traits::keyed_hash::KeyedHash;
use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash};
use rosenpass_constant_time::xor;
use rosenpass_to::{ops::copy_slice, with_destination, To};
use rosenpass_to::{ops::copy_slice, To};
use zeroize::Zeroizing;
use crate::subtle::hash_functions::blake2b;
use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash;
use crate::subtle::rust_crypto::blake2b;
/// The key length, 32 bytes or 256 bits.
pub const KEY_LEN: usize = 32;
/// The minimal key length, identical to [KEY_LEN]
pub const KEY_MIN: usize = KEY_LEN;
/// The maximal key length, identical to [KEY_LEN]
pub const KEY_MAX: usize = KEY_LEN;
/// The minimal output length, see [blake2b::OUT_MIN]
pub const OUT_MIN: usize = blake2b::OUT_MIN;
/// The maximal output length, see [blake2b::OUT_MAX]
pub const OUT_MAX: usize = blake2b::OUT_MAX;
/// The hash length, 32 bytes or 256 bits.
pub const HASH_LEN: usize = 32;
/// This is a woefully incorrect implementation of hmac_blake2b.
/// See <https://github.com/rosenpass/rosenpass/issues/68#issuecomment-1563612222>
@@ -41,12 +35,20 @@ pub const OUT_MAX: usize = blake2b::OUT_MAX;
/// # assert_eq!(hash_data, expected_hash);
///```
///
#[inline]
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IncorrectHmacBlake2bCore;
impl KeyedHash<KEY_LEN, HASH_LEN> for IncorrectHmacBlake2bCore {
type Error = anyhow::Error;
fn keyed_hash(
key: &[u8; KEY_LEN],
data: &[u8],
out: &mut [u8; HASH_LEN],
) -> Result<(), Self::Error> {
const IPAD: [u8; KEY_LEN] = [0x36u8; KEY_LEN];
const OPAD: [u8; KEY_LEN] = [0x5Cu8; KEY_LEN];
with_destination(|out: &mut [u8]| {
// Not bothering with padding; the implementation
// uses appropriately sized keys.
ensure!(key.len() == KEY_LEN);
@@ -64,18 +66,7 @@ pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<(
blake2b::hash(tmp_key.as_ref(), outer_data.as_ref()).to(out)?;
Ok(())
})
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Blake2bCore;
impl KeyedHash<32, 32> for Blake2bCore {
type Error = anyhow::Error;
fn keyed_hash(key: &[u8; 32], data: &[u8], out: &mut [u8; 32]) -> Result<(), Self::Error> {
hash(key, data).to(out)
}
}
pub type Blake2b = InferKeyedHash<Blake2bCore, 32, 32>;
pub type IncorrectHmacBlake2b = InferKeyedHash<IncorrectHmacBlake2bCore, KEY_LEN, HASH_LEN>;

View File

@@ -0,0 +1,3 @@
//! Own implementations of custom algorithms
pub mod incorrect_hmac_blake2b;

View File

@@ -1,90 +0,0 @@
use anyhow::Result;
use rosenpass_cipher_traits::keyed_hash::{KeyedHash, KeyedHashInstance};
use std::marker::PhantomData;
/// This is a helper to allow for type parameter inference when calling functions
/// that need a [KeyedHash].
///
/// Really just binds the [KeyedHash] trait to a dummy variable, so the type of this dummy variable
/// can be used for type inference. Less typing work.
#[derive(Debug, PartialEq, Eq)]
pub struct InferKeyedHash<Static, const KEY_LEN: usize, const HASH_LEN: usize>
where
Static: KeyedHash<KEY_LEN, HASH_LEN>,
{
pub _phantom_keyed_hasher: PhantomData<*const Static>,
}
impl<Static, const KEY_LEN: usize, const HASH_LEN: usize> InferKeyedHash<Static, KEY_LEN, HASH_LEN>
where
Static: KeyedHash<KEY_LEN, HASH_LEN, Error = anyhow::Error>,
{
pub const KEY_LEN: usize = KEY_LEN;
pub const HASH_LEN: usize = HASH_LEN;
pub const fn new() -> Self {
Self {
_phantom_keyed_hasher: PhantomData,
}
}
/// This just forwards to [KeyedHash::keyed_hash] of the type parameter `Static`
fn keyed_hash_internal<'a>(
&self,
key: &'a [u8; KEY_LEN],
data: &'a [u8],
out: &mut [u8; HASH_LEN],
) -> Result<()> {
Static::keyed_hash(key, data, out)
}
pub const fn key_len(self) -> usize {
Self::KEY_LEN
}
pub const fn hash_len(self) -> usize {
Self::HASH_LEN
}
}
impl<
const KEY_LEN: usize,
const HASH_LEN: usize,
Static: KeyedHash<KEY_LEN, HASH_LEN, Error = anyhow::Error>,
> KeyedHashInstance<KEY_LEN, HASH_LEN> for InferKeyedHash<Static, KEY_LEN, HASH_LEN>
{
type Error = anyhow::Error;
fn keyed_hash(&self, key: &[u8; KEY_LEN], data: &[u8], out: &mut [u8; HASH_LEN]) -> Result<()> {
self.keyed_hash_internal(key, data, out)
}
}
// Helper traits /////////////////////////////////////////////
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Default
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
fn default() -> Self {
Self::new()
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Clone
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
fn clone(&self) -> Self {
*self
}
}
impl<Static, const KEY_LEN: usize, const OUT_LEN: usize> Copy
for InferKeyedHash<Static, KEY_LEN, OUT_LEN>
where
Static: KeyedHash<KEY_LEN, OUT_LEN, Error = anyhow::Error>,
{
}

View File

@@ -1,4 +0,0 @@
pub mod blake2b;
pub mod incorrect_hmac_blake2b;
mod infer_keyed_hash;
pub mod keyed_shake256;

View File

@@ -6,8 +6,8 @@ pub const HASH_LEN: usize = 32;
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum KeyedHash {
KeyedShake256(super::hash_functions::keyed_shake256::SHAKE256<KEY_LEN, HASH_LEN>),
IncorrectHmacBlake2b(super::hash_functions::incorrect_hmac_blake2b::Blake2b),
KeyedShake256(super::rust_crypto::keyed_shake256::SHAKE256<KEY_LEN, HASH_LEN>),
IncorrectHmacBlake2b(super::custom::incorrect_hmac_blake2b::IncorrectHmacBlake2b),
}
impl KeyedHash {

View File

@@ -0,0 +1,3 @@
//! Implementations backed by libcrux, a verified crypto library
pub mod chacha20poly1305_ietf;

View File

@@ -1,15 +1,10 @@
/// This module provides the following cryptographic schemes:
/// - [blake2b]: The blake2b hash function
/// - [chacha20poly1305_ietf]: The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305) (only used when the feature `experiment_libcrux` is disabled).
/// - [chacha20poly1305_ietf_libcrux]: The Chacha20Poly1305 AEAD as implemented in [libcrux](https://github.com/cryspen/libcrux) (only used when the feature `experiment_libcrux` is enabled).
/// - [incorrect_hmac_blake2b]: An (incorrect) hmac based on [blake2b].
/// - [xchacha20poly1305_ietf] The Chacha20Poly1305 AEAD as implemented in [RustCrypto](https://crates.io/crates/chacha20poly1305)
#[cfg(not(feature = "experiment_libcrux"))]
pub mod chacha20poly1305_ietf;
#[cfg(feature = "experiment_libcrux")]
pub mod chacha20poly1305_ietf_libcrux;
pub mod either_hash;
mod hash_functions;
pub mod xchacha20poly1305_ietf;
pub mod keyed_hash;
pub use hash_functions::{blake2b, incorrect_hmac_blake2b, keyed_shake256};
pub use custom::incorrect_hmac_blake2b;
pub use rust_crypto::{blake2b, keyed_shake256};
pub mod custom;
pub mod rust_crypto;
#[cfg(feature = "experiment_libcrux")]
pub mod libcrux;

View File

@@ -1,6 +1,5 @@
use crate::subtle::hash_functions::infer_keyed_hash::InferKeyedHash;
use anyhow::ensure;
use rosenpass_cipher_traits::keyed_hash::KeyedHash;
use rosenpass_cipher_traits::keyed_hash::{InferKeyedHash, KeyedHash};
use sha3::digest::{ExtendableOutput, Update, XofReader};
use sha3::Shake256;

View File

@@ -0,0 +1,7 @@
//! Implementations backed by RustCrypto
pub mod blake2b;
pub mod keyed_shake256;
pub mod chacha20poly1305_ietf;
pub mod xchacha20poly1305_ietf;