gpt4 book ai didi

javascript - 为什么使用 Android 和 JavaScript 在 AES/CBC/ZeroBytePadding 中加密会为某些字符串返回不同的结果?

转载 作者:行者123 更新时间:2023-11-30 02:14:15 25 4
gpt4 key购买 nike

这是 JavaScript 中的代码:

<html>
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/pad-zeropadding-min.js"></script>
<!-- jquery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div id="0"></div>
<div id="1"></div>
<div id="2"></div>
<script>

var key = CryptoJS.enc.Utf8.parse('32_length_String');
var iv = CryptoJS.enc.Utf8.parse('32_length_String');
var message = '{"login":[{"username":"25697","passwd":"asdf"}]}';
$('#0').text("Message: "+message);

var encrypted = CryptoJS.AES.encrypt(message, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding, mode: CryptoJS.mode.CBC});
$('#1').text("Encrypted BASE64: "+encrypted);
$('#2').text("Encrypted HEX: "+encrypted.ciphertext);
</script>
</body>
</html>

这是安卓代码:

private static final String ZERO_PADDING_KEY = "32_length_String";
private static final String IV = "32_length_String";
private static final String CIPHER_ALGORITHM = "AES/CBC/ZeroBytePadding";

public static String encryptAESURL(String url) {
try {

byte[] key = ZERO_PADDING_KEY.getBytes("UTF-8");

SecretKeySpec sks = new SecretKeySpec(key, "AES");

byte[] iv = Arrays.copyOf(IV.getBytes("UTF-8"), 16);

IvParameterSpec ivspec = new IvParameterSpec(iv);

Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

// encryption pass
cipher.init(Cipher.ENCRYPT_MODE, sks, ivspec);

byte[] encryptedText = cipher.doFinal(url.getBytes("UTF-8"));

String resul = bytesToHex(encryptedText);
url = resul;
return resul;

} catch (Exception e) {
Log.e("ENCRYPT ERROR", e.getMessage());
e.printStackTrace();
// throw new CryptoException("Unable to decrypt", e);

}
return url;

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}

问题是使用字符串:{"login":[{"username":"25697","passwd":"asdf"}]}

JavaScript 代码返回十六进制:

c88928b4542a8faa774f27670c563fdfcb8dcc8ae554d3dd05a86ac7869d91d36a170a4e093b75e2702e8374f206e7f4

Android代码返回十六进制:

C88928B4542A8FAA774F27670C563FDFCB8DCC8AE554D3DD05A86AC7869D91D36A170A4E093B75E2702E8374F206E7F4DF33A2FBEE7FD2DBC1ED0430F3E45DCF

这两个十六进制是相似的,但在 android 代码中,末尾有更多字符,加密其他字符串,如:{"login":[{"username":"25697","passwd":"asd"}]}或者{"login":[{"username":"25697","passwd":"asdfg"}]} 返回相同的十六进制。我找不到 Android 代码中的问题,为什么会发生这种情况。

最佳答案

问题是基于 BouncyCaSTLe 的 Android 的 ZeroBytePadding 将始终添加填充,但 CryptoJS 不会。

AES 是一种 block 密码,因此仅对 16 字节的完整 block 进行操作。 CryptoJS 的 ZeroPadding 只会添加这么多的 0x00 字节,直到达到 block 大小的倍数。另一方面,Android 的 ZerBytePadding 会做同样的事情,但如果明文已经是 block 大小的倍数,那么它将添加一个完整的 0x00 字节 block 。

在您的例子中,第一个明文是 48 个字节,这意味着 ZeroBytePadding 将添加一个额外的 block 。

Android的密码是基于BouncyCaSTLe的,是discussed before ,为什么BouncyCaSTLe会这样做。它不会是“固定的”。

我建议您使用 PKCS#5/PKCS#7 填充(它们相同),这使您能够在明文末尾使用 0x00 字节,这在 ZeroPadding 中是不可能的。


不要忘记,您应该通过使用消息验证码来防止您的密文被操纵。例如,在具有不同 key 的密文上使用 HMAC-SHA256。

关于javascript - 为什么使用 Android 和 JavaScript 在 AES/CBC/ZeroBytePadding 中加密会为某些字符串返回不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29626232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com