Nodejs Crypto 解密报错“wrong final block length”
Nodejs Crypto 解密报错“wrong final block length”
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length at Decipher.Cipher.final (crypto.js:292:27) at Object.module.exports.decrypt
我用crypto模块加密的数据, 在解密的时候出现了这个错误 以下是我方法源码 function encrypt(str, secret) { var cipher, enc; cipher = crypto.createCipher(‘aes-256-cbc’, secret); enc = cipher.update(str, ‘utf8’, ‘hex’); enc += cipher.final(‘hex’); return enc; }, function decrypt(str, secret) { var dec, decipher; decipher = crypto.createDecipher(‘aes-256-cbc’, secret); dec = decipher.update(str, ‘hex’, ‘utf8’); dec += decipher.final(‘utf8’); return dec; }
Nodejs Crypto 解密报错“wrong final block length”
当你在使用Node.js的crypto
模块进行AES加密和解密时,可能会遇到“wrong final block length”的错误。这通常是因为数据长度或填充方式不正确导致的。
问题分析
这个问题通常是由于以下几个原因之一引起的:
- 数据长度:加密后的数据长度可能不是块大小的整数倍。
- 填充方式:加密和解密时使用的填充方式不一致。
- 密钥长度:AES-256需要一个256位(32字节)的密钥,如果密钥长度不对也会导致问题。
示例代码
以下是修改后的加密和解密函数,确保数据长度和填充方式的一致性:
const crypto = require('crypto');
// 加密函数
function encrypt(str, secret) {
const iv = crypto.randomBytes(16); // 初始化向量
const cipher = crypto.createCipheriv('aes-256-cbc', secret, iv);
let encrypted = cipher.update(str, 'utf8', 'hex');
encrypted += cipher.final('hex');
return iv.toString('hex') + ':' + encrypted; // 返回IV和加密后的字符串
}
// 解密函数
function decrypt(str, secret) {
const [ivHex, encrypted] = str.split(':'); // 分割IV和加密后的字符串
const iv = Buffer.from(ivHex, 'hex');
const decipher = crypto.createDecipheriv('aes-256-cbc', secret, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// 示例
const secret = crypto.randomBytes(32); // 生成32字节的密钥
const originalText = "Hello, World!";
const encryptedText = encrypt(originalText, secret);
console.log("Encrypted:", encryptedText);
const decryptedText = decrypt(encryptedText, secret);
console.log("Decrypted:", decryptedText);
解释
- 初始化向量(IV):在AES-CBC模式中,需要一个随机的初始化向量(IV)。每次加密时都应生成一个新的IV,并将其与加密后的数据一起存储或传输。
- 密钥长度:确保密钥长度为32字节(256位)。
- 填充方式:
crypto.createCipheriv
和crypto.createDecipheriv
方法会自动处理填充,因此不需要手动处理。
通过这种方式,可以避免“wrong final block length”的错误,并确保加密和解密过程的正确性。
我这边是ok的。
➜ crypto node -e "console.log(process.versions)"
{ http_parser: '1.0',
node: '0.10.32',
v8: '3.14.5.9',
ares: '1.9.0-DEV',
uv: '0.10.28',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1i' }
你两个方法用反了…
在使用 Node.js 的 crypto
模块进行 AES 加密和解密时,遇到 wrong final block length
错误通常是由于数据长度不匹配或者填充方式不一致导致的。这通常发生在解密过程中,如果输入数据长度不是正确的块大小(对于 AES-256-CBC 来说,块大小是 16 字节),则会报这个错误。
为了解决这个问题,我们需要确保在加密和解密过程中正确处理数据的长度和填充方式。通常的做法是使用固定长度的密钥和初始向量(IV),并且确保数据在加密前后的长度是一致的。
下面是改进后的加密和解密函数示例:
const crypto = require('crypto');
function encrypt(str, secret) {
const iv = crypto.randomBytes(16); // 使用随机的初始向量
const cipher = crypto.createCipheriv('aes-256-cbc', secret, iv);
let encrypted = cipher.update(str, 'utf8', 'hex');
encrypted += cipher.final('hex');
return iv.toString('hex') + ':' + encrypted; // 返回 IV 和加密后的数据
}
function decrypt(str, secret) {
const [ivHex, encrypted] = str.split(':'); // 分离 IV 和加密后的数据
const iv = Buffer.from(ivHex, 'hex');
const decipher = crypto.createCipheriv('aes-256-cbc', secret, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
关键点解释:
- 初始向量 (IV): 在加密和解密过程中都需要提供相同的 IV。在加密时生成一个随机的 IV,并将其与加密后的数据一起存储或传输。
- 数据格式: 确保加密和解密过程中的数据格式一致,即加密时的数据应为十六进制字符串,解密时的输入也应为十六进制字符串。
- 错误处理: 确保在解密过程中正确处理数据长度,避免出现
wrong final block length
错误。
通过以上改进,应该可以解决你在解密过程中遇到的 wrong final block length
错误。