使用与openssl命令行兼容的AES-256-CTR为大文件openssl加密创建php代码

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

我正在尝试创建一个 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

但是当我尝试使用上面的命令行解密生成的文件时,它不起作用。我需要更新上述方法以使用 CTR 模式模拟命令行加密。我读到 $iv 必须包含随机数和计数器,但是必须如何完成此操作以及生成计数器的函数,或者仅将

$iv = $randomBytes . $counter;
放置在
$randomBytes
固定的位置并在循环中的第二次调用中更改是安全的
$counter
1
2
或者如何在上面的php代码中完成?

php openssl aes large-files php-openssl
1个回答
1
投票

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

如果在由

$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 包装器)会自动禁用此功能。

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