PHP的AES-256-CBC加解密函数转NodeJS时密钥长度问题求解
兼容PHP AES-256-CBC加解密的NodeJS实现方案
核心问题原因
- PHP的openssl扩展对不符合长度要求的密钥,会自动用空字节(
\0)填充到对应算法要求的长度:AES-256要求32字节密钥,你使用的9位字符串crocodile会被自动补充23个空字节凑够32字节。NodeJS的crypto模块没有做这个自动补位逻辑,因此直接传入9位字符串会抛出Invalid key length错误。 - 原有PHP代码使用固定的16位空字节作为IV,你编写的NodeJS代码使用随机生成的IV,逻辑不匹配,即使修复密钥长度也无法兼容历史加密数据。
兼容实现代码
const crypto = require('crypto'); // 固定参数和PHP保持完全一致 const ENCRYPTION_METHOD = 'AES-256-CBC'; const RAW_KEY = 'crocodile'; // 生成符合要求的32字节密钥:原始密钥放在开头,剩余位置用空字节填充,和PHP逻辑完全对齐 const SECRET_KEY = Buffer.alloc(32); Buffer.from(RAW_KEY, 'utf8').copy(SECRET_KEY); // 生成固定16位空字节IV,和PHP逻辑一致 const IV = Buffer.alloc(16, 0); /** * 加密方法,和PHP encrypt函数输出完全一致 * @param {string} plain_text 待加密的明文字符串 * @returns {string} base64格式的加密结果 */ function encrypt(plain_text) { const cipher = crypto.createCipheriv(ENCRYPTION_METHOD, SECRET_KEY, IV); let encrypted = cipher.update(plain_text, 'utf8', 'base64'); encrypted += cipher.final('base64'); return encrypted; } /** * 解密方法,和PHP decrypt函数输入输出完全一致 * @param {string} encryptedMessage base64格式的加密字符串 * @returns {string} 解密后的明文字符串 */ function decrypt(encryptedMessage) { const decipher = crypto.createDecipheriv(ENCRYPTION_METHOD, SECRET_KEY, IV); let decrypted = decipher.update(encryptedMessage, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } module.exports = { encrypt, decrypt };
验证说明
用原有PHP代码加密的任意字符串,都可以用上述NodeJS代码正常解密;反之用NodeJS加密的结果也可以用原有PHP代码正常解密,完全兼容历史数据。
内容的提问来源于stack exchange,提问作者Abhinandan Chakraborty
相关产品推荐
相关产品推荐

