RSA is a fragile cryptosystem
blog.trailofbits.com
blog.trailofbits.com
If this is article is "easy" crypto, and I shouldn't roll my own crypto, then what should I do? "Just use elliptic curve crypto but make sure you choose the right curve! Here's an abbreviation for you, libsodium has it so you're all set" doesn't comfort me much. I don't have a good intuition of what a curve even is and why my sensitive data can't just go straight ahead like all the other data. I mean, when I call into libsodium with parameters I do not understand, then aren't I, for all intents and purposes, rolling my own crypto anyway? How is any of this of help?
If I want to allow my customers to send me encrypted data via an untrusted channel, then what do I do? I need public key crypto for that, right? Basically, I want the public key cryptography version of Coda Hale's classic blog post about password hashing [0], does that exist?
EDIT: thanks for all the comments folks, great insights! I particularly found [1] by CiPHPerCoder to be a great starting point (akin to Coda's password article) for all kinds of scenarios. I feel much more confident about this stuff now than I did 2 hours ago.
[0] https://codahale.com/how-to-safely-store-a-password/
[1] https://paragonie.com/blog/2017/06/libsodium-quick-reference...
(What's never trivial is key management, how do you get Alice's public key, but that's hard with any sort of public key cryptography.)
# Generate Bob's private key, which must be kept secret
skbob = PrivateKey.generate()
# Bob's public key, and similarly for Alice...
pkbob = skbob.public_key
# Bob wishes to send Alice an encrypted message so Bob must make a Box with
# his private key and Alice's public key
bob_box = Box(skbob, pkalice)
# This is our message to send (binary blob of data)
message = b"Kill all humans"
# Encrypt our message
encrypted = bob_box.encrypt(message)
[1] https://pynacl.readthedocs.io/en/stable/public/The difficulty you are describing assumes a user base of crypography pedants who make assumptions about third parties that don't matter to 99% of non-technical users (nor even technical users in many cases).
Oh god but how do you ask her without a guarantee that she's really who said yes?
Even if you meet Alice in real life to ask, how can you be sure the meeting isn't a dream or a simulation and the Alice before your eyes isn't a chosen plaintext attack by a cosmic man in the middle?!
The entire science of cybersecurity is bankrupt and founded upon untenable foundations!!
The point of the article is all the ways RSA blows up. libsodium addresses that style of problem. Saying there are other problems ("how do we agree on a key") may be true, but isn't responsive to the discussion.
Same goes with crypto. It's fine to learn the concepts of how to use a trusted library, but you really aren't likely going to understand the underlying tradeoffs and mathematics.
People here aren't just saying "just use product X", they're saying, "learn the concepts of product X and use that". That's about as good as it's going to get for any specialized, complicated domain.
Yes, of course it is. Doctors know a lot, but they're not competent to assess the pharmaceutical literature.
So here's how it works. In med school, drug manufacturers provide free equipment, food, liquor, etc. And push their drugs. Because once you have someone in the habit of prescribing some drug, they tend to keep prescribing that drug.
Also, you pay influential doctors to deliver talks at conferences, praising your drug(s). You also pay ghostwriters to draft papers, which said influential doctors can submit for publication.
And last, you pay sexy, charismatic young things (of both sexes) to visit doctors' offices, pushing your drugs, and giving away food and stuff.
When someone says something that doesn’t make sense to you, do you just put whatever they’ve handed you into your mouth without asking questions?
On the other hand, getting crypto advice from random bloggers and HN commenters is akin to getting a medical treatment plan and drugs from random bloggers and HN commenters.
To be honest, this is literally the level of discourse of most Hacker News discussions about healthcare.
Unfortunately Coda Hale's post makes a bunch of assumptions. Reasonable assumptions for a lot of the audience, but they're still assumptions. So an equivalent post has to either make equally broad assumptions OR it has to ask you a bunch of questions.
Not crypto questions, but just questions about what you actually want to achieve by having public key crypto. That's going to dictate what you should do. In particular Public Key crypto almost invariably ends up with questions about Identity because of the Public Keys, how do I know this is Bob's Public Key? Do I care about that? Who is "Bob" anyway?
Example #1: For a Web Browser the answer is Identity means the Internet DNS hierarchy decides what hosts are named, the Web PKI provides us with an Authority that says this public key belongs to news.ycombinator.com. It's up to the end user to decide whether that's Hacker News or the Disney Company.
Example #2: For Signal the answer is that Identity is defined only locally by a user's own "address book" or similar features and they get to decide whether this contact is really "Dad" or "skrebbel" or "Jenny Smith", Signal promises to tell you if "Dad" doesn't have the same public key any more (which is suspicious), but paternity tests or verifying in person that "Dad" isn't just a proxy are your problem.
If in fact you "want to allow my customers to send me encrypted data via an untrusted channel" in 2019 you should just set up a secure Web Server, with a Fully Qualified Domain Name your customers know (e.g. write it on business cards, or the sides of vans, or a huge building) with a form on it, where they can submit things. Done. Choose a web server you like and go look at Mozilla's instructions for securing Web Servers.
I believe you're talking about:
https://wiki.mozilla.org/Security/Server_Side_TLS and/or https://infosec.mozilla.org/guidelines/web_security
That assumes the customer's browser is trusted, and not configured to silently allow all encrypted connections to be intercepted, decrypted and potentially modified by someone else in the network, which is unfortunately still too common.
That just means someone else on the network securely sent you stuff...
From the article:
> The most important thing to keep in mind about cryptographic key sizes in 2019 is they don't matter nearly as much as the general public likes to think.
:P
The "general public" I'm referring to is the set of people who aren't cryptography protocol designers.
Also, this[1] article helped me visualize how ECC works. It's a great read.
[1]: https://arstechnica.com/information-technology/2013/10/a-rel...
To answer your specific comments: firstly, you don't need public key crypto. If both you and your sender can agree on a secret key, you can use secret key crypto just fine. For that, use libsodium's secretbox.
If you really need public key crypto for some reason, libsodium's box is what you want.
What's the "untrusted channel" here? Is this really about encryption in transit, or encryption at rest?
(For everyone else: just because I'm playing along with this misissuance scenario doesn't mean I don't think ~everyone should trust WebPKI.)
> that’s much safer than using public key cryptography.
It's much harder to screw up than using PKC (thereby making it safer). It's something that is really important for UX - you want to make the easiest path the safest path.
Mail is another option, depending on how secure you think that is.
However, just because you have a channel that can't be MitM-ed doesn't mean you can actually trust whoever is on the other end. The problem of "how do you know you trust the other end" requires some foundational source of trust, whether that's trusting the transportation medium (that the person you handed the USB key to is actually who he/she claims to be), the issuer (could be yourself), and so on.
Considering it took me 8 months to not even finish my own, making several serious mistakes in the process, even though I wrote my own goddamn crypto library and am standing on Noise's shoulders…
I tend to agree.
That said, we still have a problem: `crypto_box()` is nice, but it doesn't have any kind of forward secrecy, identity hiding, or key compromise impersonation resistance. Sure, offline protocols can't really have that (the best you can do is use signatures to avoid the key compromise impersonation issue, but then you loose some deniability). Online protocols however, can.
But then what do we do? We could use Noise, (the Noise explorer now generates code in several languages), but you at least have to chose a pattern. Which one? How can you even notice that XK1 maximises client anonymity, and IX (properly used) maximises server security? Even if you know that, which are you going to use?
And I'm not even talking about implementing your Noise pattern, should existing implementations not suffice (maybe you want to leverage a custom crypto library optimised for some embedded processor). Noise isn't simple. A serious drawback in my opinion.
This, if I guess correctly, is what led you to recommend that horror that is TLS for client/server security. Because the burden of choosing a reasonable TLS library, of properly configuring that TLS library to only use TLS 1.3 with a limited set of ciphers (possibly just Curve25519 and ChaPoly)… still remains less error prone than picking up a Noise protocol. <PKI matters conveniently left out>
That situation is deeply unsatisfactory. It's all well and good to tell people "don't make your own kex", but if you don't at the same time point them to an existing kex, they will be less likely to follow your advice. I mean, I didn't.
1. Computing secret keys. Inside your program, to generate a 32-byte Curve25519 secret key, start by generating 32 secret random bytes from a cryptographically safe source: mysecret[0], mysecret[1], ..., mysecret[31]. Then do
mysecret[0] &= 248;
mysecret[31] &= 127;
mysecret[31] |= 64;
to create a 32-byte Curve25519 secret key mysecret[0], mysecret[1], ..., mysecret[31].2. Computing public keys. To generate the corresponding 32-byte Curve25519 public key mypublic[0], mypublic[1], ..., mypublic[31], call
curve25519(mypublic,mysecret,basepoint);
where the constant basepoint is 9 followed by all zeros: const unsigned char basepoint[32] = {9};
3. Computing shared secrets. Given someone else's Curve25519 public key hispublic[0], hispublic[1], ..., hispublic[31], call curve25519(shared,mysecret,hispublic);
Done, you've just got a shared secret. Then you can use standard tools like OpenSSL or "gpg --symmetric" to encrypt the data using AES with that key.But seriously, just use libsodium. It has received extensive audits, its abstraction model is easy to use and understand, while mistakes are hard to make.
I mean the first hit starts with this sentence: "Ed25519 keys can be converted to X25519 keys, so that the same key pair can be used both for authenticated encryption (crypto_box) and for signatures (crypto_sign)."
I have no idea what do to next.
The first example shows both sides of the communication. The public keys are shared (but you want to make sure that you have the correct one, for example by meeting the recipient in person and comparing the keys). The library defaults in libsodium are already chosen to be secure (using Curve25519 and secure algorithms).
Assuming you're a C-programmer, read the libsodium docs first. https://download.libsodium.org/doc/public-key_cryptography/s...
If you're using higher level language, use a library that provides bindings for it https://download.libsodium.org/doc/bindings_for_other_langua...
By using libsodium, you're not rolling your own crypto. Rolling your own crypto would mean
-trying to find new one way functions for public key crypto -trying to implement RSA from textbook -trying to implement RSA-OAEP from papers, RFCs, books etc.
Using a library is not anywhere near those. There are other ways to fail cryptography too, from not doing public key authentication, to storing private keys in insecure places.
So it's highly recommended you take time to read a book on the topic. The best modern book currently availalbe is https://www.amazon.com/Serious-Cryptography-Practical-Introd...
That's debatable. Libsodium does not have a proper authenticated key exchange. The key exchange does the job somewhat, but it has worse security properties than a properly crafted interactive protocol.
Problem is, designing your own key exchange protocol is more delicate than most construction. I know, I designed my own, and made several serious mistakes in the process (one of which voided an important security property).
Granted, rolling your own constructions is generally less error prone than rolling your own primitive. But it still shouldn't be done without at least having followed and fully understood an introductory course in cryptography (I recommend https://www.crypto101.io/). I mean, I did quite a bit more than that, and I still don't fully trust myself.
There are still some dangerous things you can do (e.g. mismanage keys, reuse nonces).
I wrote a library called Halite for PHP developers that wraps libsodium and makes it even harder to misuse. My philosophy was, "You shouldn't even need to know what a nonce is to use it securely."
https://github.com/paragonie/halite
From elsewhere in the thread, PyNaCl takes a similar approach. So how dangerous "just using libsodium" is, with respect to the "don't roll your own crypto" guidance, depends a little bit on which binding you're using.
Also, a lot of tasks might require a specific protocol (PAKEs, VPN protocols, searchable encryption, etc.) that libsodium isn't suitable for.
I wish I were a little better at SEO so average nerds would have an easy time finding it.
My only SEO advice is patience. Your articles are great, people will link to it increasingly often.
That said, why the sole PHP focus? The starting point you just linked to is pretty much independent from PHP, and there's libsodium bindings in plenty languages. If your goal is simply to make good crypto easier to do for "normal" developers then the PHP association may do more harm than good (particularly because PHP is not very hip right now)
I authored Crypto 101. One of my cofounders co-authored Cryptopals and founded the cryptographic practice at Matasano (as well as co-founding Matasano itself ;)). So for cryptographic engineering, I think the answer is "historically oral, and increasingly written, tradition"?
A random person on the internet advising which curve to use (which I don't even know what that is) can be insecure as well.
And even if it's a secure choose now it may not be in a few years.
First, the advise does not come from "a random person".
* The recommendation of Curve25519 is originally concluded by its author after evaluating all available elliptic-curve standards under a set of well-defined, objective criteria. The research is published here [0].
* It's not an one-man's claim. This conclusion has been peer-reviewed by many leading researchers and institutions in the past 10 years. There have been enormous amount of discussions made in various communities, including cryptographic developers working on community projects, like OpenBSD [1], OpenSSH [2], Tor [3], industry leaders such as Apple [4], Google [5], Microsoft [6], CloudFlare [7], as well as Internet institutions such as IETF [7], now it's officially part of TLSv1.3.
Nearly everyone agreed the security claims by Curve25519 is valid and it offers many desirable properties compared to previous standards.
> And even if it's a secure choose now it may not be in a few years.
The theoretical security margin is comparable to any other 256-bit ECC encryption, yet it offers a more conservative and robust design against known attacks than other curves, including a good complex-multiplication field discriminant D against potential speedups to Rho Method, immunity against invalid-curve attack, indistinguishability from uniform random strings, and allowing easier, more robust implementations of constant-time (anti side-channel) addition and multiplication.
In other words, in theoretical cryptography, there is no known, computationally-feasible way to attack it. Perhaps in the future someone could find a way, but ECC has been thoroughly analyzed in the past 20 years and it's reasonable to believe a major weakness is very unlikely. "You cannot be sure that it cannot be attacked in the future" is not valid logic in applied cryptography. The valid logic is "You only choose something with a high-level of confidence".
Currently, the only way to attack is using a quantum computer, but when they come, all the public-key algorithms deployed on the Internet are vulnerable without exceptions (it has been claimed that ECC needs fewer qubits to crack than RSA, that's true. But when quantum computers are large enough to attack ECC, attacking RSA is only a matter of time in the short-term. Giving up ECC entirely today and facing all the potential problems of RSA with long keys for 10-20 years, just to buy a few years of time from quantum attackers is a very questionable sacrifice). Therefore, the research on Post-Quantum Cryptography has already started [8], with possible candidates like McEliece and NTRU. They are expected to replace current standard in the next decade.
> which I don't even know what that is
WE DO NOT CELEBRATE IGNORANCE.
References:
[0] https://safecurves.cr.yp.to/
[1] http://www.openbsd.org/papers/bsdcan-signify.html
[2] https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-08
[3] https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt?...
[4] https://www.apple.com/business/docs/iOS_Security_Guide.pdf
[5] https://www.chromestatus.com/feature/5682529109540864
[6] https://www.microsoft.com/en-us/research/wp-content/uploads/...
And even then if you found good solid well supported security advice from reputable sources but they are 10 years old... You are still insecure.
Therefore modern up to date information from reputable sources is the only true way to stay secure. Its a running battle not a static one.
I feel you have assumed I meant something entirely different.
There are multiple ways to "send encrypted data via an untrusted channel", none of which is perfect, but by descending order of ease of installation and use I would propose this:
- Use Signal or Wire to send that data through messages
- Use Keybase
- Setup an HTTPS server (the default configuration of caddy (https://caddyserver.com/) is good enough)
- Use the "box" function from NaCl, or libsodium, or Go's reimplementation. Those are all libraries, so it will require actual coding. But those libraries are all made so that misuse is very hard, and you don't need to know or even understand how the crypto works to be able to use it
X25519, Ed25519, XSalsa20-Poly1305--you just minimized your footguns.
Unless you have a different library accessible, use TweetNaCl or one of its wrappers--now you've minimized your library footguns: https://tweetnacl.cr.yp.to/
If the operation you want to do isn't part of that library, you need to ask yourself: "Do I truly understand the security implications of what I am try to do?" And then not do it.
There are still lots of implementation footguns (leaking values in memory, side channel attacks, etc.), but those 2 choices put you so far ahead of the pack that your can probably survive until you have enough money to actually pay a cryptographer to come review your stuff.
I'd suggest ChaCha20-Poly1305 in the AEAD construction defined in RFC 7539[1] (which is what most new libraries implement). ChaCha20 is more performant and these days is more widely used -- though the underlying construction is very similar and both were designed by Bernstein et al.
> If this is article is "easy" crypto,
This article isn’t “easy” crypto. If you expect to understand it, you should already understand how (mathematically) RSA works.
The consensus of not doing your own crypto is decades old at this point and still good advice but also a bit of a cliche. I don't come across a whole lot of projects actually doing their own algorithms. The opposite actually. People just blindly copy paste dependencies and code they think is good enough.
Despite the tone of the article (and its length), the advice is actually sound. RSA has been around quite long; can be quite complicated to deal with when integrating and definitely has a few pitfalls; mainly because it leaves a lot of things as an exercise to the developer and thus plenty of room to do it wrong.
I recently came across ECC and the curve they recommend in the article in Stellar (which uses it) and had to write a bit of code to figure out how to work with keys; this turned out to be very easy. What I like here is that from a developer point of view there's not a lot to configure here and when you use it as a black box that's a good thing. Basically key generation is generating a single random number. Which of course you should do using a secure random generator. You then calculate the public key from this secret. End of story. You probably want some tests around this to verify that you can work with some known key but this basically either works or doesn't.
The only thing I found slightly worrying was the lack of standard/commonly used implementations for different languages. For example, the Stellar Java SDK for stellar pulls in a library (net.i2p.crypto:eddsa) from the i2p project in version 0.3.0. I actually fixed a minor bug at some point to at least get rid of a fork of this that they were using but this suggests to me that there might be some issues lurking out there with not so great implementations.
The discussion for the relevant ticket to implement this in OpenJDK suggests that there are some not so trivial aspects to a proper implementation: https://openjdk.java.net/jeps/324. This only landed in v11. If you are targeting e.g. Android (like Stellar is), you'd need some third party implementation.
I've looked around and there are a few alternate implementations at this point for java and other languages but nothing that I would consider very mainstream yet. So, ECC curve 25519 looks easy to use but the implementations are all over the place in terms of maturity. That in itself should still be considered a red flag and sort of goes against the advice of not rolling your own crypto; which is effectively what you are doing when pulling in other people's libraries in really early versions.
Curve25519 for 128-bit security, to use with 128/256-bit symmetric cipher.
X448 for 224-bit security to use with 256-bit symmetric cipher.
-
For symmetric ciphers choose any of the three below:
-ChaCha20-Poly1305
-Salsa20-Poly1305
-AES-GCM.
This includes some attacks that I don't think really ever occur in the real world (bad private exponent size, Franklin-Reiter) and misses one of the great RSA attacks, Bleichenbacher's "rump session" e=3 signature attack, about which there was an excellent NDSS paper (also being presented at Black Hat) just this year.
So I guess I'm saying: RSA is even worse than this blog post suggests.
https://www.ndss-symposium.org/wp-content/uploads/2019/02/nd...
This seems to be an oblique reference to the attack you were referring to.
Rule of thumb is: just use TLS 1.3 if you can. That includes using TLS 1.3 in mutual auth mode if you need to validate both client and server identities. It comes with a lot of PKI for free to help address the "how do you know you can trust the other guy on the line?" problem. If you want the client/server to trust a restricted list of servers/clients, most clients and servers have that capability.
If SSL/TLS won't suffice and you just need to create an end to end "thing" with proof of identity, then libsodium is probably fine.
If you're looking for a more general purpose crypto library where you need to mix and match algorithms, I'd recommend something like Google Tink (https://github.com/google/tink), or the high level interface to the native API's that come with the OS. On OS X that's the native security framework (https://developer.apple.com/documentation/security), and on Windows that's the .NET cryptography library (https://docs.microsoft.com/en-us/dotnet/api/system.security....).
If you need even more flexibility and are willing to do the research to avoid the footguns, there's always OpenSSL/LibreSSL, but that comes with a huge footgun warning.
I would hesitate to trust a high stakes system (like, controlling a regional power grid) with TLS's default PKI. There are hundreds of certificate authorities out there, all of which can vouch for everything. Compromising one certificate authority is enough to mount a man in the middle attack.
Granted, this is not a trivial attack, and TLS as it is now is mostly sufficient for your regular online shopping. More critical applications however need a dedicated PKI.
If you want the client/server to trust a restricted list of servers/clients, most clients and servers have that capability.
If you are running a regional power grid, TLS as a technology is still fine, but you should absolutely not trust the default PKI.
(it's unclear from the text whether ECIES is implemented in libsodium or only Curve25519, the internet seems to believe nacl (/libsodium) implements its own superior variant of ECIES called crypto_box)
Lets define the issue: Poor understanding of cryptography leads to poor implementation in practice.
This issue applies to any crypto algorthim, not just RSA and ECC. If everyone dropped RSA tomorrow in favor of ECC, would all of our problems be solved? No.
How to solve this issue?
1. Increase understanding of general cryptography. It is a dense subject.
2. Make implementation of cryptography easier. This is slightly more difficult though, as it depends on your use-case.
No, this is actually much easier than increasing general understanding.
Just get the experts (which is a much smaller pool of individuals than the general populace) to commit to designing things like WireGuard instead of OpenVPN, sodium instead of OpenSSL, PASETO instead of JWT, etc.
If this assumption is correct, why not just recommend a key size and some checks for generation than recommending elliptic curves? Elliptic curves have their own problems especially due to their complications around exploits of specific curve properties but more importantly the fact that programmers won't understand what they are calling in their code.
I understand that libsodium has been here now since 2005, but are we really at the point where we should stop using RSA just because a lot of Salesforce/Oracle/Azure/<insert boring job> developers are misusing RSA? I guess this question is really about whether we are at the anecdote stage or the herd immunity risk stage that OP mentions.
Furthermore, they don't just tell you to use some random curve thing: they tell you to use a specific implementation with knobs twiddled for security. You could work hard to maybe get everything right, or you can just do this thing and everything will be set for safety for you.
Which I guess explains why RedHat had corruption issues with their package database for, what, a few years before they figured it out? If RedHat needs a few years to get it right for a core component of their core product, who can be expected to?
This RSA discussion makes me wonder if it is in the same boat.
The biggest issue he describes is that, when implementing RSA, most of the parameter choices are necessarily private to the developer, meaning the dev is expected to supply good parameters on her own, when "good" means in terms of heavy math that no non-cryptographer can be expected to know. It's not just key size--there's a bunch of bad choices a dev can make, many of which are hard to recognize as bad choices.
Secondarily, many of those bad choices are driven by implementing RSA in constrained environments, where they're a tradeoff to achieve performance goals--so known-good techniques or algorithms are actually rejected.
ECC, by contrast, is almost all public parameters, so the security community can provide (and already has) known-good parameters that are provably secure, and a dev can simply choose a known-good configuration for their implementation to go with a well-regarded library like libsodium.
Meanwhile with ECC the main choice is which curve to use. This is visible in the public key. Hence, you can just check whether it is a curve that is generally accepted. For picking your private key, you only need a single integer chosen uniformly from a specific range. Whilst that is not totally trivial to do up to cryptographic standards, it is a lot easier than e.g. 'pick a pair of primes at random that meets these requirements.'
Consider the libsodium example: https://libsodium.gitbook.io/doc/public-key_cryptography/aut.... The crypto implementation parameters are handled under the hood.
On the other hand, those of us who write code that uses crypto are generally beaten about the head with 'NEVER ROLL YOUR OWN CRYPTO' and use library implementations right from the start. These are libraries that I assume are indeed written by people with maths degrees and have done careful analysis of the outputs. I know for a fact that I wouldn't trust any encryption I could write myself in an hour.
The biggest obstacle I find with ECC is that it's relatively easy to judge security by RSA (assuming correct implementation) but it's surprisingly difficult to compare the two; if I want RSA-2048, what key size am I supposed to use. ECC was also heavily promoted as offering 'RSA-equivalent security' while using less CPU, which made it particularly suitable for mobile/embedded systems, without necessarily implying it was an improvement over RSA.
That's what I would trust the most. Not that such a thing actually exists (Chacha20 is one of the closest), but if I can implement it quickly in an hour, and it is vetted by the community, then peer reviewed implementation like Libsodium are much more likely to be correct.
> The biggest obstacle I find with ECC is that it's relatively easy to judge security by RSA (assuming correct implementation) but it's surprisingly difficult to compare the two;
Then don't. Compare them with hashes instead. Oversimplifying things a bit, breaking a curve of a given size is about as hard as finding a collision of a hash of a similar size. So, Curve25519, which uses about 255 bits, is about as secure as Blake2b/256, or HMAC-SHA256. That is, about 128 bits of security.
Note however that this is more secure (without quantum crypto) than 128-bit ciphers like AES-128, because hash collisions and elliptic curves aren't as vulnerable to multi key attacks, and success rates drop faster when you try to be lucky with less computational resources than you should have used.
And ECC isn't always implemented (or even standardized) securely (https://cr.yp.to/newelliptic/nistecc-20160106.pdf) either.
I'm currently writing a book targetted to developers[2] and I'm wondering how much I should write about RSA.
There are two cryptographic primitives (types of algorithm) exposed by RSA:
* Encryption
* Signature
The signature algorithm has two adopted standards usually named RSA PKCS#1v1.5 and RSA-PSS. The latter one is more recent and provides a proof of security but everyone still use the former. The former hasn't been broken and is still pretty solid. Most internet certificates are signed using RSA PKCS#1v1.5 I believe.
The encryption algorithm is the problem (also used to perform key exchanges). It also has two adopted standards usually called RSA PKCS#1v1.5 (same name as the signature scheme I know...) and OAEP. OAEP is more recent and quite secure, but nobody seems to use it. Instead the former is still largely used in applications, and is often the default algorithm you use when you write RSA in many cryptographic libraries. Unfortunately it has been broken by Bleichenbacher in 1998 and it is practical to attack it. There's been many attempts to "fix" it and they have been repeatidly broken as well. So don't expect the library you use to implement it correctly.
[1]: https://eprint.iacr.org/2018/1173 [2]: https://www.manning.com/books/real-world-cryptography
FYI, RSA PKCS#1v1.5 signatures can be broken due to trivial implementation errors. [1]
[1]: https://www.cs.purdue.edu/homes/schau/files/pkcs1v1_5-ndss19...
From a cursory glance, all of these implementations are in C it seems like a C systemic issue, not an issue with RSA.
But I might be wrong because I've yet to read the paper.
(But again, haven't read the paper, also don't remember how bb signature forgery works)
(I'll read the paper but right now I'm in Hawaii doing snorkeling)
The bug is straightforward: RSA implementations don't verify all the bits in the padding, but rather "parse" it to find the digest, and then verify that. But there are, of course, bajillions of potential padded signature block representations that contain any given digest, since the block is so much bigger than the digest. For e=3, and for particularly naive implementations (like Firefox's, at the time) you can almost literally just formulate the signature block you want, then take its cube root to forge a signature.
Sorry to disapoint I did not do all the cryptopals :P filippo actually has a good blogpost on that attack IIRC.
* Your implementation produces incorrect results for some rare curve points.
* Your implementation leaks secret data when the input isn't a curve point.
* Your implementation leaks secret data through branch timing.
* Your implementation leaks secret data through cache timing.
Curve25519 and Curve448 are designed with secure implementation in mind, naturally, they trends to have more immunity to pitfalls. There is no invalid curve attack in Curve25519, every random integer is a valid public key, secret-dependent branching can be avoided easily, etc.
See https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number.
There's actually a counter example on that Wiki page - the highly complex numbers used in the NIST curves, for which no path to derivation was publicly provided.
Bernstein, et al., demonstrate that use of nothing-up-my-sleeve numbers as the starting point in a complex procedure for generating cryptographic objects, such as elliptic curves, may not be sufficient to prevent insertion of back doors. If there are enough adjustable elements in the object selection procedure, the universe of possible design choices and of apparently simple constants can be large enough so that a search of the possibilities allows construction of an object with desired backdoor properties.
It's both. The security of curves are evaluated according a set of criteria:
1. Whether the cost for attackers by the Rho Method is above 2^100? (security margin against known attack)
- NIST P-Curves: Yes.
- Curve25519/448: Yes.
2. Whether the curve has resistance against additive and multiplicative transfer to avoid potential attacks via index calculus? (security margin against known attack) - NIST P-Curves: Yes.
- Curve25519/448: Yes.
3. Whether the absolute value of this complex-multiplication field discriminant D of the curve is larger than 2^100 to avoid attackers from benefiting from possible speedups to the Rho Method? (security margin against known attack) - NIST P-Curves: Yes.
- Curve25519/448: Yes.
Notably, - Bitcoin Curve (secp256k1): No.
But it doesn't mean Bitcoin is broken, it just decreases our confidence that it would be still secure if HUGE speedups to the Rho Method are found for a practical attack. But finding it seems unlikely.4. Whether the coefficients of the curve are justified mathematically? (security criteria against backdoor)
- NIST P-Curves: No (!)
- Curve25519/448: Yes.
- Bitcoin Curve (secp256k1): Okay.
For example, coefficients for NIST P-256 (secp256r1, prime256v1) is generated by hashing random seed: c49d3608 86e70493 6a6678e1 139d26b7 819f7e90
Nobody knows what is it. NIST has its own defense: this random seed is only used as the input of SHA-256, since all cryptographers know that SHA-256 is secure, nobody, not even the NSA, can invert SHA-256, the output must be secure. They called it "verifiable randomness". But it's still room of doubts for sophisticated cryptographers, e.g. See this highly-amusing, satirical paper with lots of insight on this issue: How to manipulate curve standards: a white paper for the black hat https://bada55.cr.yp.to/bada55-20150927.pdfCoefficients for secp256k1 are not fully explained, but nothing fishy and generally looks good.
And keep in mind that when Satoshi Nakamoto was developing Bitcoin, secp256k1 was the best choice among available, well-accepted standard curves from this perspective, obviously, Satoshi must be an experienced hacker and have made a careful decision.
5. Whether the construction of the curve allows "simple" multiplication and addition. (security criteria against implementation pitfalls).
- NIST P-Curves: No.
- Curve25519/448: Yes.
- Bitcoin Curve (secp256k1): No.
Curve25519 utilizes a mathematical technique called Montgomery Ladder, which also allowed the practical implementation of constant-time, side-channel resistance crypto. On the other hand, NIST curves make it difficult.6. Whether the curve still offers strong security guarantee even if an attacker has "twisted" the curve, e.g. fooling a program to choose a point which is not on the actual curve. (security margin against known attack and implementation pitfalls)
- NIST P-Curves: Yes.
- Curve25519/448: Yes.
- Bitcoin Curve (secp256k1): Yes.
7. Whether the representation of curve points are indistinguishable from uniform random strings. (security usefulness in various protocols) - NIST P-Curves: No.
- Curve25519/448: Yes.
- Bitcoin Curve (secp256k1): No.
Therefore, we conclude Curve25519/448 is more robust than NIST curves.What you've written here is basically a sort of semi-accurate editorialized summary of safecurves. Safecurves is a cool site, but you should let it stand on its own, I guess.
I initially posted the parent comment, it's just the introduction of SafeCurves with its original URL, and I cited that Curve25519 has advantages of better treatment of timing side-channels and invalid curves in its design. I never mentioned "backdoor" at all because I thought it was unimportant.
Then user "yarg" replied my comment, said the point of Curve25519 here is that it uses mathematically-justifiable constants. And to me, what the author seems to be implying, is (1) that those security advantages I cited before are not too important, and (2) that the main concern is that NIST curves have "backdoors".
So as a response, I gave a somewhat editorialized summary of SafeCurve's findings for those who didn't want to read the whole thing. "yarg" seems to be interested on the issue of backdoor, so I gave some personal commentary on the concern of backdoors in the coefficients of NIST curves, and the Internet folklore of why Bitcoin used that unusual Koblitz curve.
But what I wanted to communicate was that it wasn't all about the backdoors, so I summarized all the criteria in SafeCurve to make the point. For example I said Curve25519 allowed "simple" multiplication and addition, and it makes constant-time implementation easier than NIST curves.
I think it's fair enough, do you?
Something can be provably secure against all known attacks and still be back-doored.
I said "not simply" implying that there are other considerations and not "not" which wold have implied that what you'd stated was unimportant.
As to the justification for my opinion, that was based on Bruce Schneier's comments regarding the numbers - which he made long before the Snowden revelations.
I'm not saying that the numbers are back-doored, but the situation gives a reasonable justification for pause.
A paper from Mehdi Tibouchi [1] shows how to represent points on essentially any curve as uniform random bitstrings.
Another paper by Aranha, Fouque, Qian, Tibouchi, and Zapalowicz [2] gives an even more efficient construction for curves over binary fields.
(As an aside, there are really good reasons not to use curves over binary fields. Discrete log has recently been getting easier much faster over GF(2^k) than over GF(p).)
(The situation is different for pairing-friendly elliptic curves, of course, but that's a different kettle of fish).
Do the people who perpetuate this meme with no basis not realise the clear and present danger it presents to humanity?
Yes certainly don't use homerolled crypto in production.
More importantly do not dissuade human beings with talent to roll their own, play with others codebases, and in general have a good fucking time with cryptography.
Straight out of the counter-intel handbook is how it looks when people repeat this bullshit ad nauseum.
Everyone on Earth should roll their own crypto. Don't listen to this nonsense, the real world needs you.
This is an interesting exercise to help understand cryptography, but if you think cryptography is subtle or magical, you haven’t started looking at cryptanalysis. There are nearly countless possible side channel attacks. This is why we don’t roll our own practically speaking. It can take advanced degrees in mathematics to merely give ourselves some sense of assurance that our home rolled system is safe.
A friend of mine did roll his own security. A decade ago he invented a new homomorphic encryption algorithm (type of encryption that allows meaningful operations on cypertext without revealing secrets). His first step? Getting advanced degrees in mathematics and at least a year of peer review to test against possible attacks. Only years later did he found a company on it. Unfortunately while the system was believed secure, a zero-trust system took too long and too much battery to generate keys on phones.
The world badly needs more cryptographers and their eyes on code whether from a purely academic background or digital tinkerer background. People should be encouraged everywhere to frolick in the ciphers.
> How does one become a cryptographer then?
> Yes certainly don't use homerolled crypto in production.
That is the point. When the glib phrase is repeated it is to people who are working on production, or something that might be in danger of one day soon being in production (we've all seen things go from proof of concept to production with insufficient reworking, it happens far too often). In that context it is correct to be constantly restated.
If you are explicitly trying to understand cryptography, then hopefully you are aware of the higher level dangers while you are poking around the lower level details and until you are ready for prime-time you are able to keep your exploratory code from going anywhere near production, at least not without proper scrutiny.
It is like the first two rules of optimisation:
Rule 1: Don't.
Rule 2 (for advanced programmers only): Don't yet.
Basically: studying it in depth (especially the mathematics part). Focus on cryptanalysis for a while, and find some flaws in existing implementations.
The moment you really start to fix those flaws, you probably know enough to implement a cryptosystem in a reasonably safe manner.
Even then, there likely will be many flaws in your implementation. So, you need other cryptographers to review it, several sets of eyes looking for flaws. Oh, and don't forget to make sure someone reviews for side channel attacks. (and some other things that I am probably forgetting right now)
In the end, the cryptographers that implement cryptosystems are a rare breed. These generally include people that are good at both the hard mathematics involved and the low-level programming knowledge that it requires to prevent timing attacks and the like, and even some hardware knowledge.
Who am I to say this? I have studied information security with some focus on crypto, including cryptanalysis and implementation of cryptosystems. Followed some MSc-level courses on implementation specifically, would not touch implementing a cryptosystem myself for production.
> So, you need other cryptographers to review it, several sets of eyes looking for flaws.
That's a real problem with no easy solution, for every "new" cryptographer trying to implement a cryptosystem you need a dozen half-capable eyes on what they are doing. For anything used widely you need hundreds.
Creating more half-capable eyes is a good thing.
Get an advanced maths degree. Minor in cryptosystems. Spend a few years looking at old cryptosystems. Understand how they were designed, what their weaknesses were, and how new systems are designed. Read a lot of papers. Try to write your own system and ask peers to point out the glaringly obvious holes you didn't notice.
> More importantly do not dissuade human beings with talent to roll their own, play with others codebases, and in general have a good fucking time with cryptography.
The consequences of lots of people using shit crypto is that a lot of people become less secure, and won't have any idea about it. At the same time, us saying "don't roll your own" won't actually stop anyone who has a burning desire to play with crypto. So we're definitely going to keep dissuading people from rolling their own.
People aren't using shit crypto, virtually no one is using anything other than what is highly vetted or otherwise google/apple/ms/etc is telling them to.
What is the actual argument here? That some $randompeople play around with new cryptosystems and then share them with friends? The sheer derision that my original comment has directed at it is astounding, let the kids play with cryptography, who the fuck cares, I hope they roll all of the crypto themselves, the world will be a better place, who exactly is saying it should replace current elliptical curves decided so wholesomely for us all by NIST?
The simple clear fact is that Western countries do not like and are actively campaigning against modern cryptography. Lets pretend we have some dignity left please as human beings. The West used to represent something, now it feels like we are taking notes from oppressive regimes and playing catch-up.
From Why You Should Stop Using Telegram Right Now (2016) (https://gizmodo.com/why-you-should-stop-using-telegram-right...):
According to interviews with leading encryption and security experts,
Telegram has a wide range of security issues and doesn’t live up to its
proclamations as a safe and secure messaging application. [...]
Telegram did what’s known as “rolling their own encryption,” which is
widely considered to be a fatal flaw when developing encrypted messaging apps.1. Telegram's E2EE is not on by default, therefore 99% of users don't use it.
2. Telegram's E2EE is not advertising authentication, therefore ~90% of the people using it don't check for MITM attacks, therefore majority of E2EE is useless against active attackers.
3. Telegram's E2EE does not work across devices, therefore majority people who use secret chats also use non-secret chats because desktop client don't support it.
4. 100% of Telegram's group conversations can be eavesdropped by the server, because Telegram doesn't have E2EE for group chats.
Complaining about possible cribs in how Telegram implemented the protocol from cryptographic primitives is an insignificant problem compared to the fact the entire protocol is fundamentally FUBAR, how it's so glaringly obvious you can't even fill out a CVE form.
If Signal had vulnerability where 100% of group conversations were not properly end-to-end encrypted, every newspaper in the world would publish something about it. However, with Telegram it has been spun as a "feature".
Another big problem is Telegram has been mentioned by hundreds of publications as "Secure apps like Signal, WhatsApp and Telegram".
To experts it's like hearing news spout "Great writers like Leo Tolstoy, Paulo Coelho, and Stephanie Meyer", or "Great bunker materials like reinforced concrete, steel, and MDF".
Repeatedly claimed, anyone would make mental associations between the three, but when you actually find out what they're about you can't believe your ears.
My previous employer was encrypting customer data (in a project I didn't work on) with RSA. Yes, they were actually using RSA itself to encrypt the user data. If you're thinking "Oh, and that's bad because RSA right?" then "No", that's not actually why - again, I direct you to our main thesis: Stop hand-rolling crypto, this is dangerous and you are going to hurt yourself.
But even if we restrict "people" to just my mother and sister, ordinary users with common hardware and software then that's often still people using shit crypto.
Popular libraries like OpenSSL are full of garbage fire shit crypto. Lots of it is "optional" but did you turn off that option? Does my sister know where the option is? No. Some of it is because people are trying to do very hard things and there's no margin for error, but as this article suggests you can solve that by not doing the very hard things any more. Doing RSA Key Ex with TLS _safely_ is very, very hard. Not doing it at all is easy. So just don't do it.
Cryptography is not like folk dancing or pottery, where it's OK to be fairly bad at it so long as you had a good time.
This is like heart surgery. We don't encourage everybody to "have a go" at heart surgery and hope maybe some of them will do a good job, that would be crazy. People spend years acquiring enough skills to even _find out_ whether they'd actually be any good as a heart surgeon, and some don't make the cut.
What does that look like? Cryptanalysis. Probably starting with a Mathematics degree, but it is possible to get there from another numerate background and a LOT of study.
That's where anybody at all serious - certainly this century and arguably going back to the middle of the twentieth century - starts. They analyse existing crypto systems and they find new problems. They start out a bit shy, hey, did anybody notice that X is actually a member of a Boze-Lechstein inverted group here? Doesn't that mean we could use the Stross-Baxter formula to find X in O(n) time? And after a few successess (and maybe one or two setbacks where they made an embarrassing mistake) they get a reputation so that others in the field show them exciting new things. Hey, you're the guy who first saw Stross-Baxter-Watts, take a look at our SHA-4 contender which relies on a related approach, see any problems?
After you've got a few years in cryptanalysis, maybe, if you feel up to it, you can start to propose new ideas. Your colleagues will respect you enough to take a look, and the first few will definitely get shot down. Ha, you forgot that the Benford-Barnes hypothesis doesn't apply to correlated members, so your new cipher has vast swathes of hard-to-detect weak keys. Not good, better luck next time. But maybe, if you're good, you will eventually make something good enough that people remember it when it doesn't make the cut for a competition. You are now "famous".
Notice how none of this was just some random guy in his bedroom having an idea and inventing a brand new cryptosystem? That's because that doesn't work. It did two centuries ago. If your adversaries are from the late 18th century, you should definitely go try that approach. But the adversaries got a lot better.
Nobody is saying not to learn and play. They're saying don't set off a rocket while staring down the engine. The reason why it has to be said is that the consequences of doing so when writing crypto are not so impressively immediate or dramatic, but just as devastating to the outcome (and maybe cryptographer, depending on adversary).
> Straight out of the CIA handbook is how you look when you repeat this bullshit ad nauseum.
The CIA does not care if you play with libsodium.
Cryptographers are easy meat for lions.
Care to place a long-standing bet on that? 20yrs or so? We can find a solid reasonable middleman here surely?
They very much do care. I'm willing to bet on it becoming public knowledge within that timeframe. Keen?
Go contribute to libsodium, go contribute to any reasonably well used crypto library, you've now got a big red dot on your back from an assortment of governments in perpetual conflict.
I truly worry for anyone participating in these open source codebases and not being aware of how much they are targets.
Take care of yourselves friends. Please.
So when you extorted people to play with other's crypto codebases in the previous post, were you trying to make them into targets?
First they came for the A2017U1s, or they would have, except he never opposed the wrongdoing.
> Yes certainly don't use homerolled crypto in production.
You should know how easy prototypes enter production!
The real code contribution of cryptographers anyways tend to add some very specific details to libraries (like adding their latest invention).
Now the general advice is that if you want to skip the 15 years it take to become a cryptographer and you want to send a message, there are ways.
Look at the amount of trouble the NSA went into to create Stuxnet. They stole digitally signed certificates from big corporations, completely undetected.
If a known burglar installed your home security system, even if the security system was from a well known and trusted manufacturer would you trust that your house was actually secure while you were on vacation?
'RSA is easy to get wrong, stop using it' would be better. More descriptive too.
Parameter selection isn't any easier in elliptic curve land. In fact, by the point that I believe you can make an educated choice in elliptic curves, you can also make a reasonable choice in RSA parameters.
You have to:
1. Pick a curve. Which ones? You'll have to know. This article tells you to use Curve25519. Do you know if they're right? Not really. Is a Koblitz curve over GF(2m) a better choice? You sure can't tell. You'll have to rely on other people's guides, e.g. [1].
2. Pick a library that supports the curve. This can be easy if you're on the beaten path, especially in C. This can be very hard on off-beat languages, which are generally stuck wrapping OpenSSL (and then typically have a weird interface to match as a cause of having to wrap C).
3. Interoperability concerns: Sometimes you don't actually control both halves of the software. You'll also have to pick something that plays nice with other things.
And all of this is putting the cart before the horse. Programmers must first understand what kind of algorithm they need, only then they can make a choice of the actual cryptographic solutions, e.g. Crypto101[2]. I firmly believe that a basic working knowledge of cryptography is a hard requirement for a programmer that touches code going into production.
If by some ungodly anti-miracle you're stuck implementing your curve yourself, you'd better be hiring external help. Ideally, however, you can use an existing, respected library. What is a "respected" library? Well, now we're back to “you'll have to know”. Expect to spend upwards of a dozen hours getting to grips with the basics.
(Incidentally, public key cryptography has always been an implementation nightmare. ARX ciphers don't scare me as much and most hash functions seems fairly reasonable to implement, but public key cryptography is when the bignum math hell comes to bite you—and with elliptic curves, you also get “moon math”, as the article so aptly puts it, to go with it.)
FWIW: while I clearly subscribe to the notion of cryptographic education, I also thing that we should give people high-level recipes. Why are they the right ones? Yep, you gotta trust me. I'm fine with both of those existing ('tptacek and I co-authored our Cryptographic Right Answers doc from last year) because they have different audiences.
The differences, according to the article:
1. RSA looks easy, so developers are tempted to roll their own, not so with ECC
2. almost all RSA parameters are necessarily secret, making it harder to peek on supposedly well-designed systems and know what to select (or even how to select), ECC parameters are public and other users can be used as examples
This isn't entirely true, is it?
AFAICT it no longer supports RSA as a key-exchange algorithm as earlier versions did, but it certainly supports RSA authentication. The only systems that used that for TLS I've known in the last 15(ish) years were government systems that specifically wanted to prevent PFS in their logged connections.
[0]: https://www.f5.com/content/dam/f5/f5-labs/articles/20180423_...
(EDCO is Nalini Elkins' outfit, the Enterprise Data Centre Operators group - banks and that sort of thing, they tried pointlessly lobbying the TLS Working Group to get RSA Key Exchange back into TLS 1.3)
I don't have very good contacts inside that industry any more (I now work for a startup) so I'll be interested to see what if anything they _actually_ do about this over the medium term. Trying to promote "alternatives" to TLS? Deploying DH where the "random" private values are actually from a fixed or pseudorandom source under their control? No idea yet.
It is definitely true that some big name real world "security" companies will go out to a big corporation and tell them to mandate RSA key exchange in order to make the "security" product work because they want to do MITM. They're too cheap to do all the engineering to actually ship the session keys over the wire so they want you to just upload the RSA Private Key into their "security" product.
I got this mandate to require RSA Key Ex (at my old job for a B2B app I wrote) and was like "That ain't going to work, this here is a mutually authenticated TLS session". And I ended up in a bunch of calls in which more and more senior people from the "security" product team were brought on until they eventually found someone who actually knew how it works to say that yes, of course you can't MITM a mutually authenticated session without assistance from both parties, so the product can't work.
Current status is eTLS which, if I understand it correctly, is just static DH. Unclear why nobody isn't just disclosing session keys/premaster secrets per SSLKEYFILE, but my money is "organizational incompetence" (as yours is, I'm guessing from your B2B app experience :-)).
[0]: https://www.etsi.org/deliver/etsi_ts/103500_103599/10352303/...
As such, I can definitely see why TLS inspectors don't like the myriad of opportunities for mistakes created by disclosing secrets at the end-points.
The counter-argument would be that, if you really need TLS-inspection your security should be tight enough that disclosing the secrets should not be the hardest thing you are implementing. Moreover, neither should the world compromise its own encryption to make your targeted (and rarely required) ability to break encryption safer.
Never seen this in all my failed life. It is basically 65537 everywhere I have seen RSA used. That actually led me to Fermat numbers and why they are used because it looked like a conspiracy to me.
I also never generated p,q or d manually and just trust some tools from some crypt-weirdos. So it is 1 parameter I have to remember, right?
I am only a user of RSA and would never implement it myself. But prominent web services mostly supply RSA parameters for their encrypted content. Some have shifted to ed25519, but it is still very rare in my experience.
Not a conspiracy ; ). It has to do with the exponentiation. Most fast math libraries exponentiate quickly by squaring and multiplying: if you want to compute, say, x^23, you can either multiply x by itself 23 times, or you can compute: ((((x^2)^2)x)^2)x^2)x: four squaring operations and four multiplications for a savings of 15 operations. You can do this factoring easily based on the binary representation of the exponent - in this case, 23 is 10111. So I’m going to square x 5 times (since the bit length of the representation is 5 bits long) and additionally multiply x by the result every time I encounter a one bit. Now, if I want to speed this up, it’s in my best interest to choose an exponent with the fewest one bits possible - preferably with a one at the beginning and a one at the end, so now I only have to square _n_ times and multiply twice. As it turns out, numbers whose binary representation have a one at the beginning and a one at the end turn out to be Fermat primes: 2^n+1.
Besides, it appears to me that the primary problem is people who roll their own RSA implementations. As the article says, "In circumstances where people implement their own RSA, all bets are off in terms of using standard RSA setup procedures, and developers will frequently do strange things...". It also later shows a picture where the disastrous choice is "rolling your own RSA". Yes, there are a lot of ways to screw up an RSA implementation (as noted in the article), but that's less important if it's implemented by people who know what they're doing.
The CII badge does specifically address the problem of people who roll their own crypto. Specifically, its "crypto_call" criterion says: "If the software produced by the project is an application or library, and its primary purpose is not to implement cryptography, then it SHOULD only call on software specifically designed to implement cryptographic functions; it SHOULD NOT re-implement its own." https://github.com/coreinfrastructure/best-practices-badge/b...
Full disclosure: I lead the CII Best Practices badge project.
And why do you think they do? The article has an explanation for this: RSA looks easy enough to implement. If you tell people to use RSA, many will roll their own, even if they don't know what they're doing.
And to be honest, after having read this article, I don't trust even the properly peer reviewed implementations of RSA. And if compatibility is an issue, I'll first try to convince whoever I must convince to switch to Curve25519, which is simpler to implement, more secure, and faster in most cases. (Of course, one should still use an existing implementation.)
I think the key advice is to use an existing crypto library. A non-expert who tries to implement ECC themselves will almost certainly screw it up as well. Sure, it is a little less likely, but it is still possible.
The problem with RSA is that it's easy to understand and easy to implement well enough to work in the sense of "my test cases verify and reject my good and bad signatures", but extremely hard to implement correctly with respect to a host of subtle number theoretic attacks against prime generation, key selection, and bit banging that have been successful in the wild over the past few decades. Given the number of attacks that have been found and their subtlety, it seems likely that there may be additional holes yet to be found in any given implementation.
There are other options that may be harder to understand and implement, but the trade off is that if you get them to work at all, you have probably done it safely (or more likely used a library written by a cryptographer that did it correctly) - Digital Signature Algorithm (DSA) for signing and Elliptic Curve DSA (ECDSA) and Elliptic Curve Diffie-Helman (ECDH) for key agreement which allows for encryption (via a symmetric method).
Use high-level constructs designed and peer-reviewed by cryptographers who know what they're doing.
Basically: use libsodium.
One implementation docs says:
"I'm experiencing some issues on Windows. Do you have any idea?
I'm sorry but I'm completely clueless about Windows environment, but if you have any suggestions or PR changes. They will be more than welcome."
Can I trust them? How do I know there are no some Windows-specific issues in this implementation?
Another library listed on this page does not have a single release? Could it be trusted?
Next has been abandoned and moved into Apache Foundation incubator. Good but will it be maintained? Maybe use this, or maybe Lazysodium, which has a nice Github page?
If I am to verify if any of those ports is a proper one probably I would have to really become a crypto expert.
Isn't it safer to learn and understand how to use, say, AES algorithm as it is provided as a part of Java? There is a few important config choices, but still it looks easier than analyzing someone's libsodium port?
No.
AES by itself is just a function that provides symmetric encryption of one fixed size block. You can't do anything with "just AES". Bad libraries will throw a choice of block cipher modes at you, and tell you to pick CBC or CTR. Then you won't even realize that you have no integrity checking at all on these messages. If you do, you'll maybe add an HMAC, and end up with encrypt-then-MAC or MAC-then-encrypt and ughhhh.
Just use a high level library that provides idiot-proof APIs with descriptive names like "secret box".
> If I am to verify if any of those ports is a proper one probably I would have to really become a crypto expert.
These things aren't ports!!! They're simple FFI bindings. Take a quick look at the code (heck, the readmes say things like "Java Native Access" already, this should ring a bell).
As for the maintenance, it hardly needs any. Should I get hit by a bus tomorrow, you'd still have something useable today. If you want client server security, I'm currently working on Noise like protocols, and should add that during the summer. After that, my library should be mostly frozen.
Now there is this thing where you might not trust yourself enough to decide whether you should trust me…
crypto_box_easy(ciphertext, MESSAGE, MESSAGE_LEN, nonce, bob_publickey, alice_secretkey)
Where do you see a place for parameters?Even if there was some choice, it would've been a choice between known good options, no footguns.
- AWS, which has incomplete ECC support https://docs.aws.amazon.com/elasticloadbalancing/latest/appl...
> ACM supports RSA certificates with a 4096 key length and EC certificates. However, you cannot install these certificates on your load balancer through integration with ACM.
- Heroku, which is still RSA only https://devcenter.heroku.com/articles/keys
Edit: not sure why the downmod so I've added references.
I was all onboard with this articles premise, that good crypto is hard to understand and RSA requires you to make choices about crypto that can easily you screw things up.
Then I read the "So what should you use instead?" section: > "Developers could theoretically build an ECC implementation with terrible parameters and fail to check for things like invalid curve points, but they tend to not do this."
Is this not exactly the authors complaint about RSA? Granted there's fewer places to screw up, but still, you're required to specify a parameter that most developers typically don't understand the ramifications of.
(It's absolutely true that ECC can be as much of a footgun, e.g. non-random-k ECDSA is worse than RSA PKCSv15. But the real takeaway is to use something that's already set for security, like libsodium.)
From the video, one of his major complaints is that people learn RSA in their first year of university, understand the math, then roll their own. How hard can it be, its modulo and exponents. People don't tend to do this with ECC. They just pick a library.
You are right in saying that the same roll your own problems that occur with RSA would occur with ECC.
I never roll my own encryption, and most developers don't (unless they're just playing with stuff and learning how to understand it; and not use it in production). I stick to standard tools and libraries like Legion of the Bouncy Castle and pypi RSA.
I wish this article covered the way most developers interact with RSA libraries and showing us those specific problems.
Using standard tools like PyPI RSA, however, does not necessarily save you. Not only will openssl's RSA happily generate a bad key for you if you ask it nicely, Because it's pure Python, there's a good chance it's vulnerable to side channel attacks. Also, it uses PKCSv15 padding for encryption, and is therefore definitely vulnerable to the Bleichenbacher attack mentioned in the article, for example.
Just use libsodium's box.
sybrenstuvel/python-rsa/ is PKCSv1.5 which like lvh said, is not secure.
RSA is fundamentally less secure than Diffie-Hellman as it lacks forward secrecy. So even a perfect implementation is still less secure.
Ouch
A little more revealing about the playfulness this team is addressing the issue, although still filling it in with their strong opinions and data.
The article came across heavy handed which (I feel) distracted from some really good points.
AFAICT, CA vendors don't offer cert signing in anything other than RSA at present. Is there any motion to getting Curve25519 replacing RSA in the CA cert system for TLS or code signing, or are we gonna be stuck with RSA for certs for the next decade?
I'm very skeptical that this is actually possible with proper Javacards. In any case you shouldn't leave your smartcard lying around. And furthermore what kind of system uses RSA for document/disk encryption?
Presumably there are some organisations that use smart cards for EFS encryption in windows but not sure if BitLocker supports it
I don't know much about encryption as a whole, but I have some inkling about smartcards and this makes me suspect this whole article as FUD.
For example: encryption: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...
Note that ECDSA is missing.
But, for signing: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...
Here, ECDSA is an option.
Why the difference?
It means you cannot use your web browser crypto to interact with the majority of blockchains (like Ethereum).
Is there a good reason why support inside your browser for signing is available with ECDSA but not encryption?
Is this a patent or IP issue, or perhaps a political issue.
I always thought one reason for not using RSA was that you never know if there are backdoors the US government has installed, but this article makes it sound technically poor as well.
In fact, the ability to encrypt directly with RSA is probably a bug, not a feature. There are too many ways to do it catastrophically wrong, and it almost guarantees cryptosystems without forward secrecy.
(WebCrypto isn't great and I'd avoid it, but this isn't why).
Do you have a link to a discussion on why WebCrypto isn't great? More specifically, are you saying there is no real good way to do encryption with WebCrypto, or is it that it is too easy to do it wrong?
It can make some sense in extensions, or in situations where client-side cryptography is more an interoperability or offloading concern than an end-to-end security concern. But ultimately, it's misused more than it's used well.
- Hash functions
- Key derivation functions
- Public key cryptography
- Block ciphers
- Stream ciphers
- CSPRNGs
Understanding these primitives means you'll know what cryptographic news means, it means you'll understand how things like NaCl, TLS or the NOISE protocol are constructed under the hood, it means understanding how things like proof of work functions and cryptocurrencies work will be much easier.
While I would never recommend constructing your own protocol based on these, having the understanding of how they work can give you a good idea of some of the nuances and risks associated with them and help you understand what it really means when they get broken.
[1] https://arstechnica.com/information-technology/2014/01/how-t...
As to curves, just use Curve25519 and Curve448 -- those are "nothing up my sleeve" curves where the authors came up with a set of rules for picking a curve's parameters, then picked the one that most closely matched the stated goals according to their rules. The way they are it's very difficult to imagine that the authors somehow found a curve with a backdoor and then retroactively designed rules to generate the same curve, rules that have to be simple and obvious (at least to cryptographers anyways).
There are many benefits to those curves, not the least of which is that their public keys are smaller than RSA or modular DH keys, and that they are faster, all while being more secure.
Can we change it at least here? 'RSA is easy to get wrong; stop using it' seems harmless, and better describes the content anyway.
Given that the point of the article is that something has to change, I wonder if that old title wasn't the more appropriate and expressive one.
But hey, who cares...
In my opinion introducing swearing/emotion to an argument weakens it, regardless of its validity.
Not really, because the pitfalls in AES are more well-known. Moreover, there are widespread AES-modes that work pretty well. Really, once you have picked a mode of AES (besides ECB) the biggest pitfalls are 'only use a nonce once' and 'use HMAC (MAC-then-encrypt) if your mode isn't authenticated'. With AES-GCM, that last one drops off. With AES-SIV the first requirement drops, and AES-GCM-SIV has neither consideration. Granted, AES-GCM and similar are not trivial to implement, but given there are test-vectors it is harder to accidentally publish a faulty version.
Moreover, much fewer people actually know how AES works. Especially compared with the amount of people who could essentially implement primitive (insecure) RSA from memory. This comes with many more attempts at RSA. Essentially because the distance between the insecure primitive and the secure systems using RSA is so incredibly large.
Are there tools that will assist in choosing or testing those parameters?
That's why a script/tool validating against the known attacks mays be helpful.
1. https://security.stackexchange.com/questions/143442/what-are...)
Surely anyone who studied a single textbook about crypto knows this? Or anyone who bothered to do a bit of reading about the crypto library they are using?
After a bit of searching, apparently this is a big issue. Search for "RSA.gen_key" on any of the following pages:
Exhibit A:https://github.com/const586/freestream/blob/ee95c78e85719caa...
Exhibit B:https://github.com/lixmgl/Intern_OpenStack_Swift/blob/40c241...
Exhibit C:https://github.com/egbertbouman/tribler-g/blob/14e5c4eaf66f5...
Exhibit D:https://github.com/wizzard/dm-p2player/blob/fb3a89aedc0a2374...
Exhibit E:https://github.com/mimianddaniel/booksalt/blob/248c2349fd9a6...
Exhibit F:https://github.com/GrandPaRPi/p2ptv-pi/blob/6f79c00f9055a376...
Exhibit G:https://github.com/C6SUMMER/allinclusive-kodi-pi/blob/8baf24...
I switched to PyPi RSA. It took a little bit of digging, but it seems to use a sane exponent by default:
https://github.com/sybrenstuvel/python-rsa/blob/11bf33264c62...
In one sentence you admit you have limited knowledge of the field and then immediately make a definitive statement about the field. Bold.
This is because RSA lacks forward secrecy: If the private RSA key is stolen, it can be used to retrospectively decrypt all past communication.
Also X448 provides the equivalent security of ~15000-bit RSA with a fraction of the key size, and key generation takes milliseconds instead of minutes.
tl;dr
For key exchange, use X25519 or X448.
For digital signatures, use Curve25519-based ed25519 signatures.
For authenticating communication, use authenticating encryption like ChaCha20-Poly1305 or Salsa20-Poly1305 or AES256-GCM.
For hash function, use Blake2 or SHA3-256 or SHA256.
RSA lacks perfect forward secrecy is same as saying that ECDH lacks perfect forward secrecy. Both is true, and both can be used with ephemeral keys, which provide forward secrecy to both (and therefore must use other way to authenticate). Claiming that it's somehow RSA's problem while willfully pretending that it doesn't concern elliptic curve cryptography is very dishonest.
It's not a new viewpoint, and there are arguments for and against.
The NSA seemed to be suggesting that practical quantum computers were coming so soon that people who had not yet upgraded from RSA to ECC should not bother to do so, and instead should save their money for the future upgrade to post-quantum protocols. Shortly thereafter, the NSA released a revised version in response to numerous queries and requests for clarification. The new wording was even more explicit in its negative tone on the continuing use of ECC: “...elliptic curve cryptography is not the long term solution many once hoped it would be. Thus, we have been obligated to update our strategy.” Although other parts of the statement assured the public that ECC was still recommended during the time before the advent of practical quantum computers, the overall impression was inescapable that the NSA was distancing itself from ECC.
Secondly, if you were really that worried about quantum computing, you'd use a quantum-hard kex, like Google did with CECPQ1.
(I can't speak to why the NSA doesn't tell you to do that. I'm sure it has people in it that think so.)
The NSA and NIST should, in a perfect world, have lost all credibility of any sort given the revelations of poisoned RNGs. It boggles my mind that they are still given any credence let alone still considered authoritative.
But more importantly:
1. No, quantum computers that big don't exist.
2. If they are somewhat practical, you really want perfect forward secrecy so they at least have to break a classically hard problem _every time_, which is unlikely with home-rolled RSA systems.
3. If you do care about post-quantum KEX (because your information needs to be secret for longer than you can count on quantum computers not being practical), we have faster alternatives, like SIDH.
Key sizes are an attractive subject for bikeshedding. You can endlessly argue about whether better performance or stronger theoretical brute force resistance (e.g. billion years vs million years to crack) is more important.
And yet, it is a silly thing to care about. Read the article, it does not even mention this topic really.
It's all about implementation vulnerabilities, and how RSA is fundamentally resistant to correct implementation (requires padding, etc)
The EC curves from NIST[1]:
> cryptography experts have also expressed concern over the security of the NIST recommended elliptic curves
C.f. [this comment and the thread of comments nearby][2], where this, and some other concerns, are discussed. But the concerns about hidden numbers from a government agency in a world where we know what we know from Snowden just kills the NIST curves for me.
I'd happily use Curve25519/Ed25519 over RSA, if it is supported, but that's the trick. AFAIK, TLS 1.3 supports it, but the CA/B forum does not, meaning CAs won't issue such certificates, since they're bound by those rules. ACME, AFIAK, also does not support Ed25519 yet, though I believe there are plans in motion to do so.
SSH is about the happiest story: it's well supported by OpenSSH.
Aside from that, as a dev, I try to let well-known TLS libraries handle the encryption for me, as much as possible. (But even that is hard; many tools/libraries make it incredibly easy to generate invalid certs, short keys, fail to correctly validate a supplied certificate, etc.) Or push it over SSH.
[1]: https://en.wikipedia.org/wiki/Elliptic-curve_cryptography