// Copyright 2026 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !go1.27 package bundle import ( "encoding/asn1" "encoding/hex" "regexp" ) // subjectsEqual reports whether two RFC 2253 DN strings match. // // When testing with Go 1.27 or newer, it requires subjects to match exactly. // When testing with Go 1.26, 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). // // When Go 1.26 is no longer supported, // the Go 1.26 version can be removed and // the Go 1.27+ version can be inlined. 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:]]+)`)