php - PHP 相当于一个 Node 加密函数
问题描述
我正在尝试获取此节点函数的 php 等效项,以便能够在 php 中加密某些数据,然后在节点中对其进行解密
/**
* 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 的倍数。用空值填充您的字符串将为您完成此操作,而无需更改其值。
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()
可以引发异常。
推荐阅读
- java - 相同数据应用于所有相同类型的 Bean,同时创建具有不同数据的 bean 列表
- curl - 卷曲不正确的符号
- java - 我可以使用类似于 farbic8 的 spotify 插件配置远程 DOCKER_HOST
- r - 反码函数,处理引号
- android - Socket 和 SSLSocket 在同一个端口上运行
- reactjs - 如何在 package.json 中链接 css:watch 和 babel
- android - 将国家名称转换为 ISO Alpha 2 国家代码
- java - spring-boot 执行器健康检查事件
- android - 如何更改XML文件android studio中的字体
- javascript - 如何在 ng-repat 中保存元素的索引?