java - 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH' 在 Node js 中解密时

标签 java node.js encryption aes node-crypto

我已经在 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/

相关文章:

java - 带有必须实现 Serialized 的参数的静态方法

Java AES 解密得到解密的十六进制而不是解密的字符串

java - 使用 jsf 附加问题的计算器应用程序

node.js - n <version> 命令不激活指定版本

node.js - Node 应用程序之间通过 MQTT 进行简单通信

java - 使用 AES256 对称分组密码的图像加密/解密

java - 在字符串中插入多个字符而不是一个字符

java - 如何在jsp页面中添加一个递增的id

java - 我需要 "Java Advanced Imaging API"来学习Java中的 "image processing"吗

node.js - 为什么docker镜像太大? NodeJS 应用程序