dudect, workflows

This commit is contained in:
eschorn1 2024-10-03 12:24:28 -05:00
parent e68fb16221
commit 59314dc043
11 changed files with 256 additions and 130 deletions

48
.github/workflows/provenance.yaml vendored Normal file
View file

@ -0,0 +1,48 @@
name: provenance
on:
push:
tags:
- '*'
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
attestations: write
strategy:
matrix:
rust:
- 1.72
target:
- thumbv7em-none-eabi
- x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features "slh_dsa_sha2_128s slh_dsa_shake_128s slh_dsa_sha2_128f slh_dsa_shake_128f slh_dsa_sha2_192s slh_dsa_shake_192s slh_dsa_sha2_192f slh_dsa_shake_192f slh_dsa_sha2_256s slh_dsa_shake_256s slh_dsa_sha2_256f slh_dsa_shake_256f"
- name: Attest
uses: actions/attest-build-provenance@v1
with:
subject-path: '${{ github.workspace }}/target/*/release/libfips205.rlib'
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target }}--libfips204.rlib
path: '${{ github.workspace }}/target/*/release/libfips205.rlib'
retention-days: 60
- name: Checkout actions-oidc-debugger
uses: actions/checkout@v4
with:
repository: github/actions-oidc-debugger
ref: main
path: ./.github/actions/actions-oidc-debugger
- name: Debug OIDC Claims
uses: ./.github/actions/actions-oidc-debugger
with:
audience: '${{ github.server_url }}/${{ github.repository_owner }}'

View file

@ -1,6 +1,7 @@
name: test
on: [ push ]
on: [ push, pull_request ]
env:
@ -11,18 +12,12 @@ env:
jobs:
cargo-deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: EmbarkStudios/cargo-deny-action@v1
build:
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- 1.72.0 # MSRV is 1.70, but GA flaky
- 1.72 # MSRV 1.70 GA flaky
- stable
target:
- thumbv7em-none-eabi
@ -41,33 +36,58 @@ jobs:
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features "slh_dsa_sha2_128s slh_dsa_shake_128s slh_dsa_sha2_128f slh_dsa_shake_128f slh_dsa_sha2_192s slh_dsa_shake_192s slh_dsa_sha2_192f slh_dsa_shake_192f slh_dsa_sha2_256s slh_dsa_shake_256s slh_dsa_sha2_256f slh_dsa_shake_256f"
test:
cargo_audit:
runs-on: ubuntu-latest
strategy:
matrix:
include:
# 32-bit Linux
- target: i686-unknown-linux-gnu
rust: 1.72.0 # MSRV is 1.70, but GA flaky
deps: sudo apt update && sudo apt install gcc-multilib
- target: i686-unknown-linux-gnu
rust: stable
deps: sudo apt update && sudo apt install gcc-multilib
# 64-bit Linux
- target: x86_64-unknown-linux-gnu
rust: 1.72.0 # MSRV is 1.70, but GA flaky
- target: x86_64-unknown-linux-gnu
rust: stable
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
- uses: rustsec/audit-check@v1.4.1
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- run: ${{ matrix.deps }}
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo test --release --target ${{ matrix.target }}
token: ${{ secrets.GITHUB_TOKEN }}
cargo-deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: EmbarkStudios/cargo-deny-action@v1
cargo_outdated:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install cargo outdated
run: cargo install --locked cargo-outdated
- name: Run cargo outdated
run: cargo outdated -R
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Clippy
run: cargo clippy --all-targets --all-features
coverage:
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate code coverage
run: cargo llvm-cov --all-features --workspace
# No codecov account, so stop here for now
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v3
# with:
# files: lcov.info
# fail_ci_if_error: true
cross:
@ -76,17 +96,17 @@ jobs:
include:
# ARM32
- target: armv7-unknown-linux-gnueabihf
rust: 1.72.0 # MSRV is 1.70, but GA flaky
rust: 1.72 # MSRV 1.70 GA flaky
- target: armv7-unknown-linux-gnueabihf
rust: stable
# ARM64
- target: aarch64-unknown-linux-gnu
rust: 1.72.0 # MSRV is 1.70, but GA flaky
rust: 1.72 # MSRV 1.70 GA flaky
- target: aarch64-unknown-linux-gnu
rust: stable
# PPC32
- target: powerpc-unknown-linux-gnu
rust: 1.72.0 # MSRV (cross)
rust: 1.72 # MSRV 1.70 GA flaky
- target: powerpc-unknown-linux-gnu
rust: stable
runs-on: ubuntu-latest
@ -98,7 +118,7 @@ jobs:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- uses: RustCrypto/actions/cross-install@master
- run: cross test --release --target ${{ matrix.target }} --all-features
- run: cross test --target ${{ matrix.target }} --all-features
doc:
@ -111,9 +131,36 @@ jobs:
toolchain: stable
- run: cargo doc --all-features
clippy:
test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
# 32-bit Linux
- target: i686-unknown-linux-gnu
rust: 1.72.0 # MSRV 1.70 GA flaky
deps: sudo apt update && sudo apt install gcc-multilib
- target: i686-unknown-linux-gnu
rust: stable
deps: sudo apt update && sudo apt install gcc-multilib
# 64-bit Linux
- target: x86_64-unknown-linux-gnu
rust: 1.72.0 # MSRV 1.70 GA flaky
- target: x86_64-unknown-linux-gnu
rust: stable
steps:
- uses: actions/checkout@v3
- name: Run Clippy
run: cargo clippy --all-targets --all-features
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- run: ${{ matrix.deps }}
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo test --target ${{ matrix.target }}

View file

@ -10,7 +10,7 @@ use fips205::{
#[allow(clippy::redundant_closure)]
pub fn criterion_benchmark(c: &mut Criterion) {
let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
let randomize = false;
let hedged = false;
let (pk_sha2_128s, sk_sha2_128s) = slh_dsa_sha2_128s::KG::try_keygen().unwrap();
let (pk_sha2_128f, sk_sha2_128f) = slh_dsa_sha2_128f::KG::try_keygen().unwrap();
@ -26,40 +26,40 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let (pk_shake_256f, sk_shake_256f) = slh_dsa_shake_256f::KG::try_keygen().unwrap();
let sig_sha2_128s = sk_sha2_128s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_sha2_128f = sk_sha2_128f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_sha2_192s = sk_sha2_192s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_sha2_192f = sk_sha2_192f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_sha2_256s = sk_sha2_256s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_sha2_256f = sk_sha2_256f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_128s = sk_shake_128s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_128f = sk_shake_128f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_192s = sk_shake_192s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_192f = sk_shake_192f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_256s = sk_shake_256s
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
let sig_shake_256f = sk_shake_256f
.try_sign(&message, b"context", randomize)
.try_sign(&message, b"context", hedged)
.unwrap();
c.bench_function("sha2_128f keygen", |b| b.iter(|| slh_dsa_sha2_128f::KG::try_keygen()));
@ -76,40 +76,40 @@ pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("shake_256s keygen", |b| b.iter(|| slh_dsa_shake_256s::KG::try_keygen()));
//
c.bench_function("sha2_128f sign ", |b| {
b.iter(|| sk_sha2_128f.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_128f.try_sign(&message, b"context", hedged))
});
c.bench_function("sha2_192f sign ", |b| {
b.iter(|| sk_sha2_192f.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_192f.try_sign(&message, b"context", hedged))
});
c.bench_function("sha2_256f sign ", |b| {
b.iter(|| sk_sha2_256f.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_256f.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_128f sign ", |b| {
b.iter(|| sk_shake_128f.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_128f.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_192f sign ", |b| {
b.iter(|| sk_shake_192f.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_192f.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_256f sign ", |b| {
b.iter(|| sk_shake_256f.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_256f.try_sign(&message, b"context", hedged))
});
c.bench_function("sha2_128s sign ", |b| {
b.iter(|| sk_sha2_128s.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_128s.try_sign(&message, b"context", hedged))
});
c.bench_function("sha2_192s sign ", |b| {
b.iter(|| sk_sha2_192s.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_192s.try_sign(&message, b"context", hedged))
});
c.bench_function("sha2_256s sign ", |b| {
b.iter(|| sk_sha2_256s.try_sign(&message, b"context", randomize))
b.iter(|| sk_sha2_256s.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_128s sign ", |b| {
b.iter(|| sk_shake_128s.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_128s.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_192s sign ", |b| {
b.iter(|| sk_shake_192s.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_192s.try_sign(&message, b"context", hedged))
});
c.bench_function("shake_256s sign ", |b| {
b.iter(|| sk_shake_256s.try_sign(&message, b"context", randomize))
b.iter(|| sk_shake_256s.try_sign(&message, b"context", hedged))
});
//
c.bench_function("sha2_128f verify", |b| {

View file

@ -1,16 +1,15 @@
[package]
name = "fips205-dudect"
version = "0.1.0"
version = "0.4.0"
authors = ["Eric Schorn <eschorn@integritychain.com>"]
publish = false
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
fips205 = { path = ".." }
dudect-bencher = "0.6"
rand_core = { version = "0.6.4", default-features = false }
[profile.bench]

View file

@ -1,25 +1,31 @@
This needs work...
An example constant-time workbench. It can be sensitive to config/defaults, so is
not entirely definitive. A work in progress.
See https://docs.rs/dudect-bencher/latest/dudect_bencher/
Dudect can indicate something terribly wrong, but not too much else.
See <https://docs.rs/dudect-bencher/latest/dudect_bencher/>
> t-values greater than 5 are generally considered a good indication that the function is not constant time. t-values less than 5 does not necessarily imply that the function is constant-time, since there may be other input distributions under which the function behaves significantly differently.
~~~
$ cargo run --release -- --continuous sign
Finished release [optimized] target(s) in 7.34s
Running `target/release/fips205-dudect --continuous sign`
running 1 benchmark continuously
bench sign seeded with 0x2e4df99cf3c2b95b
bench sign ... : n == +0.000M, max t = +1.89036, max tau = +0.56996, (5/tau)^2 = 76
bench sign ... : n == +0.000M, max t = +3.41458, max tau = +0.72799, (5/tau)^2 = 47
bench sign ... : n == +0.000M, max t = +3.15437, max tau = +0.56654, (5/tau)^2 = 77
bench sign ... : n == +0.000M, max t = +3.68377, max tau = +0.57531, (5/tau)^2 = 75
bench sign ... : n == +0.000M, max t = +4.21598, max tau = +0.48046, (5/tau)^2 = 108
bench sign ... : n == +0.000M, max t = +3.89742, max tau = +0.39987, (5/tau)^2 = 156
bench sign ... : n == +0.000M, max t = +4.01349, max tau = +0.37924, (5/tau)^2 = 173
bench sign ... : n == +0.000M, max t = +3.47164, max tau = +0.30566, (5/tau)^2 = 267
bench sign ... : n == +0.000M, max t = +3.55797, max tau = +0.29547, (5/tau)^2 = 286
bench sign ... : n == +0.000M, max t = +2.97639, max tau = +0.23604, (5/tau)^2 = 448
~~~
October 3, 2024
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
...
Compiling fips205-dudect v0.4.0 (/home/eric/work/fips205/dudect)
Finished `release` profile [optimized] target(s) in 7.36s
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
dudect benches complete
real 63m43.206s
user 64m12.095s
sys 0m2.511s
~~~

View file

@ -1,36 +1,62 @@
use dudect_bencher::{ctbench_main, BenchRng, Class, CtRunner};
use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets.
use fips205::slh_dsa_sha2_128s; // Could use any of the twelve security parameter sets.
use fips205::traits::Signer;
use rand_core::{CryptoRng, RngCore};
fn sign(runner: &mut CtRunner, mut _rng: &mut BenchRng) {
const ITERATIONS_OUTER: usize = 10;
const ITERATIONS_INNER: usize = 1;
let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
// Simplistic RNG to regurgitate set value
#[derive(Clone)]
#[repr(align(8))]
struct TestRng([u8; 16]);
let (_pk1, sk1) = slh_dsa_shake_128s::try_keygen().unwrap(); // Generate both public and secret keys
let (_pk2, sk2) = slh_dsa_shake_128s::try_keygen().unwrap(); // Generate both public and secret keys
impl RngCore for TestRng {
fn next_u32(&mut self) -> u32 { unimplemented!() }
let mut inputs: Vec<slh_dsa_shake_128s::PrivateKey> = Vec::new();
let mut classes = Vec::new();
fn next_u64(&mut self) -> u64 { unimplemented!() }
for _ in 0..ITERATIONS_OUTER {
inputs.push(sk1.clone());
classes.push(Class::Left);
fn fill_bytes(&mut self, _out: &mut [u8]) { unimplemented!() }
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
out.copy_from_slice(&self.0);
Ok(())
}
}
for _ in 0..ITERATIONS_OUTER {
inputs.push(sk2.clone());
classes.push(Class::Right);
impl CryptoRng for TestRng {}
#[repr(align(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;
let message = AlignedBytes::<8>([0u8, 1, 2, 3, 4, 5, 6, 7]);
let z_left = AlignedBytes::<16>([0xAAu8; 16]);
let z_right = AlignedBytes::<16>([0x55u8; 16]);
let mut classes = vec![Class::Right; ITERATIONS_OUTER];
let mut z_refs = vec![&z_right.0; ITERATIONS_OUTER];
// Interleave left and right
for i in (0..ITERATIONS_OUTER).step_by(2) {
classes[i] = Class::Left;
z_refs[i] = &z_left.0;
}
for (class, input) in classes.into_iter().zip(inputs.into_iter()) {
for (class, z) in classes.into_iter().zip(z_refs.into_iter()) {
runner.run_one(class, || {
let mut rng = TestRng(*z); // regurgitates z as rng
for _ in 0..ITERATIONS_INNER {
let _ = input.try_sign(&message, true);
let (_pk, sk) = slh_dsa_sha2_128s::try_keygen_with_rng(&mut rng).unwrap(); // Generate both public and secret keys
let _ = sk.try_sign_with_rng(&mut rng, &message.0, &[0], true);
//let _ = ml_dsa_44::dudect_keygen_sign_with_rng(&mut rng, &message.0);
}
})
}
}
ctbench_main!(sign);
ctbench_main!(keygen_and_sign);

View file

@ -183,14 +183,14 @@ macro_rules! functionality {
type Signature = [u8; SIG_LEN];
fn try_sign_with_rng(
&self, rng: &mut impl CryptoRngCore, m: &[u8], ctx: &[u8], randomize: bool,
&self, rng: &mut impl CryptoRngCore, m: &[u8], ctx: &[u8], hedged: bool,
) -> Result<[u8; SIG_LEN], &'static str> {
if ctx.len() > 255 {
return Err("ctx must be less than 256 bytes");
};
let mp: &[&[u8]] = &[&[0u8], &[ctx.len().to_le_bytes()[0]], ctx, m];
let sig = crate::slh::slh_sign_with_rng::<A, D, H, HP, K, LEN, M, N>(
rng, &HASHERS, &mp, &self.0, randomize,
rng, &HASHERS, &mp, &self.0, hedged,
);
sig.map(|s| s.serialize())
}
@ -198,7 +198,7 @@ macro_rules! functionality {
/// # Errors
fn try_sign_hash_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph,
randomize: bool,
hedged: bool,
) -> Result<Self::Signature, &'static str> {
if ctx.len() > 255 {
return Err("ctx must be less than 256 bytes");
@ -213,7 +213,7 @@ macro_rules! functionality {
&phm[0..phm_len],
];
let sig = crate::slh::slh_sign_with_rng::<A, D, H, HP, K, LEN, M, N>(
rng, &HASHERS, &mp, &self.0, randomize, // BAD
rng, &HASHERS, &mp, &self.0, hedged, // BAD
);
sig.map(|s| s.serialize())
}
@ -222,12 +222,12 @@ macro_rules! functionality {
/// the external API.
/// # Errors
fn _test_only_raw_sign(
&self, rng: &mut impl CryptoRngCore, m: &[u8], randomize: bool,
&self, rng: &mut impl CryptoRngCore, m: &[u8], hedged: bool,
) -> Result<[u8; SIG_LEN], &'static str> {
let mut opt_rand = (self.0).pk_seed;
// 4: if (RANDOMIZE) then ▷ or to a random n-byte string
if randomize {
// 4: if (hedged) then ▷ or to a random n-byte string
if hedged {
// 5: opt_rand ←$ Bn
rng.try_fill_bytes(&mut opt_rand)
.map_err(|_| "Alg17: rng failed")?;

View file

@ -86,7 +86,7 @@ pub(crate) fn slh_keygen_internal<
/// calling function, and this collection proceeds down into the hasher (to help avoid memory
/// allocation, buffer copies, etc).
///
/// Input: Message `M`, context string `ctx`, private key `SK`. `randomize` == hedged variant <br>
/// Input: Message `M`, context string `ctx`, private key `SK`. `hedged` == hedged variant <br>
/// Output: SLH-DSA signature `SIG`.
#[allow(clippy::similar_names)]
#[allow(clippy::cast_possible_truncation)] // temporary, investigating idx_leaf int sizes
@ -101,7 +101,7 @@ pub(crate) fn slh_sign_with_rng<
const N: usize,
>(
rng: &mut impl CryptoRngCore, hashers: &Hashers<K, LEN, M, N>, mp: &[&[u8]],
sk: &SlhPrivateKey<N>, randomize: bool,
sk: &SlhPrivateKey<N>, hedged: bool,
) -> Result<SlhDsaSig<A, D, HP, K, LEN, N>, &'static str> {
//
// 1: if |𝑐𝑡𝑥| > 255 then
@ -115,7 +115,7 @@ pub(crate) fn slh_sign_with_rng<
// 5: if 𝑎𝑑𝑑𝑟𝑛𝑑 = NULL then
// 6: return ⊥
if randomize {
if hedged {
//
rng.try_fill_bytes(&mut opt_rand)
.map_err(|_| "Alg17: rng failed")?;
@ -160,7 +160,7 @@ pub(crate) fn slh_sign_internal<
// 2: 𝑜𝑝𝑡_𝑟𝑎𝑛𝑑𝑎𝑑𝑑𝑟𝑛𝑑 ▷ substitute 𝑜𝑝𝑡_𝑟𝑎𝑛𝑑 ← PK.seed for the deterministic variant
// This is handled in the calling function
// 3: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate randomizer
// 3: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate hedgedr
let r = (hashers.prf_msg)(&sk.sk_prf, &opt_rand, m);
// 4: SIG ← R

View file

@ -189,18 +189,18 @@ pub trait Signer {
/// ```
#[cfg(feature = "default-rng")]
fn try_sign(
&self, message: &[u8], ctx: &[u8], randomize: bool,
&self, message: &[u8], ctx: &[u8], hedged: bool,
) -> Result<Self::Signature, &'static str> {
self.try_sign_with_rng(&mut OsRng, message, ctx, randomize)
self.try_sign_with_rng(&mut OsRng, message, ctx, hedged)
}
/// blah
/// # Errors
#[cfg(feature = "default-rng")]
fn try_sign_hash(
&self, message: &[u8], ctx: &[u8], ph: &Ph, randomize: bool,
&self, message: &[u8], ctx: &[u8], ph: &Ph, hedged: bool,
) -> Result<Self::Signature, &'static str> {
self.try_sign_hash_with_rng(&mut OsRng, message, ctx, ph, randomize)
self.try_sign_hash_with_rng(&mut OsRng, message, ctx, ph, hedged)
}
/// Attempt to sign the given message, returning a digital signature on success, or an error if
@ -236,14 +236,14 @@ pub trait Signer {
/// # }
/// ```
fn try_sign_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], randomize: bool,
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], hedged: bool,
) -> Result<Self::Signature, &'static str>;
/// blah
/// # Errors
fn try_sign_hash_with_rng(
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph, randomize: bool,
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8], ph: &Ph, hedged: bool,
) -> Result<Self::Signature, &'static str>;
@ -252,7 +252,7 @@ pub trait Signer {
/// # Errors
#[deprecated = "Temporary function to allow application of internal nist vectors; will be removed"]
fn _test_only_raw_sign(
&self, rng: &mut impl CryptoRngCore, m: &[u8], randomize: bool,
&self, rng: &mut impl CryptoRngCore, m: &[u8], hedged: bool,
) -> Result<Self::Signature, &'static str>;
}

View file

@ -6,10 +6,10 @@ use rand_chacha::rand_core::SeedableRng;
#[test]
fn test_browser_message() {
let msg = b"asdf";
let randomize = true;
let hedged = true;
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
let (pk, sk) = slh_dsa_sha2_128f::KG::try_keygen_with_rng(&mut rng).unwrap();
let sig = sk.try_sign_with_rng(&mut rng, msg, &[], randomize).unwrap();
let sig = sk.try_sign_with_rng(&mut rng, msg, &[], hedged).unwrap();
assert!(pk.verify(msg, &sig, b"context"));
assert_eq!(sk.into_bytes(), *hex::decode("932b30e756257dda01d47dd4a1b0e62abb8fa01f222ad8554ed821a89f82cbbb3f537f509949e758624a70946a776986052a5761098a9b4ecbfaa10a92aee325").unwrap(), "sk not correct");

View file

@ -8,10 +8,10 @@ use fips205::traits::{SerDes, Signer, Verifier};
pub fn sign(message: &str) -> String {
let seed = 123;
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
let randomize = true;
let hedged = true;
let (pk, sk) = slh_dsa_sha2_128f::try_keygen_with_rng(&mut rng).expect("keygen failed");
let sig = sk.try_sign_with_rng(&mut rng, message.as_ref(), randomize).expect("sign failed");
let sig = sk.try_sign_with_rng(&mut rng, message.as_ref(), hedged).expect("sign failed");
assert!(pk.verify(message.as_ref(), &sig).expect("verify error"), "verify failed");
let sk_hex = hex::encode(&sk.into_bytes());