admin管理员组

文章数量:1332339

I am using CryptoJS to manually decrypt a string with a provided set of values. The secret is provided and then an SHA256 has is taken of it. The message and initialization vector are base 64 encoded. Here's what I am trying, but every time I run it, the output changes - how can that be?! I'm at the end of my wits...

// Key and take the hash of it
var secretKey = 'TESTING123Secret_Key';
var secretKeyHash = CryptoJS.SHA256(secretKey).toString(CryptoJS.enc.Hex);

// Base 64 encoded values
var accountNumberBase64 = 'nxjYfo4Stw63YBEcnjo3oQ==';
var initializationVectorBase64 = 'HnNcvu9AP9yl09APWkWnDQ==';

// decode the values provided above
var accountNumberEncrypt = atob(accountNumberBase64);
var initializationVector = atob(initializationVectorBase64);

// Use crypto to decrypt
var decrypted = CryptoJS.AES.decrypt(
    {
        ciphertext: accountNumberEncrypt,
        salt: ''
    },
  secretKeyHash,
  {
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.NoPadding,
      iv: initializationVector,
      salt: ''
  }
);
 console.log('   decrypted, by hand: ' + decrypted.toString(CryptoJS.enc.Hex));

the last line changes every time this is run (run it on page load) - same values provided every time, output is different.

How it is supposed to work:

Decryption Instructions:
1. A static, secret key will be shared which will be used for decryption (Secret Key TBD).
    a. HASH the secret key with SHA256, encode it to Hex and use the first 32 characters. This will be used as the KEY when decrypting.
2. Two pieces of information will be sent via the POST method
    a. Parameter “AN”: A Base64 Encoded, AES-256-CBC Encrypted string which will represent the Account Number when decrypted
    b. Parameter “IV”: A Base64 Encoded initialization vector (IV) string which will be used in decrypting the Account Number string
3. Base64 Decode both parameters
4. Using the AES-256-CBC method, decrypt the encrypted string (which was base64 decoded as part of Step #3) with the initialization vector decoded in Step #3 and the hash created in Step #1a
5. The decryption should then provide you the account number.

Java code

I am using CryptoJS to manually decrypt a string with a provided set of values. The secret is provided and then an SHA256 has is taken of it. The message and initialization vector are base 64 encoded. Here's what I am trying, but every time I run it, the output changes - how can that be?! I'm at the end of my wits...

// Key and take the hash of it
var secretKey = 'TESTING123Secret_Key';
var secretKeyHash = CryptoJS.SHA256(secretKey).toString(CryptoJS.enc.Hex);

// Base 64 encoded values
var accountNumberBase64 = 'nxjYfo4Stw63YBEcnjo3oQ==';
var initializationVectorBase64 = 'HnNcvu9AP9yl09APWkWnDQ==';

// decode the values provided above
var accountNumberEncrypt = atob(accountNumberBase64);
var initializationVector = atob(initializationVectorBase64);

// Use crypto to decrypt
var decrypted = CryptoJS.AES.decrypt(
    {
        ciphertext: accountNumberEncrypt,
        salt: ''
    },
  secretKeyHash,
  {
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.NoPadding,
      iv: initializationVector,
      salt: ''
  }
);
 console.log('   decrypted, by hand: ' + decrypted.toString(CryptoJS.enc.Hex));

the last line changes every time this is run (run it on page load) - same values provided every time, output is different.

How it is supposed to work:

Decryption Instructions:
1. A static, secret key will be shared which will be used for decryption (Secret Key TBD).
    a. HASH the secret key with SHA256, encode it to Hex and use the first 32 characters. This will be used as the KEY when decrypting.
2. Two pieces of information will be sent via the POST method
    a. Parameter “AN”: A Base64 Encoded, AES-256-CBC Encrypted string which will represent the Account Number when decrypted
    b. Parameter “IV”: A Base64 Encoded initialization vector (IV) string which will be used in decrypting the Account Number string
3. Base64 Decode both parameters
4. Using the AES-256-CBC method, decrypt the encrypted string (which was base64 decoded as part of Step #3) with the initialization vector decoded in Step #3 and the hash created in Step #1a
5. The decryption should then provide you the account number.

Java code

Share Improve this question edited Aug 13, 2017 at 8:37 Artjom B. 62k26 gold badges135 silver badges230 bronze badges asked Aug 12, 2017 at 17:13 James FJames F 5651 gold badge11 silver badges27 bronze badges 4
  • 1 There are some problems with your code such as passing the key as string instead of using WordArray: var secretKeyHash = CryptoJS.SHA256(secretKey);, but that and the other issues don't produce any sensible decryption (at least to me): 6497b502a3b2558263d2a9cd599d6bbe. Can you show the code that produced the IV and ciphertext? – Artjom B. Commented Aug 12, 2017 at 18:01
  • 1 You should never use a simple hash function to protect your user's passwords. You need to use a strong hashing scheme like PBKDF2, bcrypt, scrypt and Argon2. Be sure to use a high cost factor/iteration count. It is mon to choose the cost so that a single iteration takes at least 100ms. See more: How to securely hash passwords? – Artjom B. Commented Aug 12, 2017 at 18:03
  • @ArtjomB. thanks for menting, this was a request from a friend for some work help and I don't know the specifics of the actual encryption. I have updated what they have been told the decryption SHOULD be, which was all that was provided, as well as what they say works in Java here pastebin./kdy0NcnK – James F Commented Aug 12, 2017 at 23:33
  • Also, I find it so odd that the output changes every time the page is reloaded - does CryptoJS use some seed that I'm missing? I tried manually setting the salt to be the same. – James F Commented Aug 12, 2017 at 23:34
Add a ment  | 

1 Answer 1

Reset to default 5

There many issues with your code. It is hard to say what is really responsible for the non-deterministic decryption. I guess it is the fact that you're passing the key as a string which means that CryptoJS will assume that it is a password and try to use EVP_BytesToKey to derive a key from that. Since the salt is not set, CryptoJS probably has a bug that it generates a random salt for decryption (which it should not). You need to parse the key into a WordArray if you want to manually provide the key.

The other main issue is using non-CryptoJS methods for decoding (atob) which means that you get some data format that cannot be directly read by CryptoJS. CryptoJS relies on the internal WordArray for representing all binary data or expects all strings to be UTF-8-encoded.

Working code:

// Key and take the hash of it
var secretKey = 'TESTING123Secret_Key';
var secretKeyHash = CryptoJS.SHA256(secretKey).toString(CryptoJS.enc.Hex).slice(0,32);
secretKeyHash = CryptoJS.enc.Utf8.parse(secretKeyHash);

// Base 64 encoded values
var accountNumberBase64 = 'nxjYfo4Stw63YBEcnjo3oQ==';
var initializationVectorBase64 = 'HnNcvu9AP9yl09APWkWnDQ==';

var ct = CryptoJS.enc.Base64.parse(accountNumberBase64);
var iv = CryptoJS.enc.Base64.parse(initializationVectorBase64);

// Use crypto to decrypt
var decrypted = CryptoJS.AES.decrypt({
    ciphertext: ct
  },
  secretKeyHash, {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.NoPadding,
    iv: iv
  }
);
console.log('   decrypted, by hand: ' + decrypted.toString(CryptoJS.enc.Utf8));
<script src="https://cdn.rawgit./CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<script src="https://cdn.rawgit./CryptoStore/crypto-js/3.1.2/build/rollups/sha256.js"></script>
<script src="https://cdn.rawgit./CryptoStore/crypto-js/3.1.2/build/ponents/pad-nopadding-min.js"></script>

本文标签: javascriptCryptoJS decrypt changes every timeStack Overflow