mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-26 12:52:27 -08:00
dev(ciphers): change HashDomain and related structures to use EitherShakeOrBlake. Docu pending
This commit is contained in:
@@ -5,16 +5,20 @@ use rosenpass_to::To;
|
||||
use crate::keyed_hash as hash;
|
||||
|
||||
pub use hash::KEY_LEN;
|
||||
use rosenpass_cipher_traits::KeyedHashInstance;
|
||||
use crate::subtle::either_hash::EitherShakeOrBlake;
|
||||
|
||||
///
|
||||
///```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_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();
|
||||
/// let mut hash_domain = HashDomain::zero(EitherShakeOrBlake::Left(SHAKE256Core));
|
||||
/// hash_domain = hash_domain.mix(PROTOCOL_IDENTIFIER.as_bytes())?;
|
||||
/// // upgrade to reusable hash domain
|
||||
/// let hash_domain_namespace: HashDomainNamespace = hash_domain.dup();
|
||||
@@ -39,36 +43,36 @@ pub use hash::KEY_LEN;
|
||||
/// The key must consist of [KEY_LEN] many bytes. If the key must remain secret,
|
||||
/// use [SecretHashDomain] instead.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct HashDomain([u8; KEY_LEN]);
|
||||
pub struct HashDomain([u8; KEY_LEN], EitherShakeOrBlake);
|
||||
/// A reusable hash domain for a namespace identified by the key.
|
||||
/// The key must consist of [KEY_LEN] many bytes. If the key must remain secret,
|
||||
/// use [SecretHashDomainNamespace] instead.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct HashDomainNamespace([u8; KEY_LEN]);
|
||||
pub struct HashDomainNamespace([u8; KEY_LEN], EitherShakeOrBlake);
|
||||
/// A use-once hash domain for a specified key that can be used directly
|
||||
/// by wrapping it in [Secret]. The key must consist of [KEY_LEN] many bytes.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SecretHashDomain(Secret<KEY_LEN>);
|
||||
pub struct SecretHashDomain(Secret<KEY_LEN>, EitherShakeOrBlake);
|
||||
/// A reusable secure hash domain for a namespace identified by the key and that keeps the key secure
|
||||
/// by wrapping it in [Secret]. The key must consist of [KEY_LEN] many bytes.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>);
|
||||
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>, EitherShakeOrBlake);
|
||||
|
||||
impl HashDomain {
|
||||
/// Creates a nw [HashDomain] initialized with a all-zeros key.
|
||||
pub fn zero() -> Self {
|
||||
Self([0u8; KEY_LEN])
|
||||
pub fn zero(choice: EitherShakeOrBlake) -> Self {
|
||||
Self([0u8; KEY_LEN], choice)
|
||||
}
|
||||
|
||||
/// Turns this [HashDomain] into a [HashDomainNamespace], keeping the key.
|
||||
pub fn dup(self) -> HashDomainNamespace {
|
||||
HashDomainNamespace(self.0)
|
||||
HashDomainNamespace(self.0, self.1)
|
||||
}
|
||||
|
||||
/// Turns this [HashDomain] into a [SecretHashDomain] by wrapping the key into a [Secret]
|
||||
/// and creating a new [SecretHashDomain] from it.
|
||||
pub fn turn_secret(self) -> SecretHashDomain {
|
||||
SecretHashDomain(Secret::from_slice(&self.0))
|
||||
SecretHashDomain(Secret::from_slice(&self.0), self.1)
|
||||
}
|
||||
|
||||
// TODO: Protocol! Use domain separation to ensure that
|
||||
@@ -77,14 +81,16 @@ impl HashDomain {
|
||||
/// as the `data` and uses the result as the key for the new [HashDomain].
|
||||
///
|
||||
pub fn mix(self, v: &[u8]) -> Result<Self> {
|
||||
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
||||
self.1.keyed_hash(&self.0, v, &mut new_key)?;
|
||||
Ok(Self(new_key, self.1))
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
||||
/// by calling [SecretHashDomain::invoke_primitive] with this
|
||||
/// [HashDomain]'s key as `k` and `v` as `d`.
|
||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||
SecretHashDomain::invoke_primitive(&self.0, v.secret(), self.1)
|
||||
}
|
||||
|
||||
/// Gets the key of this [HashDomain].
|
||||
@@ -98,9 +104,9 @@ impl HashDomainNamespace {
|
||||
/// it evaluates [hash::hash] with the key of this HashDomainNamespace key as the key and `v`
|
||||
/// as the `data` and uses the result as the key for the new [HashDomain].
|
||||
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
||||
Ok(HashDomain(
|
||||
hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?,
|
||||
))
|
||||
let mut new_key: [u8; KEY_LEN] = [0u8; KEY_LEN];
|
||||
self.1.keyed_hash(&self.0, v, &mut new_key)?;
|
||||
Ok(HashDomain(new_key, self.1.clone()))
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
||||
@@ -109,7 +115,7 @@ impl HashDomainNamespace {
|
||||
///
|
||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
||||
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||
SecretHashDomain::invoke_primitive(&self.0, v.secret(), self.1.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,27 +124,30 @@ impl SecretHashDomain {
|
||||
/// [hash::hash] with `k` as the `key` and `d` s the `data`, and using the result
|
||||
/// as the content for the new [SecretHashDomain].
|
||||
/// Both `k` and `d` have to be exactly [KEY_LEN] bytes in length.
|
||||
pub fn invoke_primitive(k: &[u8], d: &[u8]) -> Result<SecretHashDomain> {
|
||||
let mut r = SecretHashDomain(Secret::zero());
|
||||
/// TODO: docu
|
||||
pub fn invoke_primitive(k: &[u8], d: &[u8], hash_choice: EitherShakeOrBlake) -> Result<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())?;
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] that is initialized with an all zeros key.
|
||||
pub fn zero() -> Self {
|
||||
Self(Secret::zero())
|
||||
pub fn zero(hash_choice: EitherShakeOrBlake) -> Self {
|
||||
Self(Secret::zero(), hash_choice)
|
||||
}
|
||||
|
||||
/// Turns this [SecretHashDomain] into a [SecretHashDomainNamespace].
|
||||
pub fn dup(self) -> SecretHashDomainNamespace {
|
||||
SecretHashDomainNamespace(self.0)
|
||||
SecretHashDomainNamespace(self.0, self.1)
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] from a [Secret] `k`.
|
||||
///
|
||||
/// It requires that `k` consist of exactly [KEY_LEN] bytes.
|
||||
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
|
||||
Self(k)
|
||||
pub fn danger_from_secret(k: Secret<KEY_LEN>, hash_choice: EitherShakeOrBlake) -> Self {
|
||||
Self(k, hash_choice)
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`. Specifically,
|
||||
@@ -147,7 +156,7 @@ impl SecretHashDomain {
|
||||
///
|
||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
||||
pub fn mix(self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||
Self::invoke_primitive(self.0.secret(), v)
|
||||
Self::invoke_primitive(self.0.secret(), v, self.1)
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
||||
@@ -156,7 +165,7 @@ impl SecretHashDomain {
|
||||
///
|
||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||
Self::invoke_primitive(self.0.secret(), v.secret())
|
||||
Self::invoke_primitive(self.0.secret(), v.secret(), self.1)
|
||||
}
|
||||
|
||||
/// Get the secret key data from this [SecretHashDomain].
|
||||
@@ -180,7 +189,7 @@ impl SecretHashDomainNamespace {
|
||||
///
|
||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
||||
pub fn mix(&self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||
SecretHashDomain::invoke_primitive(self.0.secret(), v)
|
||||
SecretHashDomain::invoke_primitive(self.0.secret(), v, self.1.clone())
|
||||
}
|
||||
|
||||
/// Creates a new [SecretHashDomain] by mixing in a new key `v`
|
||||
@@ -189,7 +198,7 @@ impl SecretHashDomainNamespace {
|
||||
///
|
||||
/// It requires that `v` consists of exactly [KEY_LEN] many bytes.
|
||||
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret())
|
||||
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret(), self.1.clone())
|
||||
}
|
||||
|
||||
// TODO: This entire API is not very nice; we need this for biscuits, but
|
||||
@@ -199,4 +208,8 @@ impl SecretHashDomainNamespace {
|
||||
pub fn danger_into_secret(self) -> Secret<KEY_LEN> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn shake_or_blake(&self) -> &EitherShakeOrBlake {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type EitherShakeOrBlake = HashChoice<32, 32, anyhow::Error, SHAKE256Core<32, 32>, Blake2bCore>;
|
||||
pub type EitherShakeOrBlake = EitherHash<32, 32, anyhow::Error, SHAKE256Core<32, 32>, Blake2bCore>;
|
||||
|
||||
impl Clone for EitherShakeOrBlake {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::Left(l) => Self::Left(l.clone()),
|
||||
Self::Right(r) => Self::Right(r.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ impl<const KEY_LEN: usize, const HASH_LEN: usize> SHAKE256Core<KEY_LEN, HASH_LEN
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO use nferred hash somehow here
|
||||
/// TODO use inferred hash somehow here
|
||||
/// ```rust
|
||||
/// # use rosenpass_ciphers::subtle::keyed_shake256::{SHAKE256};
|
||||
/// use rosenpass_cipher_traits::KeyedHashInstance;
|
||||
|
||||
@@ -10,6 +10,6 @@ pub mod chacha20poly1305_ietf;
|
||||
pub mod chacha20poly1305_ietf_libcrux;
|
||||
pub mod xchacha20poly1305_ietf;
|
||||
mod hash_functions;
|
||||
pub mod hash_choice;
|
||||
pub mod either_hash;
|
||||
|
||||
pub use hash_functions::{blake2b, incorrect_hmac_blake2b, keyed_shake256};
|
||||
Reference in New Issue
Block a user