解决CryptoJS Encryptor JAVA Decryptor报错问题

前段时间遇到一个需求,前端用CryptoJS加密,例如用AES和3DES,后台用JAVA解密.网上对于JAVA的AES和3DES算法DEMO有很多,自己去实现了一下,都能实现自己加密后自己解密.但是关键是前端用CryptoJS加密后,自己后端怎么都解密不出来,而且经常报错说key size不合法等等.

这里多插一句话,之前没太了解加密解密的内容,之后才发现原来相同的明文和密钥加密出来的密文是可以不同的,而且还能解出来.原谅我见识短浅!!!

之后我看了一下这些站长工具的js,都是这样的:


$("#encrypt_result").val(CryptoJS.AES.encrypt($("#msg_source").val(),$("#pwd").val()));

这里关键的一点是js没有指明用什么模式和用什么填充方式,另外iv也没有指定,所以刚开始让我很抓狂,你前端怎么做的不写清楚,我后端怎么去解啊!!!

最后是查到了stackflow一位大神的回答后才知道怎么去做的:

CryptoJS implements the same key derivation function as OpenSSL and the same format to put the IV into the encrypted data. So all Java code that deals with OpenSSL encoded data applies.

https://stackoverflow.com/questions/41432896/cryptojs-aes-encryption-and-java-aes-decryption

具体的英文意思很简单,这里不重复,反正就是用处理OpenSSL的代码处理一下就可以

public static void main(String[] args) throws Exception {
     String secret = "René Über";

     String cipherText = "U2FsdGVkX1+tsmZvCEFa/iGeSA0K7gvgs9KXeZKwbCDNCs2zPo+BXjvKYLrJutMK+hxTwl/hyaQLOaD7LLIRo2I5fyeRMPnroo6k8N9uwKk=";

    byte[] cipherData = Base64.getDecoder().decode(cipherText);

    byte[] saltData = Arrays.copyOfRange(cipherData, 8, 16);

    MessageDigest md5 = MessageDigest.getInstance("MD5");

    final byte[][] keyAndIV = GenerateKeyAndIV(32, 16, 1, saltData, secret.getBytes(StandardCharsets.UTF_8), md5);

    SecretKeySpec key = new SecretKeySpec(keyAndIV[0], "AES");

    IvParameterSpec iv = new IvParameterSpec(keyAndIV[1]);

    byte[] encrypted = Arrays.copyOfRange(cipherData, 16, cipherData.length);

    Cipher aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");

    aesCBC.init(Cipher.DECRYPT_MODE, key, iv);

    byte[] decryptedData = aesCBC.doFinal(encrypted);

    String decryptedText = new String(decryptedData, StandardCharsets.UTF_8);

    System.out.println(decryptedText);
}

public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {

    int digestLength = md.getDigestLength();

    int requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength;

    byte[] generatedData = new byte[requiredLength];

    int generatedLength = 0;

    try {

        md.reset();

        // Repeat process until sufficient data has been generated

        while (generatedLength < keyLength + ivLength) {

            // Digest data (last digest if available, password data, salt if available)

            if (generatedLength > 0)

                md.update(generatedData, generatedLength - digestLength, digestLength);

            md.update(password);

            if (salt != null)

                md.update(salt, 0, 8);

            md.digest(generatedData, generatedLength, digestLength);

            // additional rounds

            for (int i = 1; i < iterations; i++) {

                md.update(generatedData, generatedLength, digestLength);

                md.digest(generatedData, generatedLength, digestLength);

            }

            generatedLength += digestLength;

        }

        // Copy key and IV into separate byte arrays

        byte[][] result = new byte[2][];

        result[0] = Arrays.copyOfRange(generatedData, 0, keyLength);

        if (ivLength > 0)

            result[1] = Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);

        return result;

    } catch (DigestException e) {

        throw new RuntimeException(e);

    } finally {

        // Clean out temporary data

        Arrays.fill(generatedData, (byte)0);

    }

}

这个代码和其他一般代码不同的是GenerateKeyAndIV方法,这也是我唯一看不懂的地方.比较有意思的是,上面代码是拿来解密AES的,如果换成3DES的话,代码其实只要改下GenerateKeyAndIV中的参数,keyLength设为24,ivlength设为8,然后什么AES都改成DESede就可以了.(用AES的麻烦在于它的key有256位,jdk默认支持128位的key,因此要替换jdk的jar包)

最后科普一下关于CryptoJs AES的加密模式

The modes of operation currently available are:

CBC (the default)

CFB

CTR

OFB

ECB

And the padding schemes currently available are:

Pkcs7 (the default)

Iso97971

AnsiX923

Iso10126

ZeroPadding

NoPadding

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。