Java 使用 CryptoJS 进行 AES 加密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41678504/
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-08-11 23:35:18  来源:igfitidea点击:

AES Encrypt using CryptoJS

javascriptjavaencryptionaes

提问by Sergio David Romero

I need to implement AES encryption using JavaScript. Used AES/CBC/NoPadding Mode and created a method to complete 16 lenght blocks. I already solved it using Java. It looks like:

我需要使用 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);
}

With inputs key = 253D3FB468A0E24677C28A624BE0F939, strToEncrypt = "My Secret text"and ceros IV. It throws

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

7StScX3LnPUly/VNzBes0w==

7StScX3LnPUly/VNzBes0w==

I Know it's the desired output. It's right! I tried to replicate this using JavaScript. I used CryptoJs library. But i wasn't able to produce same Java's output. I have tryed:

我知道这是所需的输出。这是正确的!我尝试使用 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));

Using the same inputs, i get De+CvPVIyiBX2//EE6gXTg==as output. What am I doing wrong? How can i get same Java's output? Thanks a lot!!

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

采纳答案by Alex K.

Assuming you will fix things like the empty IV & that this is a proof of concept, your code fails because:

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

  1. You use no padding in Java, you need to use the same in JS
  2. You manually pad with nulls in Java, you need to do the same in JS
  3. You base64 decode the key but its not base64 (its a hexadecimal string of bytes)
  4. The Java IV is an array of nulls but in JS you use whitespace (and erroneously treat it as base64).
  1. 您在 Java 中不使用填充,您需要在 JS 中使用相同的填充
  2. 您在 Java 中手动填充空值,您需要在 JS 中执行相同操作
  3. 你 base64 解码密钥,但它不是 base64(它是一个十六进制的字节串)
  4. Java IV 是一个空数组,但在 JS 中您使用空格(并错误地将其视为 base64)。

To duplicate the output in JS:

在 JS 中复制输出:

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

var text = "My Secret text
    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
##代码##"; 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());

For:

为了:

7StScX3LnPUly/VNzBes0w==

7StScX3LnPUly/VNzBes0w==

回答by Sagar M

If you want to encrypt using custom IV, then you can encrypt like...

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

##代码##