x509roots/fallback/bundle: fix bundle test with Go 1.27+

In Go 1.27 we've updated crypto/x509/pkix to avoid hex-encoding
attribute values that are string-typed. However, in TestBundle() we
assert the parsed certificate subject CN matches expected and now the
parsed value differs based on Go version.

This commit introduces some small helpers that on Go 1.25/1.26 replicate
the Go 1.27 behavior, decoding hex-encoded attribute values before
making the comparison.

In this way the test continues to pass without losing any coverage, or
introducing duplicated per-version bundles. In the future when only Go
1.27+ are supported we can revert this extra machinery.

Change-Id: I66bf6439e421169c0f9c750f88116b73ec5188fe
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/775760
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Daniel McCarney <daniel@binaryparadox.net>
This commit is contained in:
Daniel McCarney
2026-05-08 08:10:15 -07:00
committed by Gopher Robot
parent fd0b90d21f
commit 9d9d507896
+34 -1
View File
@@ -7,7 +7,9 @@ package bundle
import (
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/hex"
"regexp"
"testing"
)
@@ -19,7 +21,7 @@ func TestBundle(t *testing.T) {
continue
}
if unparsed.cn != cert.Subject.String() {
if !subjectsEqual(unparsed.cn, cert.Subject.String()) {
t.Errorf("unparsedCertificates[%v].cn = %q; want = %q", i, unparsed.cn, cert.Subject.String())
}
@@ -30,3 +32,34 @@ func TestBundle(t *testing.T) {
}
}
}
// subjectsEqual reports whether two RFC 2253 DN strings match.
//
// It tolerates the rendering difference introduced in Go 1.27, where
// string-typed attribute values for OIDs outside attributeTypeNames are
// rendered as strings rather than hex-encoded DER (see Go CL 773800).
//
// This can be removed when Go 1.25/1.26 are no longer supported.
func subjectsEqual(a, b string) bool {
return a == b || normalizeHexValues(a) == normalizeHexValues(b)
}
// normalizeHexValues rewrites any "oid=#hex" to the equivalent "oid=value"
// rendering produced by Go 1.27+.
func normalizeHexValues(s string) string {
return hexAttrRE.ReplaceAllStringFunc(s, func(match string) string {
m := hexAttrRE.FindStringSubmatch(match)
der, err := hex.DecodeString(m[2])
if err != nil {
return match
}
var v string
if rest, err := asn1.Unmarshal(der, &v); err != nil || len(rest) != 0 {
return match
}
return m[1] + "=" + v
})
}
// hexAttrRE matches a "oid=#hex" attribute value in an RFC 2253 DN string.
var hexAttrRE = regexp.MustCompile(`([\d.]+)=#([[:xdigit:]]+)`)