v0.4.0 RC1

This commit is contained in:
eschorn1 2024-10-04 11:02:10 -05:00
parent 5f8a96c02b
commit e77284a10d
7 changed files with 53 additions and 21 deletions

View file

@ -12,8 +12,8 @@ dudect-bencher = "0.6"
rand_core = { version = "0.6.4", default-features = false }
[profile.bench]
debug = true
[profile.release]
debug = false
debug-assertions = false
incremental = false
lto = true

View file

@ -11,21 +11,22 @@ Intel® Core™ i7-7700K CPU @ 4.20GHz × 8 Circa 2017 Rust 1.81
$ cd dudect # this directory
$ cargo clean
$ time RUSTFLAGS="-C target-cpu=native" cargo run --release
$ time RUSTFLAGS="-C target-cpu=native" cargo run --release # A ~11 hour run
...
Compiling fips205 v0.4.0 (/home/eric/work/fips205)
Compiling fips205-dudect v0.4.0 (/home/eric/work/fips205/dudect)
Finished `release` profile [optimized] target(s) in 7.36s
Finished `release` profile [optimized] target(s) in 12.04s
Running `target/release/fips205-dudect`
running 1 bench
bench keygen_and_sign seeded with 0x89b5d1d7e0207f97
bench keygen_and_sign ... : n == +0.001M, max t = -1.03786, max tau = -0.03383, (5/tau)^2 = 21840
bench keygen_and_sign seeded with 0x54522172d8fff6c0
bench keygen_and_sign ... : n == +0.007M, max t = +3.04638, max tau = +0.03693, (5/tau)^2 = 18331
dudect benches complete
real 63m43.206s
user 64m12.095s
sys 0m2.511s
real 660m35.132s
user 660m47.614s
sys 0m2.662s
~~~

View file

@ -30,8 +30,8 @@ pub struct AlignedBytes<const BYTE_LEN: usize>(pub(crate) [u8; BYTE_LEN]);
fn keygen_and_sign(runner: &mut CtRunner, mut _rng: &mut BenchRng) {
const ITERATIONS_OUTER: usize = 1_000;
const ITERATIONS_INNER: usize = 4;
const ITERATIONS_OUTER: usize = 20_000;
const ITERATIONS_INNER: usize = 2;
let message = AlignedBytes::<8>([0u8, 1, 2, 3, 4, 5, 6, 7]);
let z_left = AlignedBytes::<16>([0xAAu8; 16]);

View file

@ -157,5 +157,5 @@ pub(crate) fn ht_verify<
// 15: else
// 16: return false
// 17: end if
node == *pk_root // TODO: CT equal (double-check: is this in signing path??)
node == *pk_root // Public data, thus no CT eq required
}

View file

@ -48,7 +48,7 @@
// TODO: Roadmap
// 1. Additional (external) top-level test vectors, particularly for hash variants (!!)
// 2. Implement fuzz harness, embedded target, code provenance functionality
// 2. Implement fuzz harness, embedded target, revise WASM test
// 3. Experiment with struct alignment for performance uplift? (and fixed size 'slices')
@ -206,6 +206,7 @@ macro_rules! functionality {
impl Signer for PrivateKey {
type Signature = [u8; SIG_LEN];
type PublicKey = PublicKey;
// Documented in traits.rs
fn try_sign_with_rng(
@ -244,6 +245,11 @@ macro_rules! functionality {
sig.map(|s| s.serialize())
}
// Documented in traits.rs
fn get_public_key(&self) -> Self::PublicKey {
PublicKey(SlhPublicKey{pk_seed: self.0.pk_seed, pk_root: self.0.pk_root})
}
// Documented in traits.rs
fn _test_only_raw_sign(
&self, rng: &mut impl CryptoRngCore, m: &[u8], hedged: bool,
@ -338,8 +344,6 @@ macro_rules! functionality {
// Documented in traits.rs
fn try_from_bytes(bytes: &Self::ByteArray) -> Result<Self, &'static str> {
// Result: opportunity for validation
//let mut pk = SlhPublicKey::default();
let mut pk = SlhPublicKey { pk_seed: [0u8; N], pk_root: [0u8; N] };
pk.pk_seed.copy_from_slice(&bytes[..(PK_LEN / 2)]);
pk.pk_root.copy_from_slice(&bytes[(PK_LEN / 2)..]);
@ -373,6 +377,8 @@ macro_rules! functionality {
sk.sk_prf.copy_from_slice(&bytes[(SK_LEN / 4)..(SK_LEN / 2)]);
sk.pk_seed.copy_from_slice(&bytes[(SK_LEN / 2)..(3 * SK_LEN / 4)]);
sk.pk_root.copy_from_slice(&bytes[(3 * SK_LEN / 4)..]);
let (sk_test, _) = crate::slh::slh_keygen_internal::<D, H, HP, K, LEN, M, N>(&HASHERS, sk.sk_seed, sk.sk_prf, sk.pk_seed);
if sk_test.pk_root != sk.pk_root { return Err("Corrupted key")}
Ok(PrivateKey(sk))
}
}

View file

@ -237,7 +237,6 @@ pub(crate) fn slh_sign_internal<
///
/// Input: Message `M`, signature `SIG`, context string `ctx`, public key `PK = (PK.seed, PK.root)`. <br>
/// Output: Boolean.
#[allow(clippy::cast_possible_truncation)] // TODO: temporary
#[allow(clippy::similar_names)]
pub(crate) fn slh_verify<
const A: usize,
@ -273,7 +272,6 @@ pub(crate) fn slh_verify<
///
/// Input: Message `M`, signature `SIG`, public key `PK = (PK.seed, PK.root)`. <br>
/// Output: Boolean.
#[allow(clippy::cast_possible_truncation)] // TODO: temporary
#[allow(clippy::similar_names)]
pub(crate) fn slh_verify_internal<
const A: usize,
@ -293,7 +291,7 @@ pub(crate) fn slh_verify_internal<
// 1: if |SIG| != (1 + k(1 + a) + h + d · len) · n then
// 2: return false
// 3: end if
// The above size is performed in the wrapper/adapter deserialize function
// The above size check is performed in the wrapper/adapter deserialize function
// 4: ADRS ← toByte(0, 32)
let mut adrs = Adrs::default();
@ -337,7 +335,8 @@ pub(crate) fn slh_verify_internal<
adrs.set_type_and_clear(FORS_TREE);
// 16: ADRS.setKeyPairAddress(idx_leaf)
adrs.set_key_pair_address(idx_leaf as u32);
let Ok(idx_leaf_u32) = u32::try_from(idx_leaf) else { return false }; // should never fail
adrs.set_key_pair_address(idx_leaf_u32);
// 17: PK_FORS ← fors_pkFromSig(SIG_FORS, md, PK.seed, ADRS)
let pk_fors =
@ -350,7 +349,7 @@ pub(crate) fn slh_verify_internal<
sig_ht,
&pk.pk_seed,
idx_tree,
idx_leaf as u32,
idx_leaf_u32,
&pk.pk_root,
)
}

View file

@ -106,7 +106,8 @@ pub trait KeyGen {
pub trait Signer {
/// The signature is specific to the chosen security parameter set, e.g., `slh_dsa_shake_128s`, `slh_dsa_sha2_128s` etc
type Signature;
/// The public key that corresponds to the private/secret key
type PublicKey;
/// Attempt to sign the given message, returning a digital signature on success, or an error if
/// something went wrong. This function utilizes the **OS default** random number generator.
@ -296,6 +297,31 @@ pub trait Signer {
) -> Result<Self::Signature, &'static str>;
/// Retrieves the public key associated with this private/secret key
/// # Examples
/// ```rust
/// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets.
/// use fips205::traits::{SerDes, Signer, Verifier};
/// # use std::error::Error;
/// # use rand_core::OsRng;
/// # use fips205::Ph;
/// # fn main() -> Result<(), Box<dyn Error>> {
///
/// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7];
/// let mut rng = OsRng;
///
///
/// // Generate both public and secret keys, but only hang onto the secret key.
/// let (_, sk) = slh_dsa_shake_128s::try_keygen()?;
///
/// // The public key can be derived from the secret key
/// let pk = sk.get_public_key();
/// # Ok(())
/// # }
/// ```
fn get_public_key(&self) -> Self::PublicKey;
/// As of October 4 2024, the available NIST test vectors are applied to the **internal** functions
/// rather than the external API. This function should not be used outside of this scenario.
/// # Errors