mirror of
https://github.com/golang/go.git
synced 2026-06-27 03:11:23 +00:00
crypto/x509/pkix: render string-typed attribute values as strings
RFC 2253 §2.4 says that an AttributeValue should be rendered as a string when its ASN.1 type has a string representation, reserving the prefixed hex form for types that don't. RDNSequence.String previously hex-encoded any value whose OID wasn't in attributeTypeNames, even when the value was already a Go string. Render string-typed values directly; the existing escape logic handles RFC 2253 special characters. Fixes #33093 Change-Id: Idb8acd907f9dac902790c9ac7d0bc0cb36b5b918 Reviewed-on: https://go-review.googlesource.com/c/go/+/773800 Reviewed-by: Cherry Mui <cherryyz@google.com> Auto-Submit: Daniel McCarney <daniel@binaryparadox.net> 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>
This commit is contained in:
parent
253aa2a12a
commit
978f00ab7f
3 changed files with 50 additions and 10 deletions
4
doc/next/6-stdlib/99-minor/crypto/x509/pkix/33093.md
Normal file
4
doc/next/6-stdlib/99-minor/crypto/x509/pkix/33093.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[RDNSequence.String] (and therefore [Name.String]) now renders string-typed
|
||||
attribute values as strings even when the attribute's OID is unrecognized.
|
||||
Previously such values were always hex-encoded in their DER form.
|
||||
See [#33093](/issue/33093).
|
||||
|
|
@ -53,12 +53,17 @@ func (r RDNSequence) String() string {
|
|||
oidString := tv.Type.String()
|
||||
typeName, ok := attributeTypeNames[oidString]
|
||||
if !ok {
|
||||
derBytes, err := asn1.Marshal(tv.Value)
|
||||
if err == nil {
|
||||
buf.WriteString(oidString)
|
||||
buf.WriteString("=#")
|
||||
buf.WriteString(hex.EncodeToString(derBytes))
|
||||
continue // No value escaping necessary.
|
||||
// RFC 2253 §2.4: if the value's ASN.1 type has a string
|
||||
// representation, render it as a string; otherwise hex-encode
|
||||
// the DER.
|
||||
if _, ok := tv.Value.(string); !ok {
|
||||
derBytes, err := asn1.Marshal(tv.Value)
|
||||
if err == nil {
|
||||
buf.WriteString(oidString)
|
||||
buf.WriteString("=#")
|
||||
buf.WriteString(hex.EncodeToString(derBytes))
|
||||
continue // No value escaping necessary.
|
||||
}
|
||||
}
|
||||
|
||||
typeName = oidString
|
||||
|
|
|
|||
|
|
@ -2189,7 +2189,7 @@ func TestPKIXNameString(t *testing.T) {
|
|||
dn pkix.Name
|
||||
want string
|
||||
}{
|
||||
{nn, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"},
|
||||
{nn, "L=Gophertown,1.2.3.4.5=golang.org"},
|
||||
{extraNotNil, "L=Gophertown"},
|
||||
{pkix.Name{
|
||||
CommonName: "Steve Kille",
|
||||
|
|
@ -2218,13 +2218,13 @@ func TestPKIXNameString(t *testing.T) {
|
|||
Locality: []string{"Gophertown"},
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
|
||||
}, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"},
|
||||
}, "1.2.3.4.5=golang.org,L=Gophertown"},
|
||||
// If there are no ExtraNames, the Names are printed instead.
|
||||
{pkix.Name{
|
||||
Locality: []string{"Gophertown"},
|
||||
Names: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
|
||||
}, "L=Gophertown,1.2.3.4.5=#130a676f6c616e672e6f7267"},
|
||||
}, "L=Gophertown,1.2.3.4.5=golang.org"},
|
||||
// If there are both, print only the ExtraNames.
|
||||
{pkix.Name{
|
||||
Locality: []string{"Gophertown"},
|
||||
|
|
@ -2232,7 +2232,38 @@ func TestPKIXNameString(t *testing.T) {
|
|||
{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 5}), Value: "golang.org"}},
|
||||
Names: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4, 6}), Value: "example.com"}},
|
||||
}, "1.2.3.4.5=#130a676f6c616e672e6f7267,L=Gophertown"},
|
||||
}, "1.2.3.4.5=golang.org,L=Gophertown"},
|
||||
// Non-string value falls back to hex-encoded DER (issue 33093).
|
||||
{pkix.Name{
|
||||
CommonName: "foobar",
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{1, 2, 3, 4}), Value: 42}},
|
||||
}, "1.2.3.4=#02012a,CN=foobar"},
|
||||
// String containing non-PrintableString chars (here, UTF-8) is still
|
||||
// rendered as a string per RFC 2253 §2.4, not hex-encoded.
|
||||
{pkix.Name{
|
||||
CommonName: "foobar",
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{2, 3, 4, 5}), Value: "Lučić"}},
|
||||
}, "2.3.4.5=Lučić,CN=foobar"},
|
||||
// String beginning with '#' has the '#' escaped (RFC 2253 §2.4).
|
||||
{pkix.Name{
|
||||
CommonName: "foobar",
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{2, 3, 4, 5}), Value: "#abcdef"}},
|
||||
}, "2.3.4.5=\\#abcdef,CN=foobar"},
|
||||
// Printable string with an embedded RFC 2253 escapable character.
|
||||
{pkix.Name{
|
||||
CommonName: "foobar",
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{2, 3, 4, 5}), Value: "abcdef,GHI"}},
|
||||
}, "2.3.4.5=abcdef\\,GHI,CN=foobar"},
|
||||
// Printable string with leading and trailing space gets escaped.
|
||||
{pkix.Name{
|
||||
CommonName: "foobar",
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{Type: asn1.ObjectIdentifier([]int{2, 3, 4, 5}), Value: " abcdef "}},
|
||||
}, "2.3.4.5=\\ abcdef\\ ,CN=foobar"},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue