The mldsa_verify_test macro previously hardcoded MlDsa44 for decoding both verifying keys and signatures. Due to public key length mismatches, this caused tests for ML-DSA-65 and ML-DSA-87 to fail type conversion and be silently skipped.
Using $params ensures test vectors for all parameter sets are properly decoded and verified.
Add public accessor for the challenge hash component of ML-DSA
signatures, needed by hybrid schemes that share
the challenge across both classical and post-quantum components.
Enable `module-lattice/alloc` feature when the `alloc` feature is
enabled. With this change, users don't need to add an explicit entry
`module-lattice` at `Cargo.toml` to enable the `alloc` feature of the
`module-lattice` crate.
This also aligns with the behavior of the `ml-kem` crate.
This should be a true "release candidate" in that there are no
additional changes intended to be made before a final release, we're
just waiting for some final feedback on recent changes.
Adds an `alloc`-gated `verifying_key` field to `SigningKey`, and when
the feature is enabled precomputes the key at the time the `SigningKey`
is initialized.
We previously used to do this but stopped to optimize stack usage (see
the changes in #1259 and #1261), however when `alloc` is enabled this
isn't an issue since we've moved the relevant data to the heap in this
case (see #1344 and #1345), so stack usage is no longer an issue.
This makes it possible to implement `signature::KeypairRef` for
`SigningKey` which still provides a blanket `signature::Keypair` impl,
so we can always depend on the latter being availble but take advantage
of the former when `alloc` is enabled.
Opportunistically stores the parts of `SigningKey` on the heap when the
`alloc` feature is enabled, similar to what #1344 did for
`VerifyingKey`.
This also addresses #1308 by adding a `Drop` (and `ZeroizeOnDrop`) impl
to `SigningKey` which clears the `Seed`.
When the `alloc` feature is enabled, uses `Box` to offload the largest
parts of `VerifyingKey` to the heap.
This also extracts an internal `PrecomputedValues` struct to store the
largest components of the key, which are all derived/precomputed values,
as a single contiguous struct in a `MaybeBox`, and extracts some of the
relevant logic to it.
Implements these traits sourced from the `crypto-common` crate.
Also implements the `Generate` trait for key generation, replacing the
previous `KeyGen` trait, which this commit deprecates in favor of using
`KeyInit` and `Generate`.
This also adds a `getrandom` feature that forwards through to
`crypto-common`, making methods available on the `Generate` trait when
enabled.
Extracts a `SigningKey::from_seed` that was previously defined on
`MlDsaParams` via a trait impl.
This changes it to an inherent method, and has the trait method call the
inherent method.
This makes it possible to restrict the visibility of `SigningKey`
fields, addressing a TODO.
Extracts code previously in `lib.rs` related to the following types into
two modules:
- `signing`: `SigningKey`, `ExpandedSigningKey`
- `verifying`: `VerifyingKey`
Per #1229: Signature and public-key types lack `Hash`, which prevents
use in `HashMap` / `HashSet` keys and similar collections.
- ecdsa: Signature, DER Signature, SignatureWithOid
- ed25519: Signature, pkcs8::PublicKeyBytes
- ed448: Signature, pkcs8::PublicKeyBytes
- ml-dsa: Signature, VerifyingKey
- slh-dsa: Signature, VerifyingKey
Where a trivial derive works (ed25519, ed448), uses derive. Where
generic bounds or upstream gaps require it, uses a manual impl over
the canonical serialized bytes (`to_bytes` / `encode` / `as_bytes`),
which is the natural Hash domain for these types anyway.
Closes#1229
Adds an internal type for opportunistic heap offload which uses `Box`
when the `alloc` feature is available and falls back to stack allocation
when it is not.
So far it's only used for the `z` component of `Signature` but is useful
elsewhere, e.g. for `VerifyingKey`.
It's so generally useful it should probably get extracted somewhere, to
`module-lattice` at the very least, but this is enough to get started.
Releases the following, which all now depend either directly or
transitively on `pkcs8` v0.11 (which had breaking changes in the final
release)
- `dsa` v0.7.0-rc.15
- `ecdsa` v0.17.0-rc.18
- `ed25519` v3.0.0-rc.5
- `ed448` v0.5.0-rc.6
- `ml-dsa` v0.1.0-rc.9
- `slh-dsa` v0.2.0-rc.5
- `xmss` v0.1.0-pre.1
The existing Drop impl for ExpandedSigningKey (gated on the zeroize
feature) zeroizes rho, K, tr, s1, s2, and t0 but skips the
NTT-domain derived values s1_hat, s2_hat, and t0_hat.
The NTT is invertible, so s1_hat in memory is equivalent to having
s1. This leaves secret key material unzeroized after drop.
Add s1_hat, s2_hat, and t0_hat to the Drop impl. All three are
NttVector types which implement Zeroize via module-lattice.
A_hat (the public matrix derived from rho) is not zeroized here
because NttMatrix does not implement Zeroize in module-lattice.
A_hat is derived from public data (rho) so this is lower priority,
but a follow-up PR to module-lattice could add Zeroize for NttMatrix
for completeness.
This reworks the API to make KeyGen::from_seed return a
`SeededSigningKey` instead of a `KeyPair`.
The `SeededSigningKey` effectively replaces the `KeyPair`, and instead
of eagerly generating the VerifyingKey (implementing
`signature::KeypairRef`), it implements `signature::Keypair` and makes
the verifying key when requested.
This reduces the depth of the stack when calling from_seed and reduces
the size of the stack by 207kb using ML-DSA-87 in debug/tests builds
(the heaviest consumers).
This is an API break.
When using the KeyGen::from_seed is used, the A Matrix is
computed (using `expand_a`).
By design, the matrix is kept on the stack, and two copies end up being
held (One in the `SigningKey` and another one in the `VerifyingKey`).
That matrix takes up to 56kB for ML-DSA-87.
Because two `SigningKey::new`/`VerifyingKey::new` code paths maybe
used without the A matrix (when decoding from an expanded key), the code
paths for both builder end up having to store two copies of the matrix
and increases the stack size.
This is all private API and does not break any of the public API.
This only affects the debug/test builds as the release builds appears to
optimize the unwrap_or_else and not use extraneous stack space.
NOTE: temporarily excludes `slh-dsa` from the workspace until `rand` is
bumped because it is the only crate that depends on it
Release notes:
https://github.com/rust-random/rand_core/releases/tag/v0.10.0
Also bumps the following:
- `chacha20` v0.10.0-rc.10
- `cipher` v0.5.0-rc.7
- `crypto-bigint` v0.7.0-rc.24
- `crypto-common` v0.2.0-rc.14
- `digest` v0.11.0-rc.10
- `elliptic-curve` v0.14.0-rc.27
- `signature` v3.0.0-rc.10
For allow instances of `allow(clippy::integer_division_remainder_used)`
adds a `reason` field which is now one of "constant" (as in bound to an
all-caps-named `const` value) or "tests".