Node加密函数的PHP等价物

问题描述 投票:0回答:1

我想找一个与这个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

php node.js encryption openssl
1个回答
0
投票

看起来你没有用空值来填充你的文本,以确保你的块大小正好是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() 可以抛出一个异常。

© www.soinside.com 2019 - 2024. All rights reserved.