Skip to content

proposal: crypto/x509: support RFC 9935 PKIX and PKCS#8 encodings for ML-KEM keys #79225

Description

@tobyguelly

Proposal Details

I propose adding support to crypto/x509 for parsing and marshaling ML-KEM public and private keys according to RFC 9935.

Go already provides crypto/mlkem, whose key types expose byte encodings for public keys and seed-based private keys. crypto/x509 already provides APIs for marshaling and parsing PKIX public keys and PKCS#8 private keys. Adding ML-KEM support there allows crypto/mlkem keys to use the standard RFC 9935 encodings without requiring applications to implement their own ASN.1 wrappers.

This would extend the following existing key encoding APIs:

crypto/x509/x509.go

crypto/x509/pkcs8.go

This proposal is limited to key encoding and decoding. It does not propose adding ML-KEM as a certificate signature algorithm, does not add TLS certificate authentication support, and does not add general ML-KEM certificate semantics.

Background

RFC 9935 specifies the X.509/PKIX algorithm identifiers and key encodings for ML-KEM. The relevant OIDs are:

  • ML-KEM-768: 2.16.840.1.101.3.4.4.2
  • ML-KEM-1024: 2.16.840.1.101.3.4.4.3

RFC 9935 also defines ML-KEM-512, but this proposal does not include it because crypto/mlkem does not currently expose ML-KEM-512.

Proposed Changes

Extend x509.MarshalPKIXPublicKey to accept:

  • *mlkem.EncapsulationKey768
  • *mlkem.EncapsulationKey1024

Extend x509.ParsePKIXPublicKey to return:

  • *mlkem.EncapsulationKey768
  • *mlkem.EncapsulationKey1024

when the SubjectPublicKeyInfo algorithm identifier contains the corresponding RFC 9935 ML-KEM OID.

Extend x509.MarshalPKCS8PrivateKey to accept:

  • *mlkem.DecapsulationKey768
  • *mlkem.DecapsulationKey1024

Extend x509.ParsePKCS8PrivateKey to return:

  • *mlkem.DecapsulationKey768
  • *mlkem.DecapsulationKey1024

when the PrivateKeyInfo private key algorithm identifier contains the corresponding RFC 9935 ML-KEM OID.

Encoding Details

The AlgorithmIdentifier parameters for ML-KEM keys must be absent, as required by RFC 9935. Encodings that include parameters, including ASN.1 NULL parameters, should be rejected.

For public keys, the SubjectPublicKeyInfo.subjectPublicKey value is the raw ML-KEM public key bytes. Expected public key sizes are 1184 bytes for ML-KEM-768 and 1568 bytes for ML-KEM-1024.

For private keys, this proposal supports only the RFC 9935 seed private-key format. This aligns with the Bytes representation of the existing crypto/mlkem decapsulation key types:

ML-KEM-PrivateKey ::= CHOICE {
    seed [0] OCTET STRING (SIZE (64))
}

Open Questions

  • Should ParsePKCS8PrivateKey accept the RFC 9935 expanded private-key forms for interoperability, or should Go initially support only seed private keys?

/cc @golang/security

Metadata

Metadata

Assignees

No one assigned

    Labels

    LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolProposal

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions