PHP openssl 加密 aes-256-cbc 并使用 NODEJS 解密

PHP openssl 加密 aes-256-cbc 并使用 NODEJS 解密

我有一个 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==

这是为什么?

相关内容