我有一个 PHP 脚本,用于使用 openssl_encrypt() 和 aes-256-cbc 算法加密数据。使用 PHP 加密/解密效果很好,这是一个旧脚本。我一直在尝试解密使用 NodeJS 和加密模块的数据。
用于调试目的的信息:
存储在数据库中的 base64 字符串包含:加密数据_b64 + iv(格式:加密数据_b64::iv)
这是由 php 脚本生成的。
T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=
以下是 base64 格式的密钥:
alFlTFNKNGtLYXhtNkpOa2tHUEs=
以下是 base64 格式 IV:
wMjleA5Ssiij4gC7yxihfA==
以下是加密数据,base64格式:
OqVlMFENnRQO4ZI8JpGnsSZSyiGuNyKaX2qasw70uLg=
您能否制作一个 NODEJS 示例文件来解码 BD 中存储的字符串中的数据?
作为示例,以下是使用的 PHP 脚本。我已经尝试了很多使用节点的选项,但总是出现错误或描述不正确。
<?php
function Encrypt($data)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs=");
// Generate an initialization vector
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
// Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
// The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
return base64_encode($encrypted . '::' . $iv);
};
function Decrypt($data)
{
// Remove the base64 encoding from our key
$encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs");
// plain $encryption_key = "jQeLSJ4kKaxm6JNkkGPK";
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}
//echo "Here is the encrypted password:" . Encrypt("mysecurepassword");
//echo "<br><br>";
//echo "here is the decrypted password:" . Decrypt(Encrypt("mysecurepassword"));
$data = "T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=";
// Remove the base64 encoding from our key
$encryption_key = base64_decode("alFlTFNKNGtLYXhtNkpOa2tHUEs");
// plain $encryption_key = "jQeLSJ4kKaxm6JNkkGPK";
// To decrypt, split the encrypted data from our IV - our unique separator used was "::"
list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
echo "This is the IV : " .base64_encode($iv);
echo '<br>';
echo openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
echo '<br>';
echo openssl_cipher_iv_length('aes-256-cbc');
echo '<br>';
echo $encrypted_data;
?>
感谢您的帮助和时间:)我希望它也能帮助其他人。
答案1
干得好 :
问题是使用的 base64 密钥不是 32 个字符。在 PHP 中,openssl_decrypt 可能会用 '\0' 添加缺少的字符,因此解密时,它总是密钥长度无效。
const crypto = require("crypto"); // Import the crypto module
const algorithm = "aes-256-cbc"; // Use AES 256-bit encryption
const key = "jQeLSJ4kKaxm6JNkkGPK\0\0\0\0\0\0\0\0\0\0\0\0"; // <====== php accept less than 32char for key and just add \0 to have 32chars or 256 bytes
//const iv = crypto.randomBytes(16); // Generate a random 16-byte IV
function encrypt(data, ivData) {
// Function to encrypt data
let cipher = crypto.createCipheriv(algorithm, Buffer.from(key), ivData);
let encrypted = cipher.update(data);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return {
ivData: ivData.toString("base64"),
encryptedData: encrypted.toString("base64")
};
}
function decrypt(encryptedData, ivData) {
// Function to decrypt data
let encryptedText = Buffer.from(encryptedData, "base64");
let decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), ivData);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
const ivNew = Buffer.from("wMjleA5Ssiij4gC7yxihfA==", "base64");
var encrypted = encrypt(data, ivNew); // Encrypt the data
console.log("Encrypt Data: ", encrypted);
const dataENC = "OqVlMFENnRQO4ZI8JpGnsSZSyiGuNyKaX2qasw70uLg=";
var decrypted = decrypt(dataENC, ivNew); // Decrypt the data
console.log("Decrypt Data: ", decrypted);
我面临的另一个问题是 NodeJS 无法将原始 IV 从其保存的格式转换为 base64。
这个 base64 :
T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw=
具有base64格式的加密数据+IV原始字符(我不知道编码类型......)
但是使用 Node 我无法获取该 IV 字符并将其编码为 base64 。结果不是预期的结果。如果您有任何想法,请分享。
以下操作无效:
const stringRef = "T3FWbE1GRU5uUlFPNFpJOEpwR25zU1pTeWlHdU55S2FYMnFhc3c3MHVMZz06OsDI5XgOUrIoo+IAu8sYoXw="
const stringRefDecoded = Buffer.from(
stringRef,
'base64'
).toString('utf8');
const pwd_iv_arr = stringRefDecoded.split('::',2);
console.log (pwd_iv_arr);
let password = pwd_iv_arr[0];
let iv = Buffer.from(pwd_iv_arr[1], 'binary').toString('base64');
console.log(iv);
节点结果:
/f39eA5S/Sj9/QD9/Rj9fA==
PHP 的结果:
wMjleA5Ssiij4gC7yxihfA==
这是为什么?