Repository navigation
Conversation
|
CC @fabianfett if you're back, could we get a CI run on this? |
|
There are also some test failures that need looking at. |
|
@Lukasa can you re-trigger CI? |
Motivation: The upcoming ML-DSA support uses the MLDSA65/MLDSA87 APIs that first appeared in swift-crypto 4.0.0. Raising the floor in a minor release follows this repository's own precedent (apple#39, apple#275, apple#300). A SwiftPM trait was considered instead, but traits are used in the ecosystem to gate optional dependencies, not versions of a required one, and SE-0450 cannot express a per-trait version floor. Modifications: - Raise the swift-crypto lower bound from 3.12.3 to 4.0.0 in Package.swift and Benchmarks/Package.swift. Result: swift-certificates requires swift-crypto 4.0.0 or later, which dependency resolution already selects for any graph that does not pin swift-crypto below 4.
Motivation: RFC 9881 registers algorithm identifiers for ML-DSA (FIPS 204) in X.509, and swift-crypto ships MLDSA65 and MLDSA87. swift-certificates could not even parse a certificate whose issuer signed with ML-DSA: Certificate.init threw on the issuer's signature algorithm before any verification was attempted, blocking post-quantum CA hierarchies. Modifications: - Add the id-ml-dsa-65 and id-ml-dsa-87 OIDs and AlgorithmIdentifier statics (parameters absent, per RFC 9881), and Certificate.SignatureAlgorithm.mldsa65/.mldsa87. - Extend Certificate.Signature with a backing case carrying the raw signature bytes, mirroring Ed25519. - Add MLDSA.swift: ML-DSA public keys are stored as validated raw bytes and rebuilt per verification, because CryptoKit's ML-DSA types are macOS 26+ on Darwin and enum cases cannot carry availability. Below macOS 26 an ML-DSA subject public key fails loudly at decode; on Linux support is unconditional. - Extend Certificate.PublicKey with SPKI decode/encode, verification dispatch, and the standard wrap/unwrap initializers. - Add MLDSATests with OpenSSL 3.6.3 interop fixtures covering parse, byte-identical round-trips, self-signature known-answer tests, tampered/wrong-parameter-set/wrong-root/padding-bits negatives, ML-DSA-44 rejection, and chain validation through Verifier with RFC5280Policy. Signing, ML-DSA-44, HashML-DSA, and TLS signature-scheme codepoints are deliberately not supported and throw unsupportedSignatureAlgorithm. Result: Certificates signed with ML-DSA-65 or ML-DSA-87 parse, round-trip, and verify, including full chains through the normal verifier path.
Motivation: Review feedback on the ML-DSA verification path: the #available guard in MLDSAPublicKeyBytes.isValidSignature can never fail at runtime, because every initializer of the type itself requires ML-DSA availability. Returning false there would present a broken library invariant as a signature-verification failure. Modifications: - Replace the guard's `return false` with a fatalError encoding the unreachability justification, and a comment explaining why the guard must exist at all (the function is callable from baseline-availability dispatch code while the swift-crypto calls are macOS 26+ on Darwin). Result: A violated construction invariant now traps loudly instead of being reported as an invalid signature.
Motivation: Code review on the ML-DSA pull request asked for several consistency and concision changes. Modifications: - Drop the unused SwiftASN1 import from MLDSA.swift. - Rename MLDSAPublicKeyBytes.bytes to rawRepresentation, matching swift-crypto's ML-DSA public key API. - Extract the variant-to-AlgorithmIdentifier mapping into AlgorithmIdentifier.init(mldsaVariant:). - Condense the MLDSAVariant, MLDSAPublicKeyBytes, and fatalError comments, and several test and fixture comments. - Annotate the ML-DSA test methods with @available instead of guarding each body with #available and XCTSkip. Result: No functional change; the diff shrinks by ~45 lines and matches the reviewer's suggestions.
Motivation: Review feedback: keep the swift-crypto floor at 3.12.3 and make ML-DSA opt-in. This also fixes the macOS and CMake CI jobs, which build against SDKs/checkouts whose swift-crypto has no ML-DSA and so must not see the MLDSA65/MLDSA87 types in a default build, and the docs check, which rejected doc links with the wrong parameter list. Modifications: - Restore the 3.12.3 floor and add a default-off `MLDSA` trait that defines SWIFT_CERTIFICATES_MLDSA on X509 and X509Tests. - Gate all code naming MLDSA65/MLDSA87 behind the trait. Parsing certificates *signed* with ML-DSA stays unconditional. - Gate the key-material tests; restore the test that decoding an ML-DSA key without the trait fails loudly. - Fix doc links to unsupportedSignatureAlgorithm(reason:file:line:). Result: Default builds keep the 3.12.3 floor and compile on toolchains without ML-DSA (532 tests pass); `swift test --traits MLDSA` opts in (544 tests pass).
913619a to
1c66422
Compare
|
Rebased onto current Review feedback:
Local results (Linux, Swift 6.4.1, swift-crypto 4.5.1): |
1c66422 to
913619a
Compare
|
Note: the branch head is temporarily back at 913619a. Downstream packages pin a commit of this PR by SHA from this repository's URL and lost it when the branch was rebased; they are moving to the rebased head first. The rebased work (onto main 715a2f4, Package.swift conflict resolved, all tests green) is at wendylabsinc/swift-certificates branch mldsa-support-rebased-1c664223 and will replace this head once those pins have moved. |
913619a to
1c66422
Compare
swift-certificates can't yet parse a certificate signed with ML-DSA: it throws on the issuer's signature algorithm before verification even starts, even though swift-crypto already supports these algorithms. That turned out to be a blocker in one of our projects involving PQ PKI.
This PR adds parsing and verification for ML-DSA-65 and ML-DSA-87, per RFC 9881.