I'm working on a small program (in C) that writes encrypted log files, but there are a lot of articles out there that say you should avoid RSA whenever possible. However, most of these articles also seem to refer specifically to home-cooked algorithms involving RSA, because in such cases inexperienced crypto-devs tend to pick insecure parameters.

In my case I'm simply using the OpenSSL library and its RSA_public_encrypt() function, along with OAEP padding. The plaintext is received over the network and never fed directly to the program, any error messages will be reported only to people having local access to the machine it's running on. The private key can be either 2048 or 4096 bits long and will be stored offline and far away from the public key. The key pair is generated outside of the application, but also through OpenSSL:

openssl genpkey -aes-256-cbc -algorithm RSA -out foo.key -pkeyopt rsa_keygen_bits:4096
openssl rsa -pubout -in foo.key -out bar.pub

Is this setup:

  1. Considered cryptographically secure? I know you could still attach a debugger and just read the plaintext strings from memory, but in that case you have bigger problems anyways so it's not really relevant for this question.
  2. Future-proof (i.e. do I need to migrate it over to something else sooner rather than later)?

New systems should not use RSA unless interoperability requires it. See for example this twitter thread for current zeitgeist: https://twitter.com/veorq/status/1148258833896263680

With RSA, the recommendation is to not even have a mode where data is encrypted using RSA directly, even if it fits. Always use hybrid encryption to not have two code paths. The symmetric encryption part should use a modern AEAD, and unless the performance difference between AESGCM (up to 5GB/s) and ChaPoly (up to 2GB/s) is important, use the ChaPoly since a random implementation of ChaPoly is more likely to be secure than a random implementation of AESGCM.

Instead of RSA-OAEP, I would use Curve25519 ECDH in ephemeral-static mode. Meaning you create a Curve25519 keypair, store the private safely offline and copy the public to the system that will encrypt.

Every time it needs to encrypt a file it generates a new Curve25519 keypair, writes the public into the beginning of the encrypted file, does ECDH between the private and the destination's public to get a shared secret, forgets the newly generated Curve25519 keypair, uses KDF over the DH shared secret, and uses the result of the KDF to generate key and nonces for the AEAD. If the cleartext is long, use chunks.

To decrypt, use the private key stored offline to do the ECDH with the ephemeral public, KDF, AEAD.

Oh wait, I'm describing libsodium. Use libsodium. It is the embodiment of 20 years of lessons learned in cryptography and misuse resistant crypto API design, it is production quality, it is portable, it is fast, etc.

If large quantum computers ever happen, both Curve25519 and RSA would be broken. Details about the future quantum computer are not available to judge whether using larger RSA would give you more safety margin (unless you use post quantum RSA, which is a joke).

  • 1
    $\begingroup$ The answer stated what to use, but it would be even better if it said why RSA in practice is discouraged: The pesky PKCS#1 v1.5 padding is haunting it, combined with the fact it is mandatory in TLS (even in 1.3 it is still around in the RSA signatures) and new versions of Bleichenbacher's attack show up again and again, where countermeasures just blow up in complexity and most often are implemented wrong. $\endgroup$ – tylo Jul 17 '19 at 1:44
  • $\begingroup$ I've heard of libsodium but I haven't looked into it yet. It sounds interesting though, so thanks for that tip. I'm not really concerned about quantum computers because it'll probably take a fair amount of years before it'll be publicly available, instead of just for the 3 or 4-letter companies. And it's not like I'm sitting on data they would be interested in. :D $\endgroup$ – Sahbi Jul 17 '19 at 17:35
  • 1
    $\begingroup$ Then please just use libsodium. RSA is very much a legacy compatibility option now, and of the 4 main RSA based cryptosystems (PKCS#1 v1.5 encryption, PKCS#1 v1.5 signatures, OAEP encryption, PSS signatures), OAEP is the least used and thus it receives the least amount of scrutiny and effort to break it (e.g. the first two are used in TLS before 1.3 and PSS is used in TLS 1.3, but OAEP is never used in TLS). Also the openssl API is terrible. $\endgroup$ – Z.T. Jul 17 '19 at 19:13

That should be secure for the time being. I'd max out the RSA key size if I were you (future proofing) as 2048 will not survive quantum computers (neither will 4096 in the long run, but it gives you more time) AND because the bigger the RSA key size the more data you can encrypt. Remember that the max data you encrypt with RSA is your key size minus padding/header data so going with 4096 gives you 256 more bytes of data that can be encrypted. And if you were thinking of encrypting multi MB or GB files with RSA then you should rethink that. Use hybrid encryption where you generate a random key and encrypt that, along with some other useful information, with RSA. You encrypt the actual data with the random key you generated. This is how things like PGP and S/MIME work.

  • 1
    $\begingroup$ Hybrid encryption is not just for large chunks of data. It should be the default setting for any kind of transmission - so that you don't need different handling of different message sizes. $\endgroup$ – tylo Jul 17 '19 at 1:39
  • $\begingroup$ Yeah, I go with 4096 whenever possible. I hadn't thought about hybrid encryption but I'll definitely read up about it. =] $\endgroup$ – Sahbi Jul 17 '19 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.