Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto/x509/pkix: Name.String() follows obsolete RFC #27401

Open
pjbgtnj opened this issue Aug 31, 2018 · 4 comments
Open

crypto/x509/pkix: Name.String() follows obsolete RFC #27401

pjbgtnj opened this issue Aug 31, 2018 · 4 comments
Labels
NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@pjbgtnj
Copy link

pjbgtnj commented Aug 31, 2018

Please answer these questions before submitting your issue. Thanks!

The format of a certificate Subject (or Issuer) when made into a String is following RFC 2253 (obsolete) instead of 4514. Using the same format as given by "openssl x509 -in cert.pem -text -noout" would be much more useful.

What version of Go are you using (go version)?

1.11

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

linux, amd64

What did you do?

Print the issuer (or subject) dn from an x509 certificat

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

package main

import (
"crypto/x509"
"encoding/pem"
"fmt"
)

func main() {
rawPem :=
-----BEGIN CERTIFICATE----- MIIDizCCAnOgAwIBAgIJAOnd3oVtvRW4MA0GCSqGSIb3DQEBCwUAMFwxFzAVBgNV BAMMDnNvbWVkb21haW4uY29tMRcwFQYDVQQKDA5NeSBDb3Jwb3JhdGlvbjETMBEG A1UECwwKT3JnIFVuaXQgMTETMBEGA1UECwwKT3JnIFVuaXQgMjAeFw0xODA4MzEw MTE5MzBaFw0xODA5MzAwMTE5MzBaMFwxFzAVBgNVBAMMDnNvbWVkb21haW4uY29t MRcwFQYDVQQKDA5NeSBDb3Jwb3JhdGlvbjETMBEGA1UECwwKT3JnIFVuaXQgMTET MBEGA1UECwwKT3JnIFVuaXQgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAKCmoAGdRmzfb807ZQw1NAIhdqeKeNi7niZeYrzocBavzHd/6WfsdF/FqLjB NH6BRwB7j86O7hyETJcfcXnrJGsKcbBTspMjDBHp+XDvoWElfx7W7A1F/ZI51MjK OZkWFgNl2bGJIvFNAe25fQTlRtjW6/OC+SxXssaHufKjTJDqGo3YlEOvVWcMGXiS cJBOnDTDABt6caAf9QbPFS6SI7Qq7East5xRATkY3Hz9CM5EU5x6j+frO30gvsQs eyIRU6vHgKEsnO90hxF0TQtXiI4IrYL/ofa6J7Ncpnerj0/0+6Kw2qgV5qse8/BS H0AUXwNp9gm/WMDI0ehiwLDUFIcCAwEAAaNQME4wHQYDVR0OBBYEFGl1dJ7BFREN NK2BF5NDqimHP9zfMB8GA1UdIwQYMBaAFGl1dJ7BFRENNK2BF5NDqimHP9zfMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADjJ34L0Rrz+suetYK+NKiXG 8dQcbMOYxSFg8HjNB7ZtL97lRpeRwoPx4IjpcbuYtvKdxVuDea0753VNe7Q3qowt 0k3IEgzVTN5fTInFisLQG9jCfkhHByeNrOgLs6qrk8O+6SqMcOgVuNmMzZDhlXj+ 9drp70xZtLLUN9zFbFESlFoq8GBd4CeerMNn/eU+ukFI/outLU+0+y9lpXwrHglk 9VGJtB40NiSNfhb8MqNTVgPnyEDTOHEStbYddmDTFXtuvGe5b0+j5DBQao87JPr/ rwUus39HqmFbSZtkxEjFI71Dh4Q0HnoDHM8+GyJohYxqk81fQlJJGW0M2XEWT3g= -----END CERTIFICATE-----
pemBlock, _ := pem.Decode([]byte(rawPem))
cert, _ := x509.ParseCertificate(pemBlock.Bytes)
fmt.Printf("%s\n", cert.Issuer)
}

What did you expect to see?

CN=somedomain.com, O=My Corporation, OU=Org Unit 1, OU=Org Unit 2

What did you see instead?

CN=somedomain.com,OU=Org Unit 1+OU=Org Unit 2,O=My Corporation

@meirf meirf changed the title x509 certificate Subject/Issuer DN strings follows obsolete rfc crypto/x509: certificate Subject/Issuer DN strings follows obsolete rfc Aug 31, 2018
@FiloSottile FiloSottile changed the title crypto/x509: certificate Subject/Issuer DN strings follows obsolete rfc crypto/x509/pkix: Name.String() follows obsolete RFC Aug 31, 2018
@FiloSottile FiloSottile added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Aug 31, 2018
@FiloSottile FiloSottile added this to the Unplanned milestone Aug 31, 2018
@FiloSottile
Copy link
Contributor

Unfortunately we documented that we follow RFC 2253 everywhere, and apparently there are systems that require this format. However, RFC 4514 explicitly obsoletes 2253 for this specific use case.

For context: #21615.

@pjbgtnj
Copy link
Author

pjbgtnj commented Sep 6, 2018

In reading RFC 4514 it appears that the two RFC's are very similar with respect to using a "+" to separate mulit-valued rdn's. The problem is actually that the certificate I originally provided is not multi-valued but golang treats it as if it is. The conversion from pkix.Name back to RDNSequence may not be correct.

This command will create a subject with 4 rdn's:

openssl req -x509 -new -newkey rsa:2048 -nodes -subj "/CN=somedomain.com/O=My Corporation/OU=Org Unit 1/OU=Org Unit 2" -out /tmp/test_single.pem

This command will create a multivalued-rdn, ie, a subject with 3 rdn's where the OU rdn is multi-valued.

openssl req -x509 -new -newkey rsa:2048 -nodes -multivalue-rdn -subj "/CN=somedomain.com/O=My Corporation/OU=Org Unit 1/OU=Org Unit 2" -out /tmp/test_multi.pem

Using the following commands you can see the difference in the structure of the ASN1 encodings:

openssl asn1parse -in /tmp/test_multi.pem
openssl asn1parse -in /tmp/test_single.pem

@ctron
Copy link

ctron commented Jun 16, 2020

I ran into the same issue. I think the best approach on the Go side would be to simply parse the RDN sequence, and leave it alone. Only re-arrange it for the "ToString" method if you really think you must do this. But then provide a simple way of getting the unaltered RDNSequence.

You can do this yourself using the following approach:

func ToX500Name(asn1Name []byte) (string, error) {
	var name pkix.RDNSequence

	rest, err := asn1.Unmarshal(asn1Name, &name)
	if err != nil {
		return "", errors.Wrap(err, "Failed to decode X500 name")
	} else if len(rest) > 0 {
		return "", fmt.Errorf("remaining bytes after decoding name (len: %d)", len(rest))
	}

	return name.String(), nil
}

func MyTest () {
	pemCert := ` YOUR PEM CERT HERE `
	block, _ := pem.Decode([]byte(pemCert))
	cert, _ := x509.ParseCertificate(block.Bytes)

	name, err := ToX500Name(cert.RawSubject)
}

@Steve973
Copy link

I wholeheartedly agree that the subject DN should remain wholly unaltered. If necessary, provide methods to convert it for people who want different formats, but why alter what is actually in the certificate? That makes Go strongly opinionated on the subject, as if Go is presuming to correct what various CAs are doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

4 participants