【问题标题】:Using CryptoJS to encrypt in Javascript and decrypt in Java使用 CryptoJS 在 Javascript 中加密和在 Java 中解密
【发布时间】:2015-10-19 21:06:44
【问题描述】:

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

这是我在 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)

这是我在 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());
    }
}

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

【问题讨论】:

    标签: javascript java encryption aes cryptojs


    【解决方案1】:

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

    使用

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

    其他注意事项:

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

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

    【讨论】:

    • 这是一个很好的观点。尽管如此,问题仍然存在。我有一个 java 算法,它使用与我之前发布的解密字符串相同的设置来加密字符串 ABCD。奇怪的是Java加密的结果是具有以下字节的字节数组:534A5782E4AB47B71C4DC7AFB5A64F5C CryptoJS的加密字符串是U0pXguSrR7ccTcevtaZPXA==
    • 您还没有显示您从 CryptoJS 解析结果的代码部分。请注意,一个是十六进制编码的,另一个是 Base64 编码的。无需实际查看文档或源代码即可轻松发现差异。
    • 使用 enc.Utf8.parse javascript 正在生成 "=U0pXguSrR7ccTcevtaZPXA==" 但不能按照 java 方法的要求将其设为 16 的倍数。有人可以帮忙吗?
    • ok:您应该添加如何有效地解密生成的代码:decrypt(new Base64().decode("U0pXguSrR7ccTcevtaZPXA".getBytes()))) 删除前导和尾随“=”,因为它是不明显。 (此处使用apache常用base64)
    • @user1767316 我不知道您是如何生成“=U0pXguSrR7ccTcevtaZPXA==”的以及它应该是什么。你应该问一个包含所有细节的新问题。 Stack Overflow 不是论坛。
    【解决方案2】:

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

    【讨论】:

    • 如何将密文传递给后端?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多