Decrypt AES/CBC/PKCS5Padding with CryptoJS

前端 未结 2 1543
Happy的楠姐
Happy的楠姐 2021-02-11 09:46

I generate 128bit AES/CBC/PKCS5Padding key using Java javax.crypto API. Here is the algorithm that I use:

public static String encryptA         


        
2条回答
  •  夕颜
    夕颜 (楼主)
    2021-02-11 10:09

    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))
    
    

    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))
    
    

    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"));
    
    

提交回复
热议问题