我想找一个与这个node函数等价的php函数,以便能够在php中加密一些数据,然后再在node中解密。
/**
* Encrypts an object with aes-256-cbc to use as a token
* @param {any} data An object to encrypt
* @param {string} secret The secret to encrypt the data with
* @returns {string}
*/
static encrypt(data, secret) {
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-cbc', secret, iv);
return `${cipher.update(JSON.stringify(data), 'utf8', 'base64') + cipher.final('base64')}.${iv.toString('base64')}`;
}
这是我想出的php函数,以及必要的辅助函数。
/**
* Encrypts an object with aes-256-cbc to use as a token
* @param $data An object to encrypt
* @param $secret The secret to encrypt data with
* @return \Illuminate\Http\Response
*/
public function encrypt($data, $secret)
{
$method = 'AES-256-CBC';
$data = static::getPaddedText($data);
$iv = static::generateIv();
$ciphertext = openssl_encrypt(json_encode($data), $method, $secret, OPENSSL_RAW_DATA, $iv);
$ciphertext_64 = base64_encode(utf8_encode($ciphertext));
$iv_64 = base64_encode($iv);
return "$ciphertext_64.$iv_64";
}
private static function getPaddedText(string $plainText): string
{
$blocksize = 8;
$textLength = strlen($plainText);
if ($textLength % $blocksize) {
$plainText = str_pad($plainText, $textLength + $blocksize - $textLength % $blocksize, "\0");
}
return $plainText;
}
public static function generateIv(): string
{
$ivLength = 16;
$success = false;
$random = openssl_random_pseudo_bytes($ivLength, $success);
if (!$success) {
$random = random_bytes($ivLength);
}
return $random;
}
但我认为它和用这个函数解密时不完全一样。
/**
* Decrypts an object with aes-256-cbc to use as a token
* @param {string} token An data to decrypt
* @param {string} secret The secret to decrypt the data with
* @returns {any}
*/
static decrypt(token, secret) {
const [data, iv] = token.split('.');
const decipher = createDecipheriv('aes-256-cbc', secret, Buffer.from(iv, 'base64'));
return JSON.parse(decipher.update(data, 'base64', 'utf8') + decipher.final('utf8'));
}
我得到这个错误 EVP_DecryptFinal_ex:wrong final block length
看起来你没有用空值来填充你的文本,以确保你的块大小正好是8个字符长。换句话说,你的字符串长度需要是8的倍数。用空值填充你的字符串可以在不改变其值的情况下达到这个目的。
class AES256Encryption
{
public const BLOCK_SIZE = 8;
public const IV_LENGTH = 16;
public const CIPHER = 'AES-256-CBC';
public static function generateIv(): string
{
$success = false;
$random = openssl_random_pseudo_bytes(static::IV_LENGTH, $success);
if (!$success) {
$random = random_bytes(static::IV_LENGTH);
}
return $random;
}
private static function getPaddedText(string $plainText): string
{
$textLength = strlen($plainText);
if ($textLength % static::BLOCK_SIZE) {
$plainText = str_pad($plainText, $textLength + static::BLOCK_SIZE - $textLength % static::BLOCK_SIZE, "\0");
}
return $plainText;
}
public static function encrypt(string $plainText, string $key, string $iv): string
{
$plainText = static::getPaddedText($plainText);
return base64_encode(openssl_encrypt($plainText, static::CIPHER, $key, OPENSSL_RAW_DATA, $iv));
}
public static function decrypt(string $encryptedText, string $key, string $iv): string
{
return openssl_decrypt(base64_decode($encryptedText), static::CIPHER, $key, OPENSSL_RAW_DATA, $iv);
}
}
使用方法
$key = 'secretkey';
$iv = AES256Encryption::generateIv();
$text = 'The quick brown fox jumps over the lazy dog';
$encryptedText = AES256Encryption::encrypt($text, $key, $iv);
$decryptedText = AES256Encryption::decrypt($encryptedText, $key, $iv);
printf('Original Text: %s%s', $text, PHP_EOL);
printf('Encrypted : %s%s', $encryptedText, PHP_EOL);
printf('Decrypted : %s%s', $decryptedText, PHP_EOL);
输出:
Original Text: The quick brown fox jumps over the lazy dog
Encrypted : 1J+0tGHzn67WA7kJGjp9malmv0w+tcl0t8YnC+F9Y9IZWMDeBH4+k9TyuznF77cWe1SGUWa6Pb6r/i0xmH+ajg==
Decrypted : The quick brown fox jumps over the lazy dog
你的用法
// Your encoding usage:
$key = 'secret';
$iv = AES256Encryption::generateIv();
$text = 'The quick brown fox jumps over the lazy dog';
$encryptedText = AES256Encryption::encrypt($text, $key, $iv);
$finalString = $encryptedText . bin2hex($iv);
// Your decoding usage:
$iv = hex2bin(substr($finalString, -32, 32));
$decryptedText = AES256Encryption::decrypt($encryptedText, $key, $iv);
printf('Original Text : %s%s', $text, PHP_EOL);
printf('Encrypted : %s%s', $encryptedText, PHP_EOL);
printf('Encrypted w/Iv: %s%s', $finalString, PHP_EOL);
printf('Decrypted : %s%s', $decryptedText, PHP_EOL);
输出:
Original Text : The quick brown fox jumps over the lazy dog
Encrypted : +JsjXFPdyTycYrc2fOb1edLKNksEUHzEGxwRewBlA8yxBWZZV2y/EVIwk0g9g17dtxAaTGZvYaf2y9+oTCvLWg==
Encrypted w/Iv: +JsjXFPdyTycYrc2fOb1edLKNksEUHzEGxwRewBlA8yxBWZZV2y/EVIwk0g9g17dtxAaTGZvYaf2y9+oTCvLWg==54993615360ff641a952a553e1500568
Decrypted : The quick brown fox jumps over the lazy dog
生成IV可以更强大,因为 random_bytes()
可以抛出一个异常。