Java AES使用CryptoJS在Javascript中加密

Java AES Encrypt in Javascript using CryptoJS

本文关键字:Javascript 加密 CryptoJS AES 使用 Java      更新时间:2023-09-26

我正在尝试使用Javascript和CryptoJS复制Java应用程序中使用的加密。我不太确定应该如何复制SecretKeySpec,因为CryptoJS似乎需要一个字符串作为密钥。

以下是我需要在JS中复制的Java加密代码:

public byte[] encrypt(byte[] origin)
    {
        String key = "testkey";
        SecretKeySpec sks = new SecretKeySpec(convertAESKey(key), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] iv = new byte[16];
        cipher.init(Cipher.ENCRYPT_MODE, sks, new IvParameterSpec(iv));
        return cipher.doFinal(origin);
    }
private byte[] convertAESKey(String key)
   {
        byte[] keyBytes;
        keyBytes = key.getBytes("UTF-8");
        byte[] keyBytes16 = new byte[16];
        System.arraycopy(keyBytes, 0, keyBytes16, 0,
                Math.min(keyBytes.length, 16));
        return keyBytes16;
    }
}

到目前为止我的JS代码:

var iv = new Uint8Array(16);
var key = "testkey";
var encrypted = CryptoJS.AES.encrypt(
    someByteArray,
    key,
    {
        iv: iv,
        mode: CryptoJS.mode.CBC
    }
);

此外,密码的最终输出是一个加密的字节数组。CryptoJS的最终输出似乎是一个带有密文的对象。有没有一种方法可以将输出作为字节数组?

我现在唯一能想到的就是将加密的响应转换为字符串,然后将其转换为字节数组,但这似乎与Java加密的输出不匹配。

CryptoJS默认不处理Uint8Array,所以我不会使用它,而是使用默认的WordArray来表示二进制数据。

var iv = CryptoJS.lib.WordArray.create([0, 0, 0, 0]);
var key = "testkey";
key = CryptoJS.enc.Utf8.parse(key);
for (var i = key.words.length; i < 4; i++) {
    key.words[i] = 0;
}
key.sigBytes = 16;
key.clamp();
var encrypted = CryptoJS.AES.encrypt(
    someByteArray,
    key,
    {
        iv: iv,
        mode: CryptoJS.mode.CBC
    }
);
console.log(encrypted.ciphertext.toString(CryptoJS.enc.Hex));

这将给出一个十六进制字符串,可以很容易地与Java生成的密文进行比较。


这个代码不是很安全:

  • IV必须是不可预测的(读作:随机(。不要使用静态IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前何时发送了相同的消息前缀。IV不是秘密,所以你可以把它和密文一起发送。通常情况下,它只是在密文之前进行预处理,并在解密之前进行切片。

  • 密钥必须是随机的(读作:看起来像随机噪声(。文本看起来不是随机的,你会通过(错误地(使用密码作为密钥来严重降低你的安全性。如果你有一个密码,那么你需要使用PBKDF2、bcrypt、scrypt或Argon2等具有高迭代次数/成本因子的东西从中导出密钥。

  • 您应该验证您的密文,以便检测(恶意(操纵。如果你不这样做,那么它可能很容易受到填充预言机的攻击。身份验证可以通过GCM或EAX等已验证的操作模式来完成,或者使用具有强MAC的先加密后MAC方案(如HMAC-SHA256(来完成。