Skip to content

Feature/mldsa cert generation 669#670

Open
netanmangal wants to merge 5 commits into
FiloSottile:masterfrom
netanmangal:feature/mldsa-cert-generation-669
Open

Feature/mldsa cert generation 669#670
netanmangal wants to merge 5 commits into
FiloSottile:masterfrom
netanmangal:feature/mldsa-cert-generation-669

Conversation

@netanmangal

Copy link
Copy Markdown

Add --mldsa flag for generating ML-DSA (FIPS 204) development certificates.

Relates to #669

mkcert --mldsa localhost 127.0.0.1 ::1

Design:

  • mldsa_go127.go (Go 1.27+): Uses crypto/mldsa natively. x509.CreateCertificate handles ML-DSA directly — no custom ASN.1.
  • mldsa_nogo127.go (Go < 1.27): Returns clear error. mldsaSupported = false.
  • No dependency changes. go.mod unchanged.
  • --ecdsa + --mldsa mutual exclusion enforced.
  • --mldsa --pkcs12 rejected (PKCS#12 can't encode PQ keys).
  • KeyUsage: DigitalSignature only (no KeyEncipherment).

mldsa_test.go (223 lines): 7 tests — key generation, root CA, leaf cert + chain verification, CA reload, flag precedence, RSA/ECDSA regression. Verified via openssl x509 -text: Signature Algorithm: ML-DSA-65.

Add the -mldsa flag parallel to the existing -ecdsa flag, including
mutual exclusion validation and CSR conflict checking. The flag will
enable ML-DSA-65 (FIPS 204) key generation for both root CA and leaf
certificates.

Ref: FiloSottile#669
Signed-off-by: netanmangal <imnetanmangal@gmail.com>
Introduce mldsa_go127.go (using crypto/mldsa from Go 1.27 stdlib)
and mldsa_nogo127.go (stub returning clear errors) to support ML-DSA
key generation without breaking builds on older Go versions.

The Go 1.27 path uses crypto/mldsa.MLDSA65 (FIPS 204) for key
generation and delegates to the stdlib x509 package for marshaling,
which gained native ML-DSA support in that release.

Ref: FiloSottile#669
Signed-off-by: netanmangal <imnetanmangal@gmail.com>
Integrate ML-DSA-65 into generateKey(), makeCert(), and newCA():

- generateKey() delegates to generateMLDSAKey() when -mldsa is set,
  with a build-time guard that fatals on Go < 1.27
- makeCert() sets KeyUsage to DigitalSignature only (ML-DSA cannot
  do key encipherment) and rejects the -pkcs12 + -mldsa combination
  since PKCS#12 libraries do not support post-quantum keys
- newCA() and loadCA() work unchanged because Go 1.27's x509 package
  natively handles ML-DSA in CreateCertificate, MarshalPKCS8PrivateKey,
  and ParsePKCS8PrivateKey

Ref: FiloSottile#669
Signed-off-by: netanmangal <imnetanmangal@gmail.com>
Test coverage for the ML-DSA-65 code path (guarded by //go:build go1.27):

- TestGenerateMLDSAKey: key generation produces *mldsa.PrivateKey
  for both leaf and root CA modes
- TestMLDSARootCA: root CA creation writes valid ML-DSA cert and key
- TestMLDSALeafCert: leaf cert is ML-DSA, signed by ML-DSA CA,
  verifies successfully, has correct KeyUsage (no KeyEncipherment)
- TestMLDSALoadCA: round-trip create/load preserves ML-DSA key types
- TestMLDSANotECDSA: mldsa flag takes precedence correctly
- TestECDSAStillWorks, TestRSAStillWorks: no regressions

Ref: FiloSottile#669
Signed-off-by: netanmangal <imnetanmangal@gmail.com>
The Go 1.27 stdlib x509 package natively handles ML-DSA keys in
MarshalPKCS8PrivateKey, ParsePKCS8PrivateKey, MarshalPKIXPublicKey,
and CreateCertificate. The wrapper functions (marshalMLDSAPrivateKey,
marshalMLDSAPublicKey, parseMLDSAPrivateKey, isMLDSAKey, etc.) are
unnecessary since cert.go's existing x509 calls work transparently
with ML-DSA keys on Go 1.27.

Keep only generateMLDSAKey() and the mldsaSupported constant.

Ref: FiloSottile#669
Signed-off-by: netanmangal <imnetanmangal@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant