我正在try 创建一个PHP方法来复制OpenSSL命令行函数,这样我就可以使用PHP进行加密,然后使用命令行进行解密.

考虑到内存性能和限制问题,我创建了加密文件的PHP方法,将文件分块加密:

$salt= random_bytes(8);
$saltPrefix = "Salted__" . $salt;
$keyIV= EVP_BytesToKey($salt, file_get_contents('my.key'));
$key = substr($keyIV, 0, 32);
$iv= substr($keyIV, 32, openssl_cipher_iv_length('AES-256-CTR'));
$original = file_get_contents('confidential.txt');
$FILE_ENCRYPTION_BLOCKS = 10000;
if ($fpOut = fopen('php-encrypted.bin', 'w')) {
    fwrite($fpOut, $saltPrefix);
    if ($fpIn = fopen('confidential.txt', 'rb')) {
        while (!feof($fpIn)) {
            $plaintext = fread($fpIn, 16 * $FILE_ENCRYPTION_BLOCKS);
            $encrypted = openssl_encrypt($plaintext, 'AES-256-CTR', $key, (feof($fpIn) ? OPENSSL_RAW_DATA:OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING), $iv);
            fwrite($fpOut, $encrypted);
        }
        fclose($fpIn);
    }
    fclose($fpOut);
}

然后,在运行此方法后,我可以使用以下命令行对其进行解密:

openssl  enc -p -d -aes-256-ctr -in php-encrypted.bin -out decrypted.txt -pass file:my.key

但是,当我try 使用上面的命令行解密生成的文件时,它不起作用.我需要更新上面的方法,以模拟使用CTR模式的命令行加密.我读到$iv必须包含随机数和计数器,但这必须如何完成以及生成计数器的函数,或者只将$iv = $randomBytes . $counter;放在$randomBytes固定的位置并在循环中的第二个调用中将$counter1更改为2是安全的,或者在上面的php代码中如何完成?

推荐答案

在CTR模式下,初始IV随每个后续块递增,请参见CTR flow diagram.这个所谓的计数器是加密的.结果,生成与明文进行异或运算的密钥流.

如果加密是以包含$FILE_ENCRYPTION_BLOCKS个块(每个块16字节)的块的形式执行的,则后续块的计数器必须相应地递增$FILE_ENCRYPTION_BLOCKS.

$iv是一个二进制字符串,可以使用gmp_import()(以及$word_size$flags的缺省值)转换为数字,然后使用gmp_export()递增并转换回二进制字符串.一种可能的实施方式是:

$FILE_ENCRYPTION_BLOCKS = 10000;
$salt= random_bytes(8);
$saltPrefix = 'Salted__' . $salt;
$keyIV = EVP_BytesToKey($salt, file_get_contents('my.key'));
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32, 16);
if ($fpOut = fopen('php-encrypted.bin', 'wb')) {
    fwrite($fpOut, $saltPrefix);
    if ($fpIn = fopen('confidential.txt', 'rb')) {
        while (!feof($fpIn)) {
            $plaintext = fread($fpIn, 16 * $FILE_ENCRYPTION_BLOCKS);
            $encrypted = openssl_encrypt($plaintext, 'AES-256-CTR', $key, OPENSSL_RAW_DATA, $iv);   // padding implicitly disabled for CTR
            $iv = gmp_export(gmp_import($iv) + $FILE_ENCRYPTION_BLOCKS);                            // increment counter
            fwrite($fpOut, $encrypted);
        }
        fclose($fpIn);
    }
    fclose($fpOut);
} 

以这种方式生成的密文可以用以下方式解密:

openssl  enc -p -d -aes-256-ctr -in ciphertext.bin -out decrypted.txt -pass file:my.key

为了完整性:流密码模式,如CTR,不需要填充.OpenSSL(以及PHP包装器)会自动禁用此功能.

Php相关问答推荐

此行动未经授权.升级Laravel时

Laravel—通过单击处理多条路由

未在moodle上运行的计划任务

PHP:从数组中获取唯一的数字组合

累加平面数组中数字子集的所有组合,以生成组合及其乘积的二维数组

PHP日期操作,将多个日期输出为格式化字符串

PHP中冒号的奇怪用例

使用php创建表格和插入数据

如何实现对数据库表中多列的唯一约束?

WooCommerce中特定付款方式的变更订单预留库存时间

如何使用PHP从TXM(XML)标记中读取特定属性

在WooCommerce存档页面中显示可变产品的库存变化属性

Woocommerce 临时购物车税未根据第一个请求正确计算

在 WooCommerce 管理变量产品中启用其他变体图像

安装 Herd 并返回 Valet 后为 502

根据WooCommerce中选定的变体重量更改输入数量步值

仅在管理员新订单通知中显示WooCommerce订单商品自定义元数据

Laravel:ArgumentCountError: 函数 App\Mail 的参数太少

为什么 8.0 之前的 PHP 版本拒绝命名空间Random\Namespace作为无效语法?

Laravel Websockets 错误:(WebSocket 在建立连接之前关闭)