4 ms·
Came here to say this. Please don't use PKIX, ASN.1, and Base64-of-DER-without-PEM-headers for Ed25519. Those are all extra complexity from protocols that were
by FiloSottile 5y ago
Came here to say this. Please don't use PKIX, ASN.1, and Base64-of-DER-without-PEM-headers for Ed25519. Those are all extra complexity from protocols that were misguidedly built with runtime agility, or from a different time in cryptography engineering in which we really felt the need to put dynamic types on everything. [0][1]
An Ed25519 public key is a 32 bytes sequence. An Ed25519 private key (called seed in crypto/ed25519 for unfortunate historical standardization reasons) is a 32 byte sequence. That's it.
Here they are encoded in Base64.
public key: 5uW7anEGF1nIjGfp5pS2kiN0cn2mGYkuSa+TCBoFIbQ=
private key: shhKyGTvTeLjXGDCjEQgHRA7ps3LRNNfoO5S714kinU=
age [2] similarly uses Curve25519 keys encoded with Bech32 to make them easier to copy-paste and read aloud. Look how nice they look compared to PKIX blobs!
$ age-keygen
# created: 2021-04-23T12:31:14-04:00
# public key: age1gek0nrawzg9fhkrzcmt4ql7au0n6hwflz7lqqc8wwcvefn2vssgsa4uulp
AGE-SECRET-KEY-19JFPFAY2DF3HJP5DFGVSY4A4G4YSRHG4ZCJMKNC5MFD9C9ZN5LCSG8VTDL
I'll think about how to make the crypto/ed25519 godoc point people in the right direction once Go 1.17 enters feature freeze.
[0] https://www.imperialviolet.org/2016/05/16/agility.html https://www.imperialviolet.org/2016/05/16/agility.html
[1] https://buttondown.email/cryptography-dispatches/archive/cryptography-dispatches-registries-considered/ https://buttondown.email/cryptography-dispatches/archive/cry...
[2] https://github.com/FiloSottile/age https://github.com/FiloSottile/age
- timbray 5y agoThis makes sense, but if I'm handing these things around probably some of the code [gasp] isn't in Go. So someone should write an RFC for the case where you don't need algorithm agility, and then devs don't need to know or care in the slightest what 25519 keys actually are, they just need to call APIs to serialize & deserialize them.
- FiloSottile 5y agoI'd argue the RFC is already there and it's RFC 8032, which defines "32 bytes string" <-> "public key" and "32 bytes string" <-> "private key" APIs. Then you can use your preferred format to serialize a 32 bytes string if you need a text-safe encoding. (If you don't you're done!) For example, you can use RFC 4648. I am positive every language has Base64 code, and if there's an Ed25519 library out there that can't accept 32 byte strings we should talk to the author because it's broken as it doesn't implement RFC 8032. What else would a serialization RFC say, that is not already said in RFC 8032? Deciding that keys are encoded with Base64 and not with, say, hex seems like a weird thing to force on people.
- timbray 5y agoReally?! I read 8032 because people told me I should and all the strings in there are bit or octet strings, anyone looking for textual serialization is going to come up empty. Also 8032 is way too heavyweight for mere mortals. Also bear in mind that lots of languages aren't as transparent as Go and their devs, given something purporting to be a public key, aren't going to look inside, they're just going to ask "where's the API to serialize/deserialize this so I can post it on the Web?" So yeah, I agree it would be a short RFC, but once it existed, people would arrange for those APIs to exist.
- FiloSottile 5y agoI think we might have different ideas of the purpose of RFCs, but I don't expect end users to read them. What I'm saying is that RFC 8032 already defines a binary encoding for Ed25519 keys (the octet strings you've found). How to encode a binary string in text is IMHO orthogonal, and has nothing to do with Ed25519. Similarly, PKIX definex binary DER encodings, and PEM defines how to encode DER as text. DER : PEM = Ed25519 binary encoding : Base64
- tialaramex 5y agoAdam's post about agility is a good read, but it's worth remembering that it makes a prediction which did not in fact come true. > When we try to add a fourth (TLS 1.3) in the next year, we'll have to add back the workaround, no doubt. Adam is talking about the unsafe downgrade fallback, traditionally done by web browsers, not so long ago even falling back to SSLv3 which was long obsolete. But in fact today, if your web browser connects to a remote server proposing TLS 1.3 and the remote server just silently drops the connection because it can't conceive of such a thing, the browser goes "Huh, I guess TLS doesn't work on that server" not "Let's try again with TLS 1.2" because the design in TLS 1.3 actually works, even if getting there was a heroic effort. A compliant TLS 1.2 server will do TLS 1.2, and sufficiently non-compliant ones just break and are now presumably very rare.