AES/CBC/PKCS5 填充 |替代 PHP OpenSSL 中的 mcrypt_get_block_size()

Posted

技术标签:

【中文标题】AES/CBC/PKCS5 填充 |替代 PHP OpenSSL 中的 mcrypt_get_block_size()【英文标题】:AES/CBC/PKCS5 Padding | Alternate to mcrypt_get_block_size() in Php OpenSSL 【发布时间】:2021-08-16 17:11:14 【问题描述】:

问题陈述:

我正在尝试集成 API 其中 AES/CBC/PKCS5 填充。经过一番研究,我在following 文章中找到了实现。

但是,在本文中使用了 mcrypt,它已被弃用并从 php 7.2 中删除。因此,我希望在openssl 中修改上述实现。

有一个函数pkcs5_pad 用于PKCS5 填充需要参数为数据和块大小的数据。而且在 openssl 中没有 mcrypt_get_block_size 的替代品。


代码片段

pkcs5_pad & pkcs5_unpad

function pkcs5_pad ($text, $blocksize)

    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);



function pkcs5_unpad($text)

    $pad = ord($textstrlen($text)-1);
    if ($pad > strlen($text)) return false;
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
    return substr($text, 0, -1 * $pad);


尝试转换关注

$paddedData = pkcs5_pad(
                            $data, 
                            mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)
                        );


$encrypteddata = mcrypt_encrypt(
                                    MCRYPT_RIJNDAEL_128,
                                    hex2bin(md5($key)),
                                    $paddedData,
                                    MCRYPT_MODE_CBC,
                                    $iv
                                );

$paddedData = pkcs5_pad($data);  // How do I getBlock size in OpenSSL. i.e. Alternate to mcrypt_get_block_size

$encrypteddata = openssl_encrypt(
                                    $paddedData, 
                                    $cipher, 
                                    $key, 
                                    $options=OPENSSL_RAW_DATA, 
                                    $iv
                                );

试错:

在 Github 上进行一些研究后,我发现了一些 file。但不知道如何使用这个文件将数据转换为pkcs5填充数据。


【问题讨论】:

【参考方案1】:

好消息是 - OpenSSL 具有“内置”填充,因此您不必担心。

下面的完整运行代码向您展示了如何使用 32 字节长、随机生成的 AES-256 密钥来加密或解密字符串。 AES 模式是 CBC,它使用 PKCS5/7 填充。加密的输出是 Base64 编码的(用于通过电子邮件传输),当然您可以在将密文保存到文件时不使用 Base64 编码/解码,然后读取文件进行解密。

请注意,没有异常处理,代码用于教育目的:

<?php
function generateRandomAesKey()

    return openssl_random_pseudo_bytes(32, $crypto_strong);


function generateRandomInitvector()

    return openssl_random_pseudo_bytes(16, $crypto_strong);


function base64Encoding($input)

    return base64_encode($input);


function base64Decoding($input)

    return base64_decode($input);


function aesCbcEncryptToBase64($key, $data)

    $iv = generateRandomInitvector();
    $ciphertext = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv) . ':' . base64_encode($ciphertext);


function aesCbcDecryptFromBase64($key, $data)

    list($iv, $encryptedData) = explode(':', $data, 2);
    return openssl_decrypt(base64_decode($encryptedData), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, base64_decode($iv));


echo 'AES CBC 256 String encryption with random key full' . PHP_EOL;

$plaintext = 'The quick brown fox jumps over the lazy dog';
echo 'plaintext: ' . $plaintext . PHP_EOL;

// generate random key
$encryptionKey = generateRandomAesKey();
$encryptionKeyBase64 = base64Encoding($encryptionKey);
echo 'encryptionKey (Base64): ' . $encryptionKeyBase64 . PHP_EOL;

// encryption
echo PHP_EOL . '* * * Encryption * * *' . PHP_EOL;
$ciphertextBase64 = aesCbcEncryptToBase64($encryptionKey, $plaintext);
echo 'ciphertext: ' . $ciphertextBase64 . PHP_EOL;
echo 'output is (Base64) iv : (Base64) ciphertext' .PHP_EOL;

echo PHP_EOL;
echo 'Cross platform cryptography: AES CBC 256 String encryption with random key (PHP)' . PHP_EOL;
// decryption
echo PHP_EOL . '* * * Decryption * * *' . PHP_EOL;
$decryptionKeyBase64 = $encryptionKeyBase64;
$ciphertextDecryptionBase64 = $ciphertextBase64;
echo 'decryptionKey (Base64): ' . $decryptionKeyBase64 . PHP_EOL;

echo 'ciphertextDecryption (Base64): ' . $ciphertextDecryptionBase64 . PHP_EOL;
echo 'input is (Base64) iv : (Base64) ciphertext' .PHP_EOL;
$decryptionKey = base64Decoding($decryptionKeyBase64);
$decryptedtext = aesCbcDecryptFromBase64($decryptionKey, $ciphertextDecryptionBase64);
echo 'plaintext: ' . $decryptedtext . PHP_EOL;
?>

输出如下:

AES CBC 256 String encryption with random key full
plaintext:  The quick brown fox jumps over the lazy dog
encryptionKey (Base64): DuLNOxN3BUc+htgigTcQOeJsPuMkF/aBcyVSaXhMcEw=

* * * Encryption * * *
ciphertext: XvXGCOyMrj2ohknIr8k1+A==:nPrEGko/7OFRjiRCgX0Hryz0a+Qc6A9RmRlipWl+R6vslqLBf/8EZtGsf+zwwGAV
output is (Base64) iv : (Base64) ciphertext

* * * Decryption * * *
decryptionKey (Base64): DuLNOxN3BUc+htgigTcQOeJsPuMkF/aBcyVSaXhMcEw=
ciphertext (Base64): XvXGCOyMrj2ohknIr8k1+A==:nPrEGko/7OFRjiRCgX0Hryz0a+Qc6A9RmRlipWl+R6vslqLBf/8EZtGsf+zwwGAV
input is (Base64) iv : (Base64) ciphertext
plaintext:  The quick brown fox jumps over the lazy dog

【讨论】:

以上是关于AES/CBC/PKCS5 填充 |替代 PHP OpenSSL 中的 mcrypt_get_block_size()的主要内容,如果未能解决你的问题,请参考以下文章

AES/CBC/PKCS5Padding 与 AES/CBC/PKCS7Padding 与 256 密钥大小性能 java

AES/CBC/PKCS5Padding对称加密

nodejs中aes-128-cbc加密和解密

Java中的AES加解密

AES加密解密在JAVA和ANDROID下互通

使用 NSMenuItems 从 NSArray 填充 NSMenu - 需要替代建议