CryptoJS AES-128 Encryption w/ Salt result does not match client supplied value
I want to match my encrypted result using CryptoJS with the provided customer API expected output.
I have not been able to achieve the expected output. There are many similar posts here and nothing I've tried seems to work, what am I missing??
(see codepen.io for code https://codepen.io/wenditurner/pen/QWoadve)
var encryptionValue = "c8FtWECYDZUgPKqHO5g1CsakelzQGyY9|2014-08-14 18:33:49|123456789,A,John Smith";
var key = 'BTikvHBatPdAtgT3317QIQqGFY25WpIz';
var iv = '3a3JD8c02zdk5isU';
var hexKey = CryptoJS.enc.Utf8.parse(key);
var hexIv = CryptoJS.enc.Utf8.parse(iv);
console.log("hexKey: " + hexKey);
// 4254696b7648426174506441746754333331375149517147465932355770497a
console.log("hexIv: " + hexIv);
// 3361334a44386330327a646b35697355
console.log("hexIV correct in docs: 3361334a44386330327a646b35697355");
// 3361334a44386330327a646b35697355 -- MATCH
var encrypted = CryptoJS.AES.encrypt(encryptionValue, hexKey, {
iv: hexIv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
}).ciphertext;
console.log("Encrypted: " + encrypted);
// encrypted output: 5d2a9fa2818578e5c6c545102ee7859216f583883fbb5683099432fcfb946de6761104d2fba77414d4f5de575e0b546b18145672884a605add2d4b2a1d9671f114520f94740e9fcfed7b4ee4cc2d40d6
// correct encrytped output per docs 5d2a9fa2818578e5c6c545102ee7859216f583883fbb5683099432fcfb946de6761104d2fba77414d4f5de575e0b546b18145672884a605add2d4b2a1d9671f1f05ce7021ba2b67a5599f5b19df6e9b6
Documentation from client :
Encryption
The AES (or Rijndael) encryption methodology is used to encrypt the [encryptionValue].
AES requires a 32-character key that will be provided. Like the Salt value, the key should not be changed unless coordinated.
AES also requires a 16-character initialization vector (IV), which should be randomly generated. a. The IV is converted to hexadecimal format and appended to the end of the encrypted [encryptionValue] and should itself not be encrypted.
This uses an encryption block size of 128.
This uses an encryption cipher mode of CBC.
This supports the following padding modes: Zeros, PKCS7, ANSIX923, and ISO10126. a. PKCS7 padding is the default.
Once encrypted, the [encryptionValue] is included in the URL as a hexadecimal string.
Example:
a. Using the following values:
i. Key: BTikvHBatPdAtgT3317QIQqGFY25WpIz
ii. Initialization Vector: 3a3JD8c02zdk5isU
iii. [encryptionValue] Data: c8FtWECYDZUgPKqHO5g1CsakelzQGyY9|2014-08-14 18:33:49|123456789,A,John Smith
b. The IV converted to hex should be this: 3361334a44386330327a646b35697355
c. The encrypted [encryptionValue] converted to hex should be this: 5d2a9fa2818578e5c6c545102ee7859216f583883fbb5683099432fcfb946de676110 4d2fba77414d4f5de575e0b546b18145672884a605add2d4b2a1d9671f1f05ce7021b a2b67a5599f5b19df6e9b6
I've written this up in https://codepen.io/wenditurner/pen/QWoadve
They've used zero padding (
.ZeroPadding) in their example, rather than PKCS#7. That's why the last block is incorrect. When everything works except the last block, it's going to be padding.In order to make this work with
.ZeroPadding, I found I needed to switch yourscripttohttps://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js. The one you imported didn't seem to support non-PCKS#7 padding.Somewhat unrelated, but note that AES-256 requires a 32-byte key, not a 32-character key. ASCII-encodable characters (and even UTF8-encodable characters) represent a tiny, tiny subset of the AES keyspace, dramatically reducing the security of the system. If you can type the key in 32 letters and numbers, it's a very weak key by AES-standards. The same is true for the IV. It's 16 bytes, not 16 characters.