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

wpx232ag  于 2023-11-16  发布在  PHP
关注(0)|答案(1)|浏览(128)

我试图创建一个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必须包含nonce和counter,但是必须如何完成以及哪个函数生成计数器,或者只是把$iv = $randomBytes . $counter;放在$randomBytes固定的地方,并在循环中的第二个调用中将$counter1更改为2,或者如何在上述php代码中完成?

qqrboqgw

qqrboqgw1#

在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 Package 器)自动禁用此功能。

相关问题