1

Following code is run on a web page via script tag. Every time I load the page or run the code in the browser console - I am getting different value...

var key = 'key-123:456';
var uid = 1234567890;
var encrypted = CryptoJS.AES.encrypt(id, key);
encrypted.toString();

How can I have single "encrypted value"for "single id" regardless of how many times I load the page or run the code in console?

wailer
  • 511
  • 7
  • 22
  • 1
    This encryption may use a salt that makes the value different everytime, to prevent stealing? Not sure though, just an idea. (like php and encryption) – DevMoutarde Nov 02 '17 at 19:17
  • 5
    Because [CryptoJS operates by default in CBC mode](https://github.com/jakubzapletal/crypto-js#block-modes-and-padding) which uses a [random initialization vector to achieve non-determinism](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29). If you want a deterministic transformation then (1) that's usually not desirable property from your encryption to have and (2) you want ECB mode. Why do you want a deterministic transformation? See the relevant section of CryptoJS's README: https://github.com/jakubzapletal/crypto-js#block-modes-and-padding – apsillers Nov 02 '17 at 19:17
  • I agree with DevMoutarde. It is probably using time and some other factors to salt. – splitwire Nov 02 '17 at 19:19
  • I need to match the data downstream so I need to have a deterministic value to decrypt. Maybe I am not using CryptoJS correctly. I will look up your github doc now. – wailer Nov 02 '17 at 19:27
  • 1
    @wailer Do you ever need to transform the data back to its original form? Could you use a hash instead? That would allow you to transform the data into a non-reversible form but would allow comparison in the hashed form. That's how secure password comparison works: you don't store the password but do store `Hash(password)`, and when the user logs in you compare the hash to `Hash(entry)`. Would that suit your needs, or do you need to decrypt the data at some point after the comparison? – apsillers Nov 02 '17 at 20:48
  • Hi @apsillers Yes. as I need to pass the data to another system as you mentioned in your question "later comparison of the data" is the primary use case. Thanks. – wailer Nov 02 '17 at 22:50
  • Hi @apsillers i thought I saw your answer but it's now deleted/gone... I just didn't get around to it.. can you please post it again. – wailer Nov 03 '17 at 07:37

1 Answers1

11

AES is a "block" cipher, which means it operates deterministically on fixed-length blocks from plaintext to ciphertext (and vice versa). However, it's typical (and generally preferred) to use a "mode of operation" that adds non-determinism to the encryption process. For example, CBC mode (which CryptoJS uses by default) XORs a random initialization vector with the plaintext before encrypting it (and, correspondingly, after decrypting it):

diagram of CBC mode showing first plaintext block XORed with initialization vector (IV)

This is vastly preferred because otherwise an eavesdropper can detect duplicate blocks, which might allow an attacker to eventually understand what is being communicated -- undoing the entire point of your encryption.

However, it sounds like you want your encryption to have this specific weakness, which suggests to me that maybe you don't really want encryption at all. Instead, you might want a hash, which is a deterministic one-way transformation. (CryptoJS supports several hashes.) With a hash, a given input A will always hash to the same hash value H, so you can compare Hash(A) == Hash(B) to see if A == B. (This isn't a perfect comparison, since hashes have an infinite input space and finite output space, but hashes are deliberately designed so that it's very, very difficult to find two inputs that produce the same output.) This is how websites securely store your password: the service stores Hash(password) instead of password itself, then when a user submits a password entry, the sites compares Hash(entry) and Hash(password) to see if the entry is correct.

var hash = CryptoJS.SHA3(message);

However, if you really do need to reverse the transformed value back into plaintext and not just compare it to another hashed value, then you do need encryption. In that case, you can use the cryptographically inferior ECB mode, which has the weaknesses described above. In CryptoJS, you can do this by supplying an options object with a mode property:

CryptoJS.AES.encrypt(msg, key, { mode: CryptoJS.mode.ECB });
apsillers
  • 112,806
  • 17
  • 235
  • 239
  • Thank you very much for your time and explanation around CryptoJS - as it's a new learning for me! It worked :) – wailer Nov 04 '17 at 17:23