Finishing off the week strong with some recycled content on RSA and EC (as in I actually wrote this before, then re-appropriated and post-dated it):

If you're here (which you are), hopefully you knew enough when you were googling to know that we're talking about asymmetric encryption that's used in OpenSSH, OpenSSL, WebCrypto, and available in just about every programming language.

Here's the TL;DR for the impatient:

  • Both are equally secure (for all existing known mathematics)
  • EC has smaller keys, faster keygen, but slower sign/verify (and encrypt/decrypt)
  • RSA has much larger keys, much slower keygen, but faster sign/verify (and encrypt/decrypt)
  • Both only really use encrypt/decrypt to handshake AES keys (so it's always fast enough)

RSA vs EC

This is what I consider to be a pragmatic and pratical overview of today's two most popular (and worthwhile) encryption standards.

I don't find the nitty-gritty details to be of much value, but I do consider it important to know that there are tradeoffs in choosing between the two.

RSA

RSA deals with prime numbers* - and very few numbers are prime!

So even though the entropy is said to be 2048-bit**, it's really only about 256-bit.

That is to say that if you could somehow limit the key space to a known list of prime numbers, guessing which prime number was used would still be impossibly hard, and all the stuff about how many quadrillions of years it would take to guess the right one still has some validity.

RSA keys are slow to generate, taking between several seconds (a fast desktop computer with a native-C implementation - like node now has) and several, or even dozens, of minutes (like a Raspberry PI Zero, or a slow computer with a pure javascript implementation) - hence it's such great news that we now have native RSA generation in node!

The upside is that signing and verifying keys, once they've been generated, is pretty fast (something you can do hundreds of times within seconds).

* Technically they're "probable primes" since it can be inordinately expensive to determine that something is a true prime and sufficiently large almost-primes are just as good as perfect primes for practical purposes, but that's really another topic entirely.

** Fun fact: the leading byte seems to always match the bitmask 0x90 (for ssh-keygen at least that's certainly true), so it would really only be 2046 bits of keyspace).

EC

EC/ECDSA* deals with elliptic curves. I'm not as well versed with the math behind this as I am with the RSA, but my understanding is that it works on the principle that when you have a curves on a graph, you're functions aren't as simple as "put x in, get y out" (the types of functions you learn in high-school).

With EC keys, basically any random 256-bit number is a valid key, so there's near-0 cost to generating a keypair. This is much nicer than RSA.

The downside, however, is that signing and verifying are much slower - something that you might measure in dozens of times within seconds in a modern browser using pure js.

That said, since they're so much smaller, they're ideal when a key needs to fit into a DNS record, or you want to reduce download size on TLS certificates or upload size of Authentication headers when using JWTs. They're also the basis of most b****chains (a dirty word in my book).

*To eliminate confusion: you'll often see EC and ECDSA used interchangeably.

DSA means "Digital Signing Algorithm", so in many cases saying "ECDSA" is redundant - just like saying "PIN number" or "DVD video" - and so the "DSA" just gets dropped.

Conversely, in other contexts you're technically not dealing with DSA (such as ECDH), so its obviously not used there either.

In reality, however, the keys described, themselves, are the same despite how they're used.

Configuration Options

Over at Native RSA and ECDSA lands in node.js I make my case that there's literally no use in tweaking your RSA public exponent, nor your RSA or EC keysize. 2048-bit RSA and EC P-256 are already overkill (read: sufficient) and unless you know that you actually need a more CPU intensive (read: expensive) variety, don't complicate things or waste your users' battery life.

Conclusion

To me, these are the most important things to know in order to decide which to use when.

Generally speaking, the web prefers EC keys these days (and so do I).

SPKI, PKCS#8, PKCS#1, sec1, PEM, and DER!
Oh My! (Bonus)

Whenever you're doing key generation you almost always have some options for the format of the key avaible, so I figure I'd mention that here as well:

spki is the normal, run-of-the-mill format for public keys. You should use this unless you have a specific need to use pkcs1 (RSA only).

pkcs8 is the standard format for private keys, even passphrase-protected encrypted ones (which we'll I touch on in Native RSA and ECDSA lands in node.js). Again, unless you specifically need pkcs1 (RSA only) or sec1 (ECDSA only), use this.

PEM is simply the ascii version DER. PEM is base64-encoded with a simple header and footer while DER is pure binary. They both represent ASN1-encoded data. You can think of ASN1 almost like an ancient binary form of JSON where spki and pkcs8 are schemas (defining mundane stuff like whether to call a field firstname or FirstName or firstName - you know the drill).

If you want to dive a bit deeper into the bits and bolts of all of that, I'd say check out ASN.1 for Dummies too.

What it looks like in practice

Although the examples are specific to node.js, a great next step would be to read Native RSA and ECDSA lands in node.js.

I think you'd get a fair bit of value out of that.


By AJ ONeal

If you loved this and want more like it, sign up!


Did I make your day?
Buy me a coffeeBuy me a coffee  

(you can learn about the bigger picture I'm working towards on my patreon page )