我已经在 java 中使用 AES 加密,并尝试在 javascript 中解密
Java:
byte[] input = "data".getBytes();
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] thedigest = md.digest("ENCRYPTION_KEY".getBytes("UTF-8"));
SecretKeySpec skc = new SecretKeySpec(Arrays.copyOf(thedigest, 16), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skc);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
String encryptData = Base64.getUrlEncoder().encodeToString(cipherText);
// Base64.encodeToString(cipherText, Base64.DEFAULT);
System.out.println("encryptString:.......... "+encryptData);
Node :
var crypto = require('crypto');
let keyStr = "ENCRYPTION_KEY";
var text = 'infodba';
var hashPwd =crypto.createHash('sha256').update(keyStr,'utf8').digest();
var key=[] ;
for (i = 0; i < 16; i++) {
key[i] = hashPwd[i];
}
var keyBuffer = new Buffer(hashPwd);
var decipherIV = crypto.createDecipheriv('aes-256-ecb', keyBuffer,'');
var cipherTxtBuffer = new Buffer('encryptedData','hex');
var output = decipherIV.update(cipherTxtBuffer);
output= output+decipherIV.final();
console.log("Dec Output "+output);
在运行 Node JS 代码时出现错误
内部/加密/cipher.js:174 const ret = this[kHandle].final(); ^
错误:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length 在 Decipheriv.final (internal/crypto/cipher.js:174:29) 在解密 (D:\TestJS\index.js:32:30)
最佳答案
Java 代码仅使用 SHA256 哈希的前 16 个字节作为 key ,因此必须相应地截断哈希:
var keyStr = 'ENCRYPTION_KEY';
var hashPwd = crypto.createHash('sha256').update(keyStr, 'utf8').digest();
var keyBuffer = Buffer.from(hashPwd.subarray(0, 16));
一个 16 字节的 key 对应于 AES-128,因此必须使用 'aes-128-ecb'
进行解密(而不是 'aes-256-ecb'
).此外,密文是 Base64url 编码的,因此必须对其进行 Base64url 解码(而不是十六进制解码):
var encryptedData = 'dkcvstQcGMQUJ1EJbHs3eY6j_0DjWqYTDGmedmUZwWs=';
var decipherIV = crypto.createDecipheriv('aes-128-ecb', keyBuffer,'');
var output = Buffer.concat([decipherIV.update(encryptedData, 'base64url'), decipherIV.final()]);
output
是一个缓冲区,可能必须进行 UTF-8 解码:
console.log(output.toString('utf8')); // §3.1: The fee is $3,000.
通过这些更改,NodeJS 代码解密了使用 Java 代码创建的密文。
安全:
- ECB 模式不安全,不应使用。现在通常使用经过身份验证的加密(例如 GCM),或者至少使用带有 IV 的模式(例如 CBC)。
- 使用像 SHA256 这样的(快速)摘要作为 key 派生是不安全的。更安全的是专用 key 派生函数,如 Argon2 或 PBKDF2。
- 在 Java 代码中,
Cipher
对象仅使用算法 ("AES"
) 进行实例化。这并不健壮,因为依赖于提供者的默认值将应用于模式和填充。对于 SunJCE,这些是 ECB 和 PKCS#5 填充,NodeJS 代码是为其量身定制的。对于其他提供者,这可能有所不同,因此 NodeJS 代码将不再兼容。因此,应该完全指定,例如“AES/ECB/PKCS5Padding”
。 - 同样,使用
getBytes()
对明文进行编码时,应指定编码,否则使用平台相关的默认编码。
关于java - 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH' 在 Node js 中解密时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72932201/