Proposal Details
Golang’s crypto/x509 library is widely used in the WebPKI. As a certificate authority, it would be helpful if there was support for handling the “To Be Signed” portion of a certificate. While crypto/x509.Certificate exposes it as the RawTBSCertificate field today, there is no first-class support for handling a TBSCertificate as an in-memory structure, creating a serialized TBSCertificate from a struct, or parsing a DER TBSCertificate to a struct.
Currently, the ecosystem uses workarounds including signing certificates with throwaway keys or fixed dummy signatures, using forks of crypto/x509, or reimplementing parts of certificate parsing or encoding. While this works, it feels like something we could make better. This problem space may feel niche, but being able to operate on a certificate’s TBS is relatively important for a certificate authority. In particular, we want to run linters on the DER encoded TBS before signing. We want to log the TBS before signing it. And we want to be able to parse the stored TBS, whether for writing linters or just inspecting logged data.
All of the code required is in x509/crypto today, but isn’t public. I’ve prototyped the refactoring required in https://github.com/mcpherrinm/x509TBS to make sure this works. I think the most controversial part of this proposed API is going to be the signature algorithms in the APIs here, so I’m at least initially just taking what makes the implementation straightforward and open for alternate options.
Looking forward, exposing CreateTBSCertificate with the correct pkix.AlgorithmIdentifier (id-alg-mtcProof) will allow creating Merkle Tree Certificates without the rest of crypto/x509 needing to be aware of their format.
Specifications
Add the following functions to crypto/x509:
Three functions which create a TBS (Certificate, and Certificate Revocation List), refactored out of the existing CreateCertificate and CreateRevocationList functions:
func CreateTBSCertificate(rand io.Reader, template, parent *Certificate, pub any, signatureAlgorithm pkix.AlgorithmIdentifier) ([]byte, error)
func CreateTBSRevocationList(template *RevocationList, issuer *Certificate, signatureAlgorithm pkix.AlgorithmIdentifier) ([]byte, error)
Three matching Parse functions:
func ParseTBSCertificate(der []byte) (*Certificate, error)
func ParseTBSRevocationList(der []byte) (*RevocationList, error)
And a SignTBS function, which can be used to sign any of the two TBS types. Note this isn’t the same as current private signTBS function, as that doesn’t include serializing the result into DER.
func SignTBS(rand io.Reader, tbs []byte, signatureAlgorithm SignatureAlgorithm, algorithmIdentifier pkix.AlgorithmIdentifier, key crypto.Signer) ([]byte, error)
Proposal Details
Golang’s crypto/x509 library is widely used in the WebPKI. As a certificate authority, it would be helpful if there was support for handling the “To Be Signed” portion of a certificate. While crypto/x509.Certificate exposes it as the RawTBSCertificate field today, there is no first-class support for handling a TBSCertificate as an in-memory structure, creating a serialized TBSCertificate from a struct, or parsing a DER TBSCertificate to a struct.
Currently, the ecosystem uses workarounds including signing certificates with throwaway keys or fixed dummy signatures, using forks of crypto/x509, or reimplementing parts of certificate parsing or encoding. While this works, it feels like something we could make better. This problem space may feel niche, but being able to operate on a certificate’s TBS is relatively important for a certificate authority. In particular, we want to run linters on the DER encoded TBS before signing. We want to log the TBS before signing it. And we want to be able to parse the stored TBS, whether for writing linters or just inspecting logged data.
All of the code required is in x509/crypto today, but isn’t public. I’ve prototyped the refactoring required in https://github.com/mcpherrinm/x509TBS to make sure this works. I think the most controversial part of this proposed API is going to be the signature algorithms in the APIs here, so I’m at least initially just taking what makes the implementation straightforward and open for alternate options.
Looking forward, exposing CreateTBSCertificate with the correct pkix.AlgorithmIdentifier (id-alg-mtcProof) will allow creating Merkle Tree Certificates without the rest of crypto/x509 needing to be aware of their format.
Specifications
Add the following functions to crypto/x509:
Three functions which create a TBS (Certificate, and Certificate Revocation List), refactored out of the existing CreateCertificate and CreateRevocationList functions:
Three matching Parse functions:
And a SignTBS function, which can be used to sign any of the two TBS types. Note this isn’t the same as current private signTBS function, as that doesn’t include serializing the result into DER.