I want to encrypt a file with a RSA public key.

  • I generate a random 16 bytes key
  • I encrypt the file with AES + the random key (aes.NewCipher() + cipher.NewGCM() + aesgcm.Seal())
  • I encrypt the random key with RSA (rsa.EncryptOAEP())

Now I can send the encrypted file + encrypted random key to the person who has the private RSA key.

I read that secretbox should be favored over the RSA package: should I keep using RSA? What is the difference with the secretbox package?

  • $\begingroup$ Secretbox can replaces the second step of the question. For the rest, this is an apple-to-orange comparison, as secretbox assumes a shared symmetric secret, where overall the question assumes a trusted public key. $\endgroup$ – fgrieu Jun 3 '18 at 20:04
  • $\begingroup$ Oh I didn't realize secretbox with symmetric encryption, thank you. So why use it instead of AES? Is it using AES internally? The documentation talks about some acronyms I don't know :/ $\endgroup$ – Matthieu Napoli Jun 3 '18 at 20:08
  • 2
    $\begingroup$ @MatthieuNapoli NaCl secretbox uses a stream cipher called XSalsa20 that provides higher confidence in security than AES and faster safer software implementations than AES. (AES is designed for (a) secure hardware implementations, (b) leaky slow software implementations, and (c) secure super-slow software implementations.) You don't need to worry about the details under the hood. You just need to choose a key uniformly at random and never repeat a nonce; then secretbox guarantees secrecy and unforgeability of the secretboxes. $\endgroup$ – Squeamish Ossifrage Jun 3 '18 at 20:12

Do you need to grant someone the ability to encrypt messages whom you do not want to grant the ability to decrypt messages? If so, you need public-key encryption—and you probably want public-key authenticated encryption.

  • For example, if you want to separate the ability to create archives from the ability to read archives at a later time, then you probably need public-key (authenticated) encryption, like Tarsnap.

    Although you might be the only human in the system handling the archives, the machine that creates the archives—a virtual server hosted at Amazon constantly listening to the internet, say—might be meaningfully distinct from the machine that reads them—e.g., a laptop deployed only once, in an emergency, with a USB key stored under your mattress—and as such you might impose a meaningful privilege boundary between them.

  • Consider using NaCl box instead of building something yourself out of difficult parts like RSA with OAEP.

    As a bonus, NaCl box is smaller than anything you build out of RSA, and decryption is much faster, and the code will be simpler, and you naturally get public-key authenticated encryption where it would take much more work to design a bespoke system with RSA.

Is the party that encrypts messages the same as the party that decrypts messages, with no meaningful privilege boundaries? If so, then NaCl secretbox is fine.

  • $\begingroup$ I want a script to encrypt a backup and store it, but not be able to read it (only one person can decrypt it with a private key). So RSA seems to make sense right? (as explain in the question I use RSA + AES because RSA cannot encrypt large files). Do you confirm NaCl is not useful here? $\endgroup$ – Matthieu Napoli Jun 4 '18 at 21:02
  • $\begingroup$ @MatthieuNapoli I do not confirm that NaCl is not useful here. NaCl crypto_box provides the secrecy and privilege separation you asked for. You can keep a long-term key pair to decrypt all the archives, and for each archive, generate a temporary per-archive key pair for use with crypto_box. (In libsodium, this construction is called crypto_box_seal.) NaCl crypto_box does everything at once for an entire message. Using RSA public-key encryption safely is considerably more complicated. $\endgroup$ – Squeamish Ossifrage Jun 5 '18 at 2:37
  • $\begingroup$ @MatthieuNapoli All that said: In addition to the secrecy, you probably want to prevent forgery by a malicious server. For that you must either sign or symmetrically authenticate the archives—again, depending on whether or not you care to separate the privilege of creating vs. reading archives so that the ability to read an archive is not sufficient to create them. (Note the reversed direction of privileges for secrecy.) If you want to sign them, I recommend using Ed25519. If you want to symmetrically authenticate them, HMAC-SHA256 or keyed BLAKE2 or KMAC are all reasonable choices. $\endgroup$ – Squeamish Ossifrage Jun 5 '18 at 2:39
  • $\begingroup$ @MatthieuNapoli There are other issues too. For instance, how big is ‘an archive’? You should set a small upper bound on the amount of memory that you're willing to tie up before you can reject forgeries, and break all the data into pieces no larger than that. This may mean refusing to handle large archives, or it may mean breaking large archives into sequences if you need only sequential access, or it may mean breaking large archives into Merkle trees whose roots you sign so that you can have efficient authenticated random access. $\endgroup$ – Squeamish Ossifrage Jun 5 '18 at 2:45

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.