Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b2c6828
feat(encoders): add text encoder for ML-DSA-65 public keys
ashaindlin Oct 31, 2025
11baff4
refactor(encoders): extract a format_hex_bytes helper function
ashaindlin Nov 3, 2025
45e967f
feat(encoders): add text encoder for ML-DSA-{44,87} public keys
ashaindlin Nov 3, 2025
ab59efb
feat(encoders): add text encoder for ML-DSA-{44,65}-Ed25519 public keys
ashaindlin Nov 3, 2025
dd22305
refactor(encoders): use a macro to generate plain text encoders for p…
ashaindlin Nov 25, 2025
a78123b
refactor(encoders): take encoder name as argument in text encoder gen…
ashaindlin Dec 9, 2025
8cb94d4
feat(adapters/common/transcoders): Do not clutter the current namespa…
romen Dec 11, 2025
41c720b
refactor(common/transcoders): make explicit that the Structureless2Te…
romen Dec 11, 2025
9a4e713
feat(pqclean): Add `ENCODER_PrivateKeyInfo2Text` for MLDSA and Compos…
romen Dec 11, 2025
614ce5f
refactor(common/transcoders/make_privkey_text_encoder): C functions s…
romen Dec 11, 2025
9313a0f
refactor(common/transcoders/make_pubkey_text_encoder): C functions sh…
romen Dec 11, 2025
35722d9
test: add basic known-answer tests for composite signatures
ashaindlin Oct 22, 2025
3f4a24f
feat(tests): add basic wycheproof test for MLDSA65_Ed25519
ashaindlin Nov 21, 2025
2455ef8
feat(tests): add wycheproof verify tests for pure ML-DSA
ashaindlin Nov 24, 2025
158015d
feat(tests): use a testing harness for wycheproof mldsa65ed25519 tests
ashaindlin Nov 24, 2025
ac5cbbf
feat(tests): add wycheproof signing tests for ML-DSA (pure & composite)
ashaindlin Nov 27, 2025
803ba76
fix(tests): don't refer to verify tests as sign tests in error message
ashaindlin Nov 27, 2025
e7724db
fix(tests): check test flags before describing key decoding error as …
ashaindlin Nov 27, 2025
071694b
feat(tests): run signing tests with seed-only keys
ashaindlin Nov 27, 2025
cdbf18c
cleanup(tests): remove base64 dependency and hardcoded MLDSA44_Ed2551…
ashaindlin Dec 12, 2025
cfe2a08
cleanup(tests): build wycheproof module in test mode only
ashaindlin Dec 12, 2025
3057df3
feat(pqclean): fail gracefully on length error when decoding composit…
romen Dec 16, 2025
4b4fd43
chore(Cargo.lock): update local Cargo.lock
romen Dec 16, 2025
6c4998c
chore(release): bump version to 0.10.0+dev
romen Dec 17, 2025
95eb580
feat(pqclean): implement sign and verify with ctx for pure ML-DSA
ashaindlin Dec 1, 2025
9c506b7
feat(pqclean): implement sign and verify with ctx for composite ML-DSA
ashaindlin Dec 1, 2025
851a88c
feat(pqclean): consistently implement Signer/Verifier as a wrapper fo…
romen Dec 16, 2025
056ffac
cleanup(pqclean/composites): remove all legacy draft07 stuff
romen Dec 16, 2025
685fdd9
feat(pqclean): derive private key from seed using rustcrypto-based he…
ashaindlin Dec 3, 2025
b7c47f8
refactor(pqclean): rename SupportedSecretKey trait to SupportedMlDsaS…
ashaindlin Dec 9, 2025
873b510
refactor(pqclean): define ML-DSA seed type alias and enforce at callsite
ashaindlin Dec 12, 2025
2352fac
feat(pqclean): switch to seed-only format for MLDSA44_Ed25519
ashaindlin Dec 12, 2025
19ca72b
feat(pqclean): switch to seed-only format for MLDSA65_Ed25519
ashaindlin Dec 12, 2025
b647a0d
chore(Cargo.toml): revert to wycheproof-rs revision without the tempo…
romen Dec 17, 2025
6f9c8fc
chore(doc,pqclean): refer to pq-composite-sigs-13 everywhere
romen Dec 17, 2025
94f1410
fix(tests): remember to initialize crate::tests::common::setup for wy…
romen Dec 17, 2025
2dd4c85
chore(common/signature): improve error message on expected signature …
romen Dec 17, 2025
ca5da0c
fix(pqclean): validate ctx length before calling the backend
romen Dec 17, 2025
510120c
feat(pqclean): validate decoding of private keys through foreign module
romen Dec 17, 2025
4aa37b8
cleanup(pqclean): rename helpers to make explicit they operate on mldsa
romen Dec 17, 2025
fa17d54
chore(CHANGELOG): Update CHANGELOG for v0.10.0
romen Dec 17, 2025
7da83ea
chore(release): bump version to 0.10.0
romen Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,70 @@

All notable changes to this project will be documented in this file.

## [0.10.0] - 2025-12-17

### ⚠ BREAKING CHANGES

- *(pqclean)* Switch to seed-only format for MLDSA44_Ed25519 private keys
- *(pqclean)* Switch to seed-only format for MLDSA65_Ed25519 private keys

### πŸš€ Features

- Disallow building other profiles than debug
- *(encoders)* Add text encoder for ML-DSA-65 public keys
- *(encoders)* Add text encoder for ML-DSA-{44,87} public keys
- *(encoders)* Add text encoder for ML-DSA-{44,65}-Ed25519 public keys
- *(adapters/common/transcoders)* Do not clutter the current namespace when calling `make_pubkey_text_encoder!`
- *(pqclean)* Add `ENCODER_PrivateKeyInfo2Text` for MLDSA and Composite MLDSA
- *(tests)* Add basic wycheproof test for MLDSA65_Ed25519
- *(tests)* Add wycheproof verify tests for pure ML-DSA
- *(tests)* Use a testing harness for wycheproof mldsa65ed25519 tests
- *(tests)* Add wycheproof signing tests for ML-DSA (pure & composite)
- *(tests)* Run signing tests with seed-only keys
- *(pqclean)* Fail gracefully on length error when decoding composite ML-DSA private keys
- *(pqclean)* Implement sign and verify with ctx for pure ML-DSA
- *(pqclean)* Implement sign and verify with ctx for composite ML-DSA
- *(pqclean)* Consistently implement Signer/Verifier as a wrapper for SignerWithCtx/VerifierWithCtx
- *(pqclean)* Derive private key from seed using rustcrypto-based helper
- *(pqclean)* Validate decoding of private keys through foreign module

### πŸ› Bug Fixes

- *(tests)* Don't refer to verify tests as sign tests in error message
- *(tests)* Check test flags before describing key decoding error as "expected"
- *(tests)* Remember to initialize crate::tests::common::setup for wycheproof tests
- *(pqclean)* Validate ctx length before calling the backend

### 🚜 Refactor

- *(encoders)* Extract a format_hex_bytes helper function
- *(encoders)* Use a macro to generate plain text encoders for public keys
- *(encoders)* Take encoder name as argument in text encoder generator macro
- *(common/transcoders)* Make explicit that the Structureless2Text encoder is specific for public keys only
- *(common/transcoders/make_privkey_text_encoder)* C functions should only do argument parsing and delegate logic to safe rust abstractions.
- *(common/transcoders/make_pubkey_text_encoder)* C functions should only do argument parsing and delegate logic to safe rust abstractions.
- *(pqclean)* Rename SupportedSecretKey trait to SupportedMlDsaSecretKey
- *(pqclean)* Define ML-DSA seed type alias and enforce at callsite

### πŸ“š Documentation

- *(README)* Add notes about SLH-DSA and hybrids
- *(readme)* Fix typos and clarify project description
- *(doc,pqclean)* Refer to pq-composite-sigs-13 everywhere

### πŸ§ͺ Testing

- Add basic known-answer tests for composite signatures
- *(Cargo.toml)* Revert to wycheproof-rs revision without the temporary extension for expanded private keys
- *(common/signature)* Improve error message on expected signature length mismatch

### Cleanup

- *(tests)* Remove base64 dependency and hardcoded MLDSA44_Ed25519 test vectors
- *(tests)* Build wycheproof module in test mode only
- *(pqclean/composites)* Remove all legacy draft07 stuff
- *(pqclean)* Rename helpers to make explicit they operate on mldsa

## [0.9.0] - 2025-10-24

### πŸš€ Features
Expand Down Expand Up @@ -426,6 +490,7 @@ All notable changes to this project will be documented in this file.

<!-- generated by git-cliff -->

[0.10.0]: https://github.com/QUBIP/aurora/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/QUBIP/aurora/compare/v0.8.5...v0.9.0
[0.8.5]: https://github.com/QUBIP/aurora/compare/v0.8.4...v0.8.5
[0.8.4]: https://github.com/QUBIP/aurora/compare/v0.8.3...v0.8.4
Expand Down
34 changes: 31 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "qubip_aurora"
version = "0.9.1+dev"
version = "0.10.0"
edition = "2021"
description = "A framework to build OpenSSL Providers tailored for the transition to post-quantum cryptography"
license = "Apache-2.0"
Expand All @@ -17,7 +17,7 @@ name = "aurora"
default = [
"env_logger",
"default_adapters",
"_composite_sigs_draft_12_postWGLC",
"_composite_sigs_draft_13",
]
default_adapters = [
"libcrux_adapter",
Expand All @@ -31,9 +31,7 @@ export = []
# One (and not more than one!) of the _draft_N features must be enabled to support `_composite_mldsa_eddsa`!
# These features are _experimental_: they will be removed in an upcoming release once the composite_sigs draft graduates to RFC.
# You have been warned: DO NOT DEPEND ON THEM!
_composite_sigs_draft_07 = []
_composite_sigs_draft_12 = []
_composite_sigs_draft_12_postWGLC = []
_composite_sigs_draft_13 = []

# These features are _private_: they are automatically enabled by the selection of adapters.
# DO NOT MANUALLY ENABLE THEM IN CARGO.TOML
Expand Down Expand Up @@ -90,6 +88,7 @@ slhdsa-c-rs = { version = "0.0.3", optional = true }
pqcrypto-mldsa = { version = "0.1.0", optional = true }
pqcrypto-traits = { version = "0.3.5", optional = true }
sha2 = { version = "0.10.9", optional = true }
itertools = "0.14.0"

[build-dependencies]
rasn-compiler = "0.11.0"
Expand All @@ -99,3 +98,4 @@ regex = "1"
tempfile = "3"
serde_json = "1.0.140"
paste = "1.0"
wycheproof = { git = "https://github.com/eferollo/wycheproof-rs", branch = "composite-mldsa-draft13" }
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,17 @@ The current supported algorithms are summarized in the following tables.
| _SLH-DSA-SHAKE-128f_ | rustcrypto | ❎ Exempt | [`0x0918` (`2328`)][ID-reddy-tls-slhdsa-01:sigscheme] ⚠️ | [`2.16.840.1.101.3.4.3.27`][ID-lamps-x509-slhdsa-09:s3.7] |
| _SLH-DSA-SHAKE-192f_ | slhdsa_c | ❎ Exempt | [`0x091A` (`2330`)][ID-reddy-tls-slhdsa-01:sigscheme] ⚠️ | [`2.16.840.1.101.3.4.3.29`][ID-lamps-x509-slhdsa-09:s3.7] |
| _SLH-DSA-SHAKE-256s_ | slhdsa_c | ❎ Exempt | [`0x091B` (`2331`)][ID-reddy-tls-slhdsa-01:sigscheme] ⚠️ | [`2.16.840.1.101.3.4.3.30`][ID-lamps-x509-slhdsa-09:s3.7] |
| _ML-DSA-44_ED25519_ | pqclean | βœ… Composite [`ID-lamps-pq-composite-sigs@12`][ID-lamps-pq-composite-sigs-12] | [`0x090A` (`2314`)][ID-reddy-tls-composite-mldsa-05:sigscheme] | [`1.3.6.1.5.5.7.6.39`][ID-lamps-pq-composite-sigs:GH:post-WGLC:params] |
| _ML-DSA-65_ED25519_ | pqclean | βœ… Composite [`ID-lamps-pq-composite-sigs@12`][ID-lamps-pq-composite-sigs-12] | [`0x090B` (`2315`)][ID-reddy-tls-composite-mldsa-05:sigscheme] | [`1.3.6.1.5.5.7.6.48`][ID-lamps-pq-composite-sigs:GH:post-WGLC:params] |
| _ML-DSA-44_ED25519_ | pqclean | βœ… Composite [`ID-lamps-pq-composite-sigs@13`][ID-lamps-pq-composite-sigs-13] | [`0x090A` (`2314`)][ID-reddy-tls-composite-mldsa-05:sigscheme] | [`1.3.6.1.5.5.7.6.39`][ID-lamps-pq-composite-sigs-13:params] |
| _ML-DSA-65_ED25519_ | pqclean | βœ… Composite [`ID-lamps-pq-composite-sigs@13`][ID-lamps-pq-composite-sigs-13] | [`0x090B` (`2315`)][ID-reddy-tls-composite-mldsa-05:sigscheme] | [`1.3.6.1.5.5.7.6.48`][ID-lamps-pq-composite-sigs-13:params] |

[iana:tls:sigscheme]: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme
[ID-tls-mldsa-01:sigscheme]: https://datatracker.ietf.org/doc/html/draft-ietf-tls-mldsa-01#name-ml-dsa-signaturescheme-valu
[ID-reddy-tls-slhdsa-01:sigscheme]: https://datatracker.ietf.org/doc/html/draft-reddy-tls-slhdsa-01#name-iana-considerations
[ID-lamps-pq-composite-sigs-12]: https://datatracker.ietf.org/doc/draft-ietf-lamps-pq-composite-sigs/12/
[ID-lamps-pq-composite-sigs-13]: https://datatracker.ietf.org/doc/html/draft-ietf-lamps-pq-composite-sigs/13/
[ID-lamps-pq-composite-sigs-13:params]: https://datatracker.ietf.org/doc/html/draft-ietf-lamps-pq-composite-sigs-13#name-algorithm-identifiers-and-p
[ID-reddy-tls-composite-mldsa-05:sigscheme]: https://datatracker.ietf.org/doc/html/draft-reddy-tls-composite-mldsa-05#name-iana-considerations
[nist:csor:algs]: https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
[ID-lamps-x509-slhdsa-09:s3.7]: https://datatracker.ietf.org/doc/html/draft-ietf-lamps-x509-slhdsa-09#section-3-7
[ID-lamps-pq-composite-sigs:GH:post-WGLC:params]: https://github.com/lamps-wg/draft-composite-sigs/blob/5ba4655fa1ae3b3b4c112c6cd8c97a93e6d900c3/src/algParams.md

> [!NOTE]
> - The `ML-DSA-{44,65}_ED25519` algorithms also use `ed25519-dalek`
Expand All @@ -141,7 +141,7 @@ The current supported algorithms are summarized in the following tables.
> experimentation only.
> In QUBIP's Internet Browsing Pilot we avoid pure `ML-DSA`
> deployments in favor of
> ["Composite `ML-DSA`"][ID-lamps-pq-composite-sigs-12]
> ["Composite `ML-DSA`"][ID-lamps-pq-composite-sigs-13]
> and consistently recommend this approach.
> - Transition recommendations that mandate hybrids for the PQC
> transition usually mark `SLH-DSA` as explicitly exempt from the
Expand Down
7 changes: 7 additions & 0 deletions src/adapters/common.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
use crate::named;

pub mod helpers;

pub mod keymgmt_functions;

pub mod macros;

pub mod transcoders;

#[cfg(test)]
pub mod wycheproof;
13 changes: 13 additions & 0 deletions src/adapters/common/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use itertools::Itertools;

/// Formats `bytes` as a colon-separated string of hex values, with `bytes_per_line` elements on
/// each line, indented by `indent` spaces.
pub(crate) fn format_hex_bytes(bytes_per_line: usize, indent: usize, bytes: &[u8]) -> String {
bytes
.iter()
.map(|b| format!("{:02x}", b))
.chunks(bytes_per_line)
.into_iter()
.map(|mut row| format!("{:indent$}{}", "", row.join(":")))
.join(":\n")
}
25 changes: 24 additions & 1 deletion src/adapters/common/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ impl<'a> TryFrom<&'a [u8]> for Signature {

fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
if value.len() != SIGNATURE_LEN {
log::error!("Signature is expected to be exactly {SIGNATURE_LEN} bytes");
log::error!(
"Signature is expected to be exactly {SIGNATURE_LEN} bytes, got {}",
value.len()
);
return Err(anyhow!(
"signature length mismatch, got {}, expected {SIGNATURE_LEN}",
value.len()
Expand Down Expand Up @@ -81,3 +84,23 @@ impl TryInto<SignatureBytes> for Signature {
impl SignatureEncoding for Signature {
type Repr = SignatureBytes;
}

/// Verify the provided message bytestring using `Self` (typically a public key)
pub(crate) trait VerifierWithCtx<S> {
/// Use `Self` to verify that the provided signature for a given message
/// bytestring is authentic.
fn verify_with_ctx(&self, msg: &[u8], signature: &S, ctx: &[u8]) -> Result<(), Error>;
}

/// Sign the provided message bytestring using `Self`, returning a digital signature.
pub(crate) trait SignerWithCtx<S> {
/// Sign the given message and return a digital signature
fn sign_with_ctx(&self, msg: &[u8], ctx: &[u8]) -> S {
self.try_sign_with_ctx(msg, ctx)
.expect("signature operation failed")
}

/// Attempt to sign the given message, returning a digital signature on
/// success, or an error if something went wrong.
fn try_sign_with_ctx(&self, msg: &[u8], ctx: &[u8]) -> Result<S, Error>;
}
Loading