通常,我使用openssl_encrypt
在PHP中使用AES加密简单字符串,并且效果非常好。
现在我需要使用AES-256-CTR模式加密文件,但唯一的方法是file_get_contents
文件的整个内容,然后将其发送到openssl_encrypt
函数加密实际的文件数据。问题是这种方法非常“差”,因为内存的关键浪费。
1)有没有办法使用PHP OpenSSL处理分块数据?
例如:
<?php
// ...
$f = fopen('large.iso','r');
while(feof($f)){
$chunk = fread($f,16);
$cipher = openssl_encrypt(...$chunk...);
// ... code ...
}
// ... more code ...
?>
2)openssl_encrypt
官方文档尚未发布。有人可以澄清用于AES-CTR模式的函数参数的含义吗?计数器是否自动处理?是否有必要对函数返回的数据进行手动异或?
注意:这是一个专业项目,所以我不想使用phpseclib
或其他人的“匿名”库,也不想使用命令行。
答案 0 :(得分:1)
对于php来说,如果没有临时文件,就无法使用aes-256-ctr。
但是对于下一个chiper类型:
OPENSSL_CIPHER_RC2_40
OPENSSL_CIPHER_RC2_128
OPENSSL_CIPHER_RC2_64
OPENSSL_CIPHER_DES
OPENSSL_CIPHER_3DES
OPENSSL_CIPHER_AES_128_CBC
OPENSSL_CIPHER_AES_192_CBC
OPENSSL_CIPHER_AES_256_CBC
你可以动态使用生成密钥:
$res = openssl_pkey_new('chiper args here');
openssl_pkey_export($res, $private_key);
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"];
然后加密:
$crypted_text = openssl_get_privatekey($private_key,'your data');
解密:
openssl_public_decrypt($crypted_text,$decrypted_text,$public_key);
所以如果你不想使用文件,可能会切换到OPENSSL_CIPHER_AES_256_CBC对你有帮助吗?
答案 1 :(得分:1)
1)它应该是这样的:
function strtohex($x) {
$s = '';
foreach (str_split($x) as $c){
$s.=sprintf("%02X", ord($c));
}
return($s);
}
$method = "aes-256-ctr"; //aes-256-cbc
echo "Selected method: ".$method."<br /><br />";
$textToEncrypt = "My chunk of data";
$iv = "1234567890123456";
$pass = 'some_pass';
$dec_iv = strtohex($iv);
$key = strtohex($pass);
$enc_data = openssl_encrypt($textToEncrypt, $method, $pass, true, $iv);
echo "Encrypted message (openssl): ".$enc_data."<br />";
$dec_data = openssl_decrypt($enc_data, $method, $pass, OPENSSL_RAW_DATA, $iv);
echo "Decrypted message (openssl): ".$dec_data."<br />";
对于每个块,CTR $ iv应该是唯一的,否则您的数据可能会被破坏。
2)我知道CBC和CTR之间只有很多不同之处:
对于CBC,IV必须是随机的,但不是唯一的。它也一定不为人知。
对于CTR,IV必须是唯一的且未知,但不需要是随机的。