This question already has an answer here:

I am attempting to write a function to encrypt and decrypt data using NodeJs following current best practices.

In order to achieve this I am doing the following:

  • Taking an end user password and enforcing password strength requirements
  • Generating 128 random bytes for a salt
  • Hashing the user password with pbkdf2 and the salt
  • Generating 16 random bytes for an IV
  • Encrypting my data with AES-256-CBC using the IV, and hashed password
  • Storing the encrypted data as a string in the format iv:salt:encryptedData

I'm assuming that using something like Argon2 for the hashed password would be superior, although everything I have read so far about encrypting files recommends pbkdf2.

Is it safe to store the salt and IV in the encrypted file? I'd like to only require a password for decrypting the file, so this would be preferable. I am under the impression that this protects me against a rainbow table style attack. I am not certain if this significantly increases the likelihood of someone being able to decrypt the data.

Is there anything else I could be doing to improve the security of the encrypted file?

This gist contains my exact code: https://gist.github.com/briancw/485e2645f7da16eaa3b530dd913297a5

marked as duplicate by Steffen Ullrich, Polynomial, ThoriumBR, Teun Vink, Anders Dec 28 '17 at 13:12

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • The salt and IV only need to be unique, they don't need to be secret. You can even have the IV generated from the key, eliminating the necessity to store it. As the salt already ensures the resulting key will be unique, there is no risk of IV re-use. I would however recommend you use an existing library/function to do encryption, though, rather than trying to implement it on your own. – forest Dec 20 '17 at 2:34
  • Thanks @forest. I attempted to find a more vetted solution but couldn't find anything that appeared to be sufficient. I looked through the source code of any npm modules I could find that looked production ready. Any that I looked at appeared to have flaws. I believe the next best method then is to use some sort of existing binary and write/find some bindings for it, although this seems not much better than what I've done here. Any resources I've been able to find on doing encryption with Node suggested using Crypto directly.If you could suggest an existing library I would love to look at it. – Brian Whicheloe Dec 20 '17 at 4:19
  • Try libsodium/NaCl. It seems there are several ports of it to Node, e.g. github.com/jedisct1/libsodium. – forest Dec 20 '17 at 4:30
  • 1
    @forest Thank you very much. I'll almost certainly be using one of those ports in my project. – Brian Whicheloe Dec 20 '17 at 4:49
  • 1
    I've just realized that another post where I got a recommended salt size was in fact recommending 128 bit salts, not 128 byte. – Brian Whicheloe Dec 20 '17 at 7:34

A popular crypto library is libsodium, based on NaCl, which provides an easy way to perform basic cryptographic operations like key exchange. It supports few algorithms, but the ones it does support are modern, secure, and chosen to work in a wide-variety of situations, removing the necessity to be understand the details of various crypto primitives. The library is for C, but it has been ported (usually in the form of C bindings) to many different languages, including to Node.js.

Installing it for Node.js is simple:

npm install libsodium

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