CryptoJS AES-128 does not encrypt with expected encrypted result

88 Views Asked by At

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

  1. The AES (or Rijndael) encryption methodology is used to encrypt the [encryptionValue].

  2. AES requires a 32-character key that will be provided. Like the Salt value, the key should not be changed unless coordinated.

  3. 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.

  4. This uses an encryption block size of 128.

  5. This uses an encryption cipher mode of CBC.

  6. This supports the following padding modes: Zeros, PKCS7, ANSIX923, and ISO10126. a. PKCS7 padding is the default.

  7. Once encrypted, the [encryptionValue] is included in the URL as a hexadecimal string.

  8. 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

1

There are 1 best solutions below

0
Rob Napier On

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 your script to https://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.