Decrypt AES/CBC/PKCS5Padding with CryptoJS

江枫思渺然 提交于 2019-12-03 21:54:13

The problem is that you're using a 64 bit key as a 128 bit. Hashing.sha1().hashString(secretKey, Charsets.UTF_8) is an instance of HashCode and its toString method is described as such:

Returns a string containing each byte of asBytes(), in order, as a two-digit unsigned hexadecimal number in lower case.

It is a Hex-encoded string. If you take only 16 characters of that string and use it as a key, you only have 64 bits of entropy and not 128 bits. You really should be using HashCode#asBytes() directly.


Anyway, the problem with the CryptoJS code is manyfold:

  • The ciphertext must be a CipherParams object, but it is enough if it contains the ciphertext bytes as a WordArray in the ciphertext property.
  • The key must be passed in as a WordArray instead of a string. Otherwise, an OpenSSL-compatible (EVP_BytesToKey) key derivation function is used to derive the key and IV from the string (assumed to be a password).
  • Additional options are either unnecessary, because they are defaults, or they are wrong, because the blockSize is calculated in words and not bytes.

Here is CryptoJS code that is compatible with your broken Java code:

var str = 'CB5E759CE5FEAFEFCC9BABBFD84DC80C0291ED4917CF1402FF03B8E12716E44C';

console.log("Result: " + CryptoJS.AES.decrypt({
    ciphertext: CryptoJS.enc.Hex.parse(str.substring(32))
}, CryptoJS.enc.Utf8.parse(CryptoJS.SHA1("test").toString().substring(0,16)),  
{
  iv: CryptoJS.enc.Hex.parse(str.substring(0,32)),
}).toString(CryptoJS.enc.Utf8))
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/sha1.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>

Here is CryptoJS code that is compatible with the fixed Java code:

var str = 'F6A5230232062D2F0BDC2080021E997C6D07A733004287544C9DDE7708975525';

console.log("Result: " + CryptoJS.AES.decrypt({
    ciphertext: CryptoJS.enc.Hex.parse(str.substring(32))
}, CryptoJS.enc.Hex.parse(CryptoJS.SHA1("test").toString().substring(0,32)),  
{
  iv: CryptoJS.enc.Hex.parse(str.substring(0,32)),
}).toString(CryptoJS.enc.Utf8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/sha1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

The equivalent encryption code in CryptoJS would look like this:

function encrypt(plaintext, password){
    var iv = CryptoJS.lib.WordArray.random(128/8);
    var key = CryptoJS.enc.Hex.parse(CryptoJS.SHA1(password).toString().substring(0,32));
    var ct = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });
    return iv.concat(ct.ciphertext).toString();
}

console.log("ct: " + encrypt("plaintext", "test"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/sha1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!