You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When template.SubjectKeyId is empty and template.IsCA is true, CreateCertificate fills it in as the sha1.Sum of the raw public key (without the SubjectPublicKeyInfo algorithm metadata).
This is documented in the CreateCertificate docs as
If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId will be generated from the hash of the public key.
and in an internal comment as
// SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2:
// (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
// value of the BIT STRING subjectPublicKey (excluding the tag,
// length, and number of unused bits).
That part of RFC 5280, Section 4.2.1.2 is a SHOULD, and says that other methods are allowed.
RFC 7093 specifies four additional methods: the first 160 bits of the SHA-256, SHA-384, or SHA-512 of the same raw public key, or an unspecified hash of the SubjectPublicKeyInfo.
Using SHA-1 is currently panic'ing in fips140=only mode. This can be worked around by specifying an explicit template.SubjectKeyId but the hash input is not trivial to compute for an application.
Proposal
Switch to using the first 160 bits of the SHA-256 of the raw public key. (Hashing the whole SubjectPublicKeyInfo is appealing, but ultimately this field has no security relevance, and we might as well align with Let's Encrypt.)
The behavior can be reverted with GODEBUG=x509sha256skid=0.
I don't think we ever promised the CreateCertificate output to be stable, but I can imagine one risk of this change being applications that regenerate a certificate instead of storing it and expect it to have the same SKID.
Alternatively, we can use SHA-256 only in FIPS 140-3 mode, but that might be even more confusing, and we tried to keep the behavior divergence at a minimum.
The text was updated successfully, but these errors were encountered:
The most significant danger for this change is compatibility with external tools that make assumptions about SKID being SHA-1. We've seen that periodically in the Let's Encrypt community forums, with tooling either:
Assuming that a SKID in a CSR would be copied to the final certificate (which has never been true for us, it merely looked true), or
Breaking because it expected to independently derive the same SKID string.
Neither case has been very common, and the semantics of RFC 5280 are clearly in favor of it being treated as an opaque string.
I think your proposal to use a truncated SHA-256 is a good one.
I'm going to bump this out of the proposal process, since this is an undocumented implementation detail, and should not need a formal proposal. We've previously made changes to this particular behavior without proposals, e.g. see https://go.dev/issue/39429.
It seems plausible that this may break some tooling which assumes the way the SKID is generated, but those things are acting inappropriately, since an external consumer should not be making any assumptions about the format of the SKID, as @jcjones says it's intended to be entirely opaque, with RFC 5280 Section 4.2.1.2 being merely a suggestion.
Let's do it and see what breaks.
rolandshoemaker
changed the title
proposal: crypto/x509: use truncated SHA-256 for SubjectKeyId
crypto/x509: use truncated SHA-256 for SubjectKeyId
Mar 19, 2025
Background
When
template.SubjectKeyId
is empty andtemplate.IsCA
is true,CreateCertificate
fills it in as thesha1.Sum
of the raw public key (without the SubjectPublicKeyInfo algorithm metadata).This is documented in the
CreateCertificate
docs asand in an internal comment as
That part of RFC 5280, Section 4.2.1.2 is a SHOULD, and says that other methods are allowed.
RFC 7093 specifies four additional methods: the first 160 bits of the SHA-256, SHA-384, or SHA-512 of the same raw public key, or an unspecified hash of the SubjectPublicKeyInfo.
Let's Encrypt moved to truncated SHA-256 of the raw public key one year ago.
Generally, the SubjectKeyId is an opaque string.
Using SHA-1 is currently panic'ing in
fips140=only
mode. This can be worked around by specifying an explicittemplate.SubjectKeyId
but the hash input is not trivial to compute for an application.Proposal
Switch to using the first 160 bits of the SHA-256 of the raw public key. (Hashing the whole SubjectPublicKeyInfo is appealing, but ultimately this field has no security relevance, and we might as well align with Let's Encrypt.)
The behavior can be reverted with
GODEBUG=x509sha256skid=0
.I don't think we ever promised the CreateCertificate output to be stable, but I can imagine one risk of this change being applications that regenerate a certificate instead of storing it and expect it to have the same SKID.
Alternatively, we can use SHA-256 only in FIPS 140-3 mode, but that might be even more confusing, and we tried to keep the behavior divergence at a minimum.
The text was updated successfully, but these errors were encountered: