27 comments

[ 3.0 ms ] story [ 72.0 ms ] thread
Sort of related, one of the best resources I've used that helped me understand much more is this doc:

https://jamielinux.com/docs/openssl-certificate-authority/

It hasn't been updated for Subject Alternative Names or EC keys, but it's sort of like a Linux From Scratch for SSL CA ops that can help you understand what tools like smallstep-cli are doing behind the scenes.

My greatest pain with certificates and especially the X509 standard is that it‘s so large / loosely designed, it‘s hard to call it a standard at all. X509 is more of a bucket you can almost drop anything in.

Perhaps my greatest grievance is that it’s a leaky abstraction by design. There are small to huge differences between different CA vendors, SSL implementations and the internal DER/Asn1 structures they emit. This also includes key encodings.

Error codes are incredibly opaque. Ever tried parsing a wrapped SPKI key with Ring/BoringSSL? It crashes with „Wrong Tag“ and incromprehensible letter soup. OpenSSL‘s Base64 toolset only works with aligned/padded input and a specific alphabet. Try inputting non-padded data, all you get is „Error“. That‘s it. Incredible.

Does this SSL implementation expect raw SubjectPublicKeyInfo, or can it accept Keys with additional headers? Can I trust that extended attributes are handled correctly? OpenSSL just emits „some“ DER here, while BoringSSL expects my public key to be of „ECDSA__ASN1“ format - or was it „ ECDSA__FIXED“? I have embedded devices that use MbedTLS or WolfSSl, Rust backend servers which depend on Ring/BoringSSL, Users which want to use OpenSSL EE certs and a public CA which could use any of these. How the hell do I generate certificates and keys in a way they all understand?

I don‘t know, and neither do you.

It‘s all a massive headache.

X509 certs are more or less interoperable as seen everyday on the Internet where your HTTPS sites mostly work. Keys are another matter (and a private one at that).
That's because some people came along and produced a parallel standard [1] adding loads more rules, clarifications and constraints to convert X509 into something approximately fit for purpose.

[1] https://github.com/cabforum/servercert

That's mostly only if you use them for HTTPS/SSL. There are many more uses for certificates, like signing payloads via JWS/Jose, CWS or CMS/PKCS7.
X.509 isn't used for JWTs?
JSON Web Keys include (optional) X.509-related properties but don't necessarily use X.509 for anything. X.509 isn't used in JWT signing or really with any part of a JWT.
You can deliver x5c certificates that need to have been signed by the same public key as the token signature.
> How the hell do I generate certificates and keys in a way they all understand?

When we built Python Cryptography's X.509 validator[1], we also built an entire test suite that compares different implementations for RFC 5280/CABF compliance for exactly this purpose[2]. It's already found a decent number of bugs (both public and non-public) in widely used implementations; you may find it useful!

(I agree that X.509's constellation of standards are a mess. But I also think a huge part of the mess in practice is implementations trying to do too much: if all you need is to verify client/server chains in the Web PKI, then "all" you need is CABF. There's no point in implementing RFC 3280, etc.)

[1]: https://blog.trailofbits.com/2024/01/25/we-build-x-509-chain...

[2]: https://x509-limbo.com/

That is very nice work. Thank you so much! One thing I would be interested in is if there were any differences between rust-webpki and BoringSSL itself.

Also, I would love if MbedTLS or WolfSSL would also be compared. However, their state is in itself a bit questionable.

> One thing I would be interested in is if there were any differences between rust-webpki and BoringSSL itself.

Adding BoringSSL as a harness would probably be pretty easy! We have an existing OpenSSL harness[1] that would probably be straightforward to adapt.

We could also probably improve the visualization of differences between implementations: right now you can find them either by looking at individual testcases[2] or on each harness's "anomalies" page[3], but it'd be cool to have a more unified UI.

[1]: https://github.com/C2SP/x509-limbo/blob/main/harness/openssl...

[2]: https://x509-limbo.com/testcases/rfc5280/#rfc5280akileaf-mis...

[3]: https://x509-limbo.com/anomalous-results/rust-webpki/

> My greatest pain with certificates and especially the X509 standard is that it‘s so large / loosely designed, it‘s hard to call it a standard at all. X509 is more of a bucket you can almost drop anything in.

I recently wrote a blog post[1] about the limits of TLS certs and from what I understood of X.509 is more of a framework and standards or applications can use it to define their certificates such as RFC 5280[2] which is the standard that defines their usage on the Internet.

[1] https://0x00.cl/blog/2024/exploring-tls-certs/

[2] https://www.rfc-editor.org/rfc/rfc5280

The "What Problem Do Certificates Solve" paragraph is a little bit confusing. The role of a certificate is to ensure integrity and confidentiality of communications between two hosts. The "making sure the certificate holder is who they claim" part is the role of the CA authority hierarchy, which interestingly is a system based on some hard math but also mostly on trust, authority, and everyone's ability to keep keys private.
As a total newcomer expecting to have the use of certificates explained, that section lost me at this point:

> However, the hacker somehow obtains a certificate issued to super-bank.com

If the article is to explain the use, it might be good to explain first what they are. As it immediately circularly referenced certificates as if they're a concept the reader already understands, I couldn't learn anything from it.

Don't worry, several sections in, after couple of (clumsy) metaphors trying to explain what certificates are for, the author suddenly remembers that:

> To Themselves: Protect the private key of their root certificate.

Oh, there are also keys! Apparently, private (but maybe also public).

I, too, find this explanation to be poorly thought out. I generally don't like it when an explanation has to resort to metaphors in order to explain something: it usually generates more questions as to the extent of the applicability of the metaphor.

----

While I do have to use certificates in less trivial ways than just firing up the browser, I cannot comprehend some design choices that went into building this contraption. Not to mention the abysmal quality of the libraries implementing the relevant functions as well as abysmal quality of documentation to accompany it.

I'm not expert enough to point to the exact problems, or offer better solutions though...

No, the role of a certificate is to certify that a given entity is the owner of the private key associated withe the public key you see. Its role is similar to an ID card (which certifies that the pictured person is the one named on the card).

You don’t need certificates to ensure the integrity and confidentiality of communication. Cryptographic keys alone already do that job. What certificates do is ensure that the peer you’re confidentially exchanging integrity-assured messages with is really the one you think it is, based on a third party (the CA) whose key you already trust.

As a physical-world analogy: A sealed envelope ensures the integrity and confidentiality of a letter. But it doesn’t tell you who really sent the letter. If, however, the seal (think of a wax seal) was made with a stamp, and you have a government document (certificate) that tells you that this stamp belongs to person X, then you have assurance about who sent the letter.

My "issue" with X509 is that it's hard to create certificates in code. I have not seen a single software package I use do it from scratch. They always use a library.

The X509 library functions in openssl is horrific, with plenty of opportunities to mess up.

It's a paradox that something that is designed to improve security is designed in a way that make it extremely hard to implement it in a clean and secure manner.

Not “from scratch”, but the Go standard library contains very easy-to-use functions around requests, certificates, keys and CRLs. OpenSSL is a different story of course and it is unfortunate that so many ecosystems just wrap it.
(comment deleted)
The DNS system is overly complicated IMO.

I've actually come to like the idea of zone files with different record types like A records, CNAME, etc... but the architecture is too complicated and centralised.

With replication and caching, you can scale to unlimited reads. That's good. But the writes require trusting a small number of centralised entities.

It would be best implemented as a Blockchain. Then you would get unlimited scalability in terms of reads and there would be no complex cache hierarchy because every node is an equal replication. No single node requires special privileges. You just pay the Blockchain transaction fee to buy and sell domains and you just pay to the block forgers/miners... Which can be anyone.... So there is need to trust authorities. It would all be market based.

Blockchain data is fully public and cryptographically verifiable so it's an ideal match for this use case. Also, you could actually own your domain names without expiry instead of having to pay some rent-seeking organization every year or so.

Isn't it crazy that it's not possible to actually own a domain name? You'd think some big tech company would lobby for that... Surely worth having extra guarantees...

So when i want to point a record at a new ip i just have to pay some miners an unknown amount of money and wait and unknown amount of time?
The time is known. You can get an instant transaction so long as you're willing to pay enough. The amount of money it costs depends on the popularity of the Blockchain/gTLD.

A more popular gTLD would cost more than a less popular one... Just like buying real estate in a popular area costs more than real estate in the middle of nowhere.

How is any of that unreasonable?

I’m not gonna pay some sum approaching infinity to ensure that the record appears at a time span approaching instantaneously. I’m gonna pay like fucking whatever a buck and then wait out the fuck long who knows
This was wonderful, thank you! The certificate chain was one of my blind spots and this could not have come at a more ideal time since I am debugging TLS cert issues.