mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-05 20:40:02 -08:00
Reorganize the ciphers crate
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
3
ciphers/src/subtle/custom/mod.rs
Normal file
3
ciphers/src/subtle/custom/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
//! Own implementations of custom algorithms
|
||||
|
||||
pub mod incorrect_hmac_blake2b;
|
||||
@@ -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>,
|
||||
{
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod blake2b;
|
||||
pub mod incorrect_hmac_blake2b;
|
||||
mod infer_keyed_hash;
|
||||
pub mod keyed_shake256;
|
||||
@@ -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 {
|
||||
3
ciphers/src/subtle/libcrux/mod.rs
Normal file
3
ciphers/src/subtle/libcrux/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
//! Implementations backed by libcrux, a verified crypto library
|
||||
|
||||
pub mod chacha20poly1305_ietf;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
7
ciphers/src/subtle/rust_crypto/mod.rs
Normal file
7
ciphers/src/subtle/rust_crypto/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
//! Implementations backed by RustCrypto
|
||||
|
||||
pub mod blake2b;
|
||||
pub mod keyed_shake256;
|
||||
|
||||
pub mod chacha20poly1305_ietf;
|
||||
pub mod xchacha20poly1305_ietf;
|
||||
Reference in New Issue
Block a user