使用 CryptoJS 在 Javascript 中加密并在 Java 中解密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33223926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 16:14:30  来源:igfitidea点击:

Using CryptoJS to encrypt in Javascript and decrypt in Java

javascriptjavaencryptionaescryptojs

提问by mdagis

I am trying to encrypt something in JavaScript using the google's https://code.google.com/p/crypto-js/#AESexactly as it is if the example. The problem is that where I am trying to decrypt it in Java the result is way different. The only difference that I can see is the padding (CryptoJs uses Pkcs7 whereas java uses Pkcs5) after reading a bit I realized that Pkcs7 and Pkcs5 are basically the same.

我正在尝试使用谷歌的https://code.google.com/p/crypto-js/#AES在 JavaScript 中加密一些东西,就像这个例子一样。问题是我试图用 Java 解密它的结果是不同的。我能看到的唯一区别是填充(CryptoJs 使用 Pkcs7 而 java 使用 Pkcs5)在阅读了一点之后我意识到 Pkcs7 和 Pkcs5 基本相同。

Here is a sample of the code that i do the encryption in Javascript:

这是我在 Javascript 中进行加密的代码示例:

var crypto = require('./aes.js');
var login = 'ABCD';
var key = crypto.CryptoJS.enc.Hex.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Hex.parse('0123456789012345');

var encrypted = crypto.CryptoJS.AES.encrypt(login, key, {iv: ive});
console.log('encrypted msg = ' + encrypted)

This is the code that I am using in Java to decrypt it:

这是我在 Java 中用来解密它的代码:

public String decrypt(byte[] cipherText) throws Exception {

    String psk = "0123456789012345";
    String iv = "0123456789012345";
    try {
        String encryptionKey = psk;
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        final SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(UTF8), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes(UTF8)));
        return new String(cipher.doFinal(cipherText), UTF8);
    } catch (BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException ex) {
        LOG.log(Level.SEVERE, ex.getMessage(), ex);
        throw new Exception(ex.getMessage());
    }
}

Do you have any idea why it fails that bad? Is it a different algorithm or do I fail somewhere else?

你知道为什么它失败得那么糟糕吗?它是一种不同的算法还是我在其他地方失败了?

回答by Artjom B.

You're not using the same key and IV in CryptoJS and Java. The key and IV in the CryptoJS are too short to be valid, because you're parsing a 16 character string as Hex which results in only 8 bytes, but AES supports only key sizes of 128, 192 and 256 bit.

您没有在 CryptoJS 和 Java 中使用相同的密钥和 IV。CryptoJS 中的密钥和 IV 太短而无效,因为您将 16 个字符的字符串解析为十六进制,结果只有 8 个字节,但 AES 仅支持 128、192 和 256 位的密钥大小。

Use

利用

var key = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');


Other considerations:

其他注意事项:

  • Always use a random IV. Since it doesn't have to be secret, you can prepend it to the ciphertext or send it along in another way.

  • Authenticate the ciphertexts with HMAC or use and authenticated mode like GCM to prevent some attacks such as padding oracle attack.

  • 始终使用随机 IV。由于它不必是秘密的,您可以将其添加到密文中或以其他方式发送。

  • 使用HMAC对密文进行认证,或者使用GCM等认证方式来防止一些攻击,比如padding oracle攻击。

回答by mdagis

Ok, I found the problem. Instead of passing as a parameter the encryptedI should pass encrypted.ciphertext. I now works perfect.

好的,我发现了问题。而不是作为参数传递,encrypted我应该传递encrypted.ciphertext。我现在工作完美。