agwa
2 hours ago
The blog post provides a certificate chain that validates in OpenSSL but not in Go.
The reason it doesn't validate in Go is that the Subject field in the CA certificate uses a different string encoding than the Issuer field in the leaf certificate, so the fields are not byte-for-byte equal.
Go requires the Issuer and Subject to be byte-for-byte equal. This was permitted by older specs, but RFC 5280 changed the rules to require the use of RFC 4518 (LDAP stringprep) for comparing strings. This turned a simple memcmp into a complicated algorithm that requires implementing Unicode normalization, for virtually zero benefit. That's the last thing you want in your security-critical certificate verifier, so Go quite sensibly chose to follow the older specs in this regard. The CA/Browser Forum's Baseline Requirements also mandate byte-for-byte equality, so Go's behavior won't cause publicly-trusted certificates to be incorrectly rejected.
Note that LDAP stringprep is so complicated that OpenSSL doesn't even try to implement it properly and uses an approximation instead. So you would also be able to "fool" OpenSSL into rejecting certificate chains that RFC 5280 says are valid.
The blog post says that this is an "ongoing debate" in the Go project but I don't think that's accurate. I'd be shocked if they ever changed this behavior, given that crypto/x509 targets publicly-trusted certificates and the current behavior is so much simpler.
tptacek
2 hours ago
I feel like basically all the X509 threads on HN should basically be locked until after you write your first comment on them.
agwa
36 minutes ago
Aw, thanks :-)
tialaramex
an hour ago
Yeah, no, Andrew has insightful things to say, but he's hardly indispensable.
jiggawatts
2 hours ago
Something I noticed decades ago is that some small, innocuous features can drag with them giant ecosystems of software.
I first noticed this when I had to implement a C++ client for a custom RPC protocol and the dev “on the other end of the wire” added one new “convenience” in the data types supported… which would have required me to include the entire Java runtime in my client!
All protocol specs are vulnerable to this effect where it’s all too easy to require clients to include half a dozen different regex engines, three byte code virtual machines, and most of LLVM for good measure.
sidewndr46
40 minutes ago
any specification eventually grows to encompass all features of its original implementation language.
PunchyHamster
3 minutes ago
We should require 2 different implementation, each in different enough (so no C/C++ pair) language with each specification.
Because that way we not only get rid of language's smell in how stuff is implemented, but also the act of implementing the spec will quickly show any cases where it looked simple in spec but turns out to be mess implementation wise.
Too much work ? Well, make your spec be tighter and simpler before you burden the rest of programming community with implementing it