gpt4 book ai didi

javascript - 与 java 相比, Node 中的 AES 加密产生不同的输出

转载 作者:行者123 更新时间:2023-11-29 04:11:25 34 4
gpt4 key购买 nike

我正在尝试将用于 AES ECB 加密的 Java 代码移植到 node.js 中

问题是 java 和 node 的输出不一样。

这是java代码

 public static final String DEFAULT_ENCODING = "UTF-8";
public static final String SEC_PROVIDER = "SunJCE";
public static final String AES_ALGORITHM = "AES";
public static final String RIJNDAEL_CIPHER = **"Rijndael/ECB/NoPadding"**;
public static final int **CIPHER_PAD_SIZE = 32**;
public static final String HEX_KEY = "3b6ce332ca3b6519eac769710f41ca5c";

public static String encryptData(String text, String hexKey) throws
Exception {
byte[] b1 = Hex.decodeHex(HEX_KEY.toCharArray());
SecretKey key = new SecretKeySpec(b1, AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(RIJNDAEL_CIPHER, SEC_PROVIDER);
text = padRightToMod(text, CIPHER_PAD_SIZE);
byte[] buf = text.getBytes(DEFAULT_ENCODING);
cipher.init(Cipher.ENCRYPT_MODE, key);
buf = cipher.doFinal(buf);
String result = new String(Hex.encodeHex(buf));
result = result.toUpperCase();
return result;
}

// ensure block size of 32
public static String padRightToMod(String text, int mod) {
if (text == null || mod <= 0) {
return text;
}
final int len = text.length();
StringBuilder buf = new StringBuilder(512);
buf.append(text);
for (int i = len; i % mod > 0; i++) {
buf.append(" ");
}
String rs = buf.toString();
System.out.println(rs.length());
return rs;
}

// Call to the encrypt function

String encText = encryptData("Hello", HEX_KEY);

结果为CC0AC95B5FFD4758DBFA40F909C285F0F86A8F19ED1A12C1BFC098348A2AC683

还有这个 javascript 代码

crypto = require('crypto');

function encrypt(data,key) {
var cipher = crypto.createCipher('**aes-128-ecb**', key); //create aes cipher
var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
return encrypted;
}

function padRightTo32(str) // ensure block size of 32
{
len=str.length;
for(i=len; i%32>0; i++){
str=str +" ";
}
return str;
}

// call to encryption function
hexkey="3b6ce332ca3b6519eac769710f41ca5c"
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);

结果是1B928CF3C18D53BA5138DD1484D181939FD2B7BB2A17AE6A79664488B5C12652

====更新======

我试过了 https://github.com/Snack-X/rijndael-js使用此代码在 github 上实现

const Rijndael = require("./node_modules/node-rijndael-master");
function padRightTo32(str)
{
len=str.length;

for(i=len; i%32>0; i++){
str=str +" ";
}
console.log(str);
console.log(str.length);
return str;
}
let key = "3b6ce332ca3b6519eac769710f41ca5c";
let original = padRightTo32("Hello");
let cipher = new Rijndael(key, "ecb");
let ciphertext = cipher.encrypt(original, 128);
console.log(ciphertext.toString("hex"));

我得到这个结果 e97282fb5838a9c78e6df1f1b4aad108aa010418ec573d74b9c991f4e897e752 但不是我从 java 中得到的加密文本。尝试 256 block 大小也无济于事。

我遗漏了什么会导致不同的输出?

最佳答案

关于您的 key ,您必须使用缓冲区将您的十六进制字符串转换为二进制数据(参见例如 Encrypt binary data with aes-ecb on node.js)。

此外,您必须使用方法 crypto.createCipheriv 来实例化密码(参见例如 https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options )。当前使用的(已弃用)方法 crypto.creataCipher 需要密码并根据密码生成 key (参见例如 https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options)。

下面的代码

crypto = require('crypto');

function encrypt(data,key) {
var cipher = crypto.createCipheriv('aes-128-ecb', key,''); //create aes-128 cipher
var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
return encrypted;
}

function padRightTo32(str) { // ensure block size of 32

len=str.length;
for(i=len; i%32>0; i++) {
str=str +" ";
}
return str;
}

// call to encryption function
var hexKey = new Buffer('3b6ce332ca3b6519eac769710f41ca5c', 'hex'); // 16 Byte-key
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);

有输出

cc0ac95b5ffd4758dbfa40f909c285f0f86a8f19ed1a12c1bfc098348a2ac683

这等于 Java 代码的输出。

在 Java 中, key 的长度定义了使用的 AES 变体,例如如果选择 16 字节 key ,则使用 AES-128,如果选择 32 字节 key ,则使用 AES-256。在 nodejs 代码中,您必须显式指定 AES 变体,即 aes-128-ecb 用于 16 字节 key ,aes-256- ecb 用于 32 字节 key 等。

正如评论中提到的 ECB 不是安全模式(参见例如 https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption)。

我不知道 Rijndael/ECB/NoPaddingAES/ECB/NoPadding 在 Java 中的密码实例化方面是否真的有区别。在我的测试用例中,至少结果是相同的。因此,对于 nodejs-code,应该选择 aes-128-ecb(对于 16 字节 key )或 aes-256-ecb(对于 32 字节 key )工作。

关于javascript - 与 java 相比, Node 中的 AES 加密产生不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54874072/

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