0

I ran into an issue with my server that made me ask a question - is AES-256 encryption reliably consistent?

So my node server, to avoid DDOS vulnerabilities while keeping user data anonymous, takes an IP from the request, encrypts it, and stores the number of times it has made a request in the last 24 hours.

It checks if the user had made a request in the last 24 hours by re-encrypting the IP using the exact same password. It then, takes that and matches it with the first stored IP.

But then:

Error: Can't find data: /ipcount/d00c526612cec9e5d3e201af35993c75. Stopped at ipcount

d00c526612cec9e5d3e201af35993c75 should be the encrypted string, but the database is acting like it's never seen it before. So can I have it encrypt consistently with the same password?

Thanks in advance.

Here is the encryption function...

const crypto = require('crypto'),
    algorithm = 'aes-256-ctr',
    password = 'aSecureNotSharedOverAForumPassword'

function encrypt(text){
   var cipher = crypto.createCipher(algorithm,password)
  var crypted = cipher.update(text,'utf8','hex')
  crypted += cipher.final('hex');
  return crypted;
}
jasonidris
  • 13
  • 4
  • I added an error catching `try...catch` and it worked... but I still want an answer – jasonidris Dec 04 '17 at 00:04
  • AES encryption is consistent given the same inputs, modes, etc. If it weren't consistent it would not be useful. Inconsistent usage will produce inconsistent results. – zaph Dec 04 '17 at 00:16
  • 1
    Encrypting it doesn't keep it anonymous since it can just as easily be decrypted. Something like bcrypt might be more appropriate. – President James K. Polk Dec 04 '17 at 01:14
  • Right; something somebody else also said. Did a node version – jasonidris Dec 04 '17 at 02:00
  • Encryption is the wrong tool for this problem. Any cryptographic hash would be a much better fit. SHA-256 is widely available. See `crypto.createHash`. – Rob Napier Dec 04 '17 at 04:20

2 Answers2

1

As per the Node.js documentation for crypto:

It is recommended that developers derive a key and IV on their own using crypto.pbkdf2() and to use crypto.createCipheriv() to create the Cipher object. Users should not use ciphers with counter mode (e.g. CTR, GCM or CCM) in crypto.createCipher()

So the behaviour you are experiencing isn't exactly a defined behaviour, per se. My guess is that the underlying cipher object is randomly generating a nonce for your CTR mode and thus the output is different each time.

To fix this, use crypto.createCipheriv as recommended by the documentation and generate the nonce yourself. This way you can store the nonce and use it to generate the same output stream.

Luke Joshua Park
  • 9,527
  • 5
  • 27
  • 44
  • Thanks, like I said, I tried setting a setting a variable with my own password with a try catch, and it worked. – jasonidris Dec 04 '17 at 00:25
0

For others who are looking, do not use the same nonce. It takes away all the security guarantees of AES. Take a look at this thread instead: CryptoJS AES encryption with ECB mode produces different results with the same params