【问题标题】:AES Encrypt using CryptoJS使用 CryptoJS 进行 AES 加密
【发布时间】:2017-01-16 14:20:43
【问题描述】:

我需要使用 JavaScript 实现 AES 加密。使用 AES/CBC/NoPadding 模式并创建了一种完成 16 个长度块的方法。我已经使用 Java 解决了它。它看起来像:

public static String encrypt(byte[] key, byte[] initVector, String value) {
    try {
        IvParameterSpec iv = new IvParameterSpec(initVector);
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(completeBlocks(value));
        return Base64.encodeBase64String(encrypted);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException ex) {
        System.out.println("Error: " + ex);
    }

    return null;
}

/**
 * Completes 16 lenght blocks
 *
 * @param message
 *
 *
 */
static byte[] completeBlocks(String message) {
    try {

        int bytesLenght = message.getBytes("UTF-8").length;
        if (bytesLenght % 16 != 0) {
            byte[] newArray = new byte[bytesLenght + (16 - (bytesLenght % 16))];
            System.arraycopy(message.getBytes(), 0, newArray, 0, bytesLenght);
            return newArray;
        }

        return message.getBytes("UTF-8");

    } catch (UnsupportedEncodingException ex) {
        System.out.println("" + ex);
    }
    return null;
}

public static void main(String[] args) {

    String key = "253D3FB468A0E24677C28A624BE0F939";
    String strToEncrypt = "My Secret text";
    final byte[] initVector = new byte[16];
    String resultado = encrypt(new BigInteger(key, 16).toByteArray(), initVector, strToEncrypt.trim());
    System.out.println("ENCRYPTED:");
    System.out.println(resultado);
}

使用输入 key = 253D3FB468A0E24677C28A624BE0F939strToEncrypt = "My Secret text" 和 ceros IV。它抛出

7StScX3LnPUly/VNzBes0w==

我知道这是所需的输出。这是正确的! 我尝试使用 JavaScript 复制它。我使用了 CryptoJs 库。但我无法产生相同的 Java 输出。我试过了:

var text = "My Secret text";
var key = CryptoJS.enc.Base64.parse("253D3FB468A0E24677C28A624BE0F939");
var iv  = CryptoJS.enc.Base64.parse("                ");
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log(encrypted.toString());

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
console.log(decrypted.toString(CryptoJS.enc.Utf8));

使用相同的输入,我得到De+CvPVIyiBX2//EE6gXTg== 作为输出。我究竟做错了什么?如何获得相同的 Java 输出?非常感谢!!

【问题讨论】:

  • 看来cryptojs不支持CBC模式。
  • 另外,您的密钥以十六进制而不是 base64 的形式给出,并且为 base64 提供空格与零数组不同。
  • @TamasHegedus 我认为你是对的!!遗憾的是,不支持 CBC 模式。我找到了这个:github.com/ricmoo/aes-js。看起来它支持CBC模式。我要试试!!非常感谢!
  • Sergio,事实证明它确实支持 CBC。它在 github.com/sytelus/CryptoJS/blob/… 中实现,而不是在 mode-cbc.js 中作为其他一些模式。
  • @TamasHegedus 我正在检查它!你看起来很棒!我要试试!谢谢

标签: javascript java encryption aes


【解决方案1】:

假设您将修复空 IV 之类的问题,并且这是一个概念证明,您的代码将失败,因为:

  1. 你在Java中不使用padding,你需要在JS中使用同样的
  2. 您在 Java 中手动填充空值,您需要在 JS 中执行相同操作
  3. 您对密钥进行 base64 解码,但不是 base64(它是十六进制字节字符串)
  4. Java IV 是一个空数组,但在 JS 中您使用空格(并错误地将其视为 base64)。

在 JS 中复制输出:

CryptoJS.pad.NoPadding = {pad: function(){}, unpad: function(){}};

var text = "My Secret text\0\0";
var key  = CryptoJS.enc.Hex.parse("253D3FB468A0E24677C28A624BE0F939");
var iv   = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");

var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.NoPadding});

console.log(encrypted.toString());

为:

7StScX3LnPUly/VNzBes0w==

【讨论】:

  • 晚了几分钟。他让我使用了自定义填充。
  • 另外我想指出自定义填充函数存在缺陷,因为它在多个地方调用getBytes时使用了不同的编码。
  • @Alex K. 这看起来很不错!!我有一个疑问!我怎么能设法再次解密!!?谢谢!我试过了:var decrypt = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
  • 终于用上了; var decrypted = CryptoJS.AES.decrypt(text.toString(), key, {iv: iv}); console.log(decrypted.toString(CryptoJS.enc.Utf8));
  • @SergioDavidRomero 解密不起作用。你为什么要传递 text.toString() 而不是 encrypt.toString() ?
【解决方案2】:

如果你想使用自定义 IV 进行加密,那么你可以像这样加密......

    let iv = CryptoJS.lib.WordArray.random(IV_LENGTH);
    const key = CryptoJS.enc.Utf8.parse(ENCRYPTION_KEY);

    let encrypted = CryptoJS.AES.encrypt(text, key, { iv })

    const encrypted = encrypted.iv+':'+encrypted.ciphertext

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多