Skip to content

Commit

Permalink
init hash sign/verify
Browse files Browse the repository at this point in the history
  • Loading branch information
eschorn1 committed Sep 26, 2024
1 parent 905204f commit 1c8a8d0
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 76 deletions.
8 changes: 4 additions & 4 deletions rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ tab_spaces = 4
newline_style = "Auto"
indent_style = "Block"
#use_small_heuristics = "Default"
fn_call_width = 100
attr_fn_like_width = 100
fn_call_width = 90
attr_fn_like_width = 90
struct_lit_width = 60
struct_variant_width = 60
array_width = 60
chain_width = 100
chain_width = 90
single_line_if_else_max_width = 50
single_line_let_else_max_width = 50
wrap_comments = false
Expand Down Expand Up @@ -49,7 +49,7 @@ match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
fn_params_layout = "Compressed"
fn_args_layout = "Compressed"
#fn_args_layout = "Compressed"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
Expand Down
51 changes: 50 additions & 1 deletion src/hashing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::conversion::{bit_unpack, coeff_from_half_byte, coeff_from_three_bytes};
use crate::helpers::{bit_length, is_in_range};
use crate::types::{R, R0, T, T0};
use crate::types::{Ph, R, R0, T, T0};
use sha3::digest::{ExtendableOutput, Update, XofReader};
use sha3::{Shake128, Shake256};

Expand Down Expand Up @@ -339,3 +339,52 @@ pub(crate) fn expand_mask<const L: usize>(gamma1: i32, rho: &[u8; 64], mu: u16)
// 7: return s
s
}


pub(crate) fn hash_message(message: &[u8], ph: &Ph, phm: &mut [u8; 64]) -> ([u8; 11], usize) {
match ph {
Ph::SHA256 => {
use sha2::{Digest, Sha256};
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
],
{
let mut hasher = Sha256::new();
Digest::update(&mut hasher, message); //hasher.update(message);
phm[0..32].copy_from_slice(&hasher.finalize());
32
},
)
}
Ph::SHA512 => {
use sha2::{Digest, Sha512};
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
],
{
let mut hasher = Sha512::new();
Digest::update(&mut hasher, message); //hasher.update(message);
phm.copy_from_slice(&hasher.finalize());
64
},
)
}
Ph::SHAKE128 => {
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0B,
],
{
use sha3::digest::{ExtendableOutput, Update, XofReader}; // some collide with sha2
let mut hasher = Shake128::default();
hasher.update(message);
let mut reader = hasher.finalize_xof();
reader.read(phm);
64
},
)
}
}
}
127 changes: 63 additions & 64 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ const D: u32 = 13; // See table 1 page 13 second row
macro_rules! functionality {
() => {
use crate::encodings::{pk_decode, sk_decode};
use crate::hashing::hash_message;
use crate::helpers::{bit_length, ensure};
use crate::ml_dsa;
use crate::traits::{KeyGen, SerDes, Signer, Verifier};
use crate::types::Ph;
use rand_core::CryptoRngCore;
use sha2::{Digest, Sha256};
use zeroize::{Zeroize, ZeroizeOnDrop};

const LAMBDA_DIV4: usize = LAMBDA / 4;
Expand Down Expand Up @@ -265,34 +265,14 @@ macro_rules! functionality {

// Algorithm 4 in Signer trait.
fn try_hash_sign_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: Ph,
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph,
) -> Result<Self::Signature, &'static str> {
ensure!(ctx.len() < 256, "HashML-DSA.Sign: ctx too long");
let esk = ml_dsa::sign_start::<CTEST, K, L, SK_LEN>(ETA, &self.0)?;
let (oid, phm) = match ph {
Ph::SHA256 => {
let mut hasher = Sha256::new();
hasher.update(message);
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
],
hasher.finalize(),
)
}
_ => {
let mut hasher = Sha256::new();
hasher.update(message);
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
],
hasher.finalize(),
)
}
};
let mut phm = [0u8; 64]; // hashers don't all play well with each other
let (oid, phm_len) = hash_message(message, ph, &mut phm);
let sig = ml_dsa::sign_finish::<CTEST, K, L, LAMBDA_DIV4, SIG_LEN, SK_LEN, W1_LEN>(
rng, BETA, GAMMA1, GAMMA2, OMEGA, TAU, &esk, message, ctx, &oid, &phm, false,
rng, BETA, GAMMA1, GAMMA2, OMEGA, TAU, &esk, message, ctx, &oid, &phm[0..phm_len], false,
)?;
Ok(sig)
}
Expand Down Expand Up @@ -330,22 +310,13 @@ macro_rules! functionality {
// start+finish enables the ability of signing with a pre-computeed expanded private
// key for performance.
fn try_hash_sign_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], _ph: Ph,
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph,
) -> Result<Self::Signature, &'static str> {
ensure!(ctx.len() < 256, "HashML-DSA.Sign: ctx too long");
let mut phm = [0u8; 64]; // hashers don't all play well with each other
let (oid, phm_len) = hash_message(message, ph, &mut phm);
let sig = ml_dsa::sign_finish::<CTEST, K, L, LAMBDA_DIV4, SIG_LEN, SK_LEN, W1_LEN>(
rng,
BETA,
GAMMA1,
GAMMA2,
OMEGA,
TAU,
&self,
message,
ctx,
&[],
&[],
false,
rng, BETA, GAMMA1, GAMMA2, OMEGA, TAU, &self, message, ctx, &oid, &phm[0..phm_len], false,
)?;
Ok(sig)
}
Expand Down Expand Up @@ -385,36 +356,16 @@ macro_rules! functionality {
}

// Algorithm 5 in Verifier trait.
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: Ph) -> bool {
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: &Ph) -> bool {
if ctx.len() > 255 {
return false;
};
let epk = ml_dsa::verify_start(&self.0);
if epk.is_err() {
return false;
};
let (oid, phm) = match ph {
Ph::SHA256 => {
let mut hasher = Sha256::new();
hasher.update(message);
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
],
hasher.finalize(),
)
}
_ => {
let mut hasher = Sha256::new();
hasher.update(message);
(
[
0x06u8, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
],
hasher.finalize(),
)
}
};
let mut phm = [0u8; 64]; // hashers don't all play well with each other
let (oid, phm_len) = hash_message(message, ph, &mut phm);
let res = ml_dsa::verify_finish::<K, L, LAMBDA_DIV4, PK_LEN, SIG_LEN, W1_LEN>(
BETA,
GAMMA1,
Expand All @@ -426,7 +377,7 @@ macro_rules! functionality {
&sig,
ctx,
&oid,
&phm,
&phm[0..phm_len],
false,
);
if res.is_err() {
Expand Down Expand Up @@ -467,8 +418,30 @@ macro_rules! functionality {
// Algorithm 5 in Verifier trait. Rather than an external+internal split, this split of
// start+finish enables the ability of verifing with a pre-computeed expanded public
// key for performance.
fn hash_verify(&self, _message: &[u8], _sig: &Self::Signature, _ctx: &[u8], _ph: Ph) -> bool {
unimplemented!()
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: &Ph) -> bool {
if ctx.len() > 255 {
return false;
};
let mut phm = [0u8; 64]; // hashers don't all play well with each other
let (oid, phm_len) = hash_message(message, ph, &mut phm);
let res = ml_dsa::verify_finish::<K, L, LAMBDA_DIV4, PK_LEN, SIG_LEN, W1_LEN>(
BETA,
GAMMA1,
GAMMA2,
OMEGA,
TAU,
&self,
&message,
&sig,
ctx,
&oid,
&phm[0..phm_len],
false,
);
if res.is_err() {
return false;
};
res.unwrap()
}
}

Expand Down Expand Up @@ -498,6 +471,32 @@ macro_rules! functionality {
fn into_bytes(self) -> Self::ByteArray { self.0 }
}


#[cfg(test)]
mod tests {
use super::*;
use crate::types::Ph;
use rand_chacha::rand_core::SeedableRng;

#[test]
fn smoke_test() {
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
let message = [0u8, 1, 2, 3, 4, 5, 6, 7];

for _i in 0..100 {
let (pk, sk) = try_keygen_with_rng(&mut rng).unwrap();
let sig = sk.try_sign_with_rng(&mut rng, &message, &[]).unwrap();
let v = pk.verify(&message, &sig, &[]);
assert!(v);
for ph in [Ph::SHA256, Ph::SHA512, Ph::SHAKE128] {
let sig = sk.try_hash_sign_with_rng(&mut rng, &message, &[], &ph).unwrap();
let v = pk.hash_verify(&message, &sig, &[], &ph);
assert!(v);
}
}
}
}

// ----- SUPPORT FOR DUDECT CONSTANT TIME MEASUREMENTS ---

/// This function supports the dudect constant-time measurement framework, and
Expand Down
11 changes: 6 additions & 5 deletions src/ml_dsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,16 @@ pub(crate) fn sign_finish<
} = esk;

// 6: µ ← H(tr || M', 512) ▷ Compute message representative µ
// We may have arrived via `HashML-DSA.Sign()`
// We may have arrived from 3 different paths
let mut h6 = if nist {
// 1. NIST vectors are being applied to "internal" functions
h_xof(&[tr, message])
} else if oid.is_empty() {
// From ML-DSA.Sing(): 𝑀′ ← BytesToBits(IntegerToBytes(0,1) ∥ IntegerToBytes(|𝑐𝑡𝑥|,1) ∥ 𝑐𝑡𝑥) ∥ 𝑀
h_xof(&[tr, &[0u8], &[ctx.len().to_le_bytes()[0]], ctx, message]) // TODO: OMFG! <---- CAVP VECTORS WHA!!!
// 2. From ML-DSA.Sign(): 𝑀′ ← BytesToBits(IntegerToBytes(0,1) ∥ IntegerToBytes(|𝑐𝑡𝑥|,1) ∥ 𝑐𝑡𝑥) ∥ 𝑀
h_xof(&[tr, &[0u8], &[ctx.len().to_le_bytes()[0]], ctx, message])
} else {
// From HashML-DSA.Sign(): 𝑀′ ← BytesToBits(IntegerToBytes(1,1) ∥ IntegerToBytes(|𝑐𝑡𝑥|,1) ∥ 𝑐𝑡𝑥 ∥ OID ∥ PH𝑀 )
h_xof(&[tr, &[0x01u8], &[oid.len().to_le_bytes()[0]], ctx, oid, phm])
// 3. From HashML-DSA.Sign(): 𝑀′ ← BytesToBits(IntegerToBytes(1,1) ∥ IntegerToBytes(|𝑐𝑡𝑥|,1) ∥ 𝑐𝑡𝑥 ∥ OID ∥ PH𝑀 )
h_xof(&[tr, &[1u8], &[oid.len().to_le_bytes()[0]], ctx, oid, phm])
};
let mut mu = [0u8; 64];
h6.read(&mut mu);
Expand Down
4 changes: 2 additions & 2 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub trait Signer {
/// # Errors
/// Will return an error on rng failure
fn try_hash_sign_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: Ph,
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph,
) -> Result<Self::Signature, &'static str>;
}

Expand Down Expand Up @@ -205,7 +205,7 @@ pub trait Verifier {
fn verify(&self, message: &[u8], signature: &Self::Signature, ctx: &[u8]) -> bool;

/// TKTK placeholder
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: Ph) -> bool;
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: &Ph) -> bool;
}


Expand Down

0 comments on commit 1c8a8d0

Please sign in to comment.