Node.js crypto库AES-128-ECB加密报错:数据长度非块长整数倍
解决AES加密时"data not multiple of block length"错误
嘿,这个错误我之前踩过坑,我来给你拆解一下!
错误原因
你看到的error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length,本质是因为AES是块加密算法,它要求每次加密的数据长度必须是块大小的整数倍(AES-128的块大小是16字节)。
你代码里设置了cipher.setAutoPadding(false),这就关掉了Node.js crypto库默认的PKCS#7自动填充功能——原本这个功能会自动把你的明文补到16字节的倍数,现在你关了它,而你的JSON字符串转成Buffer后长度刚好不是16的倍数,所以cipher.final()就报错了。
另外提一句:你用的是AES-128-ECB模式,这个模式其实不需要IV(初始化向量),你代码里生成了iv但没用到,这个可以去掉避免混淆~
解决方案
有两种方式可以解决这个问题,选哪种看你的需求:
方案1:开启自动填充(最简单)
如果你没有特殊的填充要求(比如不需要和其他自定义填充的系统交互),直接删掉cipher.setAutoPadding(false)这一行就行,crypto会自动帮你处理填充,代码修改后如下:
self.test = async function(info, object) { let message = { info: info, object: object }; let key = Buffer.from(config.key, 'utf8'); // ECB模式不需要IV,这里可以移除iv相关代码 let cipher = crypto.createCipheriv("aes-128-ecb", key, ''); // 删掉setAutoPadding(false),用默认的自动填充 let encrypted = cipher.update(JSON.stringify(message)); encrypted = Buffer.concat([encrypted, cipher.final()]); encrypted = encrypted.toString('base64'); console.log(encrypted); }
方案2:手动实现填充(适合需要自定义填充的场景)
如果必须关闭自动填充,那你得手动把明文补到16字节的倍数,推荐用和默认一致的PKCS#7填充算法,这样解密的时候也能统一处理。先写一个填充函数:
// PKCS#7填充函数:把buffer补到blockSize的整数倍 function pkcs7Pad(buffer, blockSize) { const paddingLength = blockSize - (buffer.length % blockSize); // 填充的每个字节的值等于填充长度(比如需要补3字节,就填充0x03,0x03,0x03) const padBuffer = Buffer.alloc(paddingLength, paddingLength); return Buffer.concat([buffer, padBuffer]); }
然后修改你的加密逻辑,先填充再加密:
self.test = async function(info, object) { let message = { info: info, object: object }; let key = Buffer.from(config.key, 'utf8'); let cipher = crypto.createCipheriv("aes-128-ecb", key, ''); cipher.setAutoPadding(false); // 把消息转成Buffer并手动填充 const messageBuffer = Buffer.from(JSON.stringify(message)); const paddedBuffer = pkcs7Pad(messageBuffer, 16); // AES-128块大小是16字节 let encrypted = cipher.update(paddedBuffer); encrypted = Buffer.concat([encrypted, cipher.final()]); encrypted = encrypted.toString('base64'); console.log(encrypted); }
额外建议
- 密钥长度检查:AES-128要求密钥是16字节(128位),如果你的
config.key转成utf8后不是16字节,Node.js会自动截断或补全,这可能导致加密不符合预期,建议确认密钥长度是否正确。 - ECB模式的安全性:ECB模式是比较不安全的,相同的明文块会生成相同的密文块,容易被攻击。既然你因为UDP的限制不能用CBC(依赖消息顺序),可以考虑试试CTR模式——它属于流加密模式,不需要处理填充,而且每个块可以独立解密,即使UDP包乱序,只要你能跟踪每个块的计数器值,就能正确解密,更适合UDP场景。
内容的提问来源于stack exchange,提问作者0rka
相关产品推荐
相关产品推荐

