PHP-改进文件加密

PHP-改进文件加密,php,encryption,cryptography,Php,Encryption,Cryptography,免责声明:英语不是我的母语,所以如果有什么不清楚的地方,请随时询问 你好 一旦文件上传到服务器上,我就必须使用AES对其进行加密,并通过邮件将解密所需的密钥发送到客户端(而不是将其存储在服务器端的任何位置)。文件大小可达2GB,上传7天后会被删除 下面是我用来加密/解密文件的内容: function encrypt_file($source, $destination, $key) { $iv = md5("\x1B\x3C\x58".$key, true); $ivsize =

免责声明:英语不是我的母语,所以如果有什么不清楚的地方,请随时询问

你好

一旦文件上传到服务器上,我就必须使用AES对其进行加密,并通过邮件将解密所需的密钥发送到客户端(而不是将其存储在服务器端的任何位置)。文件大小可达2GB,上传7天后会被删除

下面是我用来加密/解密文件的内容:

function encrypt_file($source, $destination, $key) {
    $iv = md5("\x1B\x3C\x58".$key, true);
    $ivsize = openssl_cipher_iv_length('aes-256-cbc');
    $fp = fopen($destination, 'wb') or die("Could not open file for writing.");
    $handle = fopen($source, "rb");
    while (!feof($handle)) {
        $e = 0;
        $contents = fread($handle, 4 * 1024 * 1024);
        $ciphertext = openssl_encrypt($contents, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        $iv = substr($ciphertext, -$ivsize);
        while (!fwrite($fp, $ciphertext)) {
            $e++;
            if ($e == 5) {
                die("Couldn't write to file.");
                break 2;
            }
        }
    }
    fclose($handle);
    fclose($fp);
}

function streamdecrypt_file($source, $key) {
    $iv = md5("\x1B\x3C\x58".$key, true);
    $ivsize = openssl_cipher_iv_length('aes-256-cbc');
    $handle = fopen($source, "rb");
    while (!feof($handle)) {
        $contents = fread($handle, 4 * 1024 * 1024);
        $raw = openssl_decrypt($contents, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        $iv = substr($contents, -$ivsize);
        print $raw; // Printing because it's directly sent to the user to download
    }
    fclose($handle);
}
如果你想知道为什么
4*1024*1024
这就是我得到最快加密的缓冲区大小。我的实现使用这里提出的模式

我还使用以下两个小函数使用密码短语将字符串加密到文件中:

function encrypt_string($source, $destination, $passphrase) {
    $iv = md5("\x1B\x3C\x58".$passphrase, true);
    $key = md5("\x2D\xFC\xD8".$passphrase, true);
    $ciphertext = openssl_encrypt($source, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    $fp = fopen($destination, 'wb') or die("Could not open file for writing.");
    fwrite($fp, $ciphertext) or die("Could not write to file.");
    fclose($fp);
}

function decrypt_string($source, $passphrase) {
    $iv = md5("\x1B\x3C\x58".$passphrase, true);
    $key = md5("\x2D\xFC\xD8".$passphrase, true);
    $contents = file_get_contents($source);
    return openssl_decrypt($contents, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
}
以下是上传完成后我最终要做的事情:

$skey = /* 32 chars random generated string [a-Z0-9]*/
$ukey = /* 10 chars random generated string [a-Z0-9]*/

encrypt_file($originalFile, $encryptedFile, $skey);
encrypt_string($skey, $encryptedKey, $ukey);
然后,我删除原始文件并通过邮件向用户发送包含
$ukey
的链接

当他们想要解密文件以下载它时,我首先使用
$ukey
对包含
$skey
的文件进行解密,检查我是否最终得到一个由[a-Z0-9]组成的32字符256位长的字符串。如果
$skey
与regexp不匹配,我知道
$ukey
无效,所以我就到此为止

我这样做是为了不必解密文件来检查密钥是否正确

现在,我希望我的问题符合以下要求:

  • 我做得对吗
  • 有什么可以/应该改进的吗
  • 加密2GB文件大约需要60秒,这是“确定”结果吗
  • 够好吗?其目的是防止攻击者访问服务器,同时也可以访问已存储的用户文件。我知道他将能够修改代码并访问以下上传,但这应该可以保护已经存储的文件,对吗?我做得太多了吗

谢谢你的回答

对于IV,使用随机字节

对于密码扩展,使用或等效;推导速度需要慢一些

将键限制在字符[a-Z0-9]上,256键基本上减少到36字节。这不是很安全。您至少需要128位的关键材料


您需要更好的方法来验证用户密码。

对于IV,请使用随机字节

对于密码扩展,使用或等效;推导速度需要慢一些

将密钥限制为字符[a-Z0-9]会将256个密钥减少到36个字节。这不是很安全。您至少需要128位的关键材料


您需要一种更好的方法来验证用户密码。

由于这个问题更多的是一个代码检查而不是一个特定的问题,因此我建议将其移动到您不指定执行加密的系统,该加密需要60秒/4GB。iPhone6s可以加密400MB/s,我的笔记本电脑可以加密150MB/s。对于使用密码扩展或等效密码,推导速度需要较慢。@MatthewHerbst在引用其他站点时,指出这个问题更像是代码审查而不是特定问题通常是有帮助的,我建议将其移动到您不指定执行加密的系统,这需要60s/4GB。iPhone6s可以加密400MB/s,我的笔记本电脑可以加密150MB/s。对于使用密码扩展或等效的方法,推导速度需要慢一些。@MatthewHerbst在引用其他网站时,指出感谢您的回答是很有帮助的,尽管有一部分我不明白。如果我从[a-Z0-9]中选择一个32个字符长的字符串,这难道不意味着有36^32个可能性,即使低于2^256,也高于2^128吗?(我不太擅长加密或数学,所以我很确定我错了,但我看不出有什么错)关于PBKDF2,我没有访问PHP5.5+,我发现许多不同的低版本实现,不确定选择哪个。你有机会得到推荐吗?或者我可以使用吗?你的任务是实现一个自制的加密协议,而他们甚至不允许你使用PHP的安全版本?WTF:任何人,从最无知的业余爱好者到最优秀的密码学家,都可以创建一个他自己无法破解的算法。@ScottArciszewski:我刚刚听说他们正在迁移这个项目,我将开始使用PHP5.6.17,好消息。扎夫,我没有收到你的报价。。。我并不是说我做了一些安全和牢不可破的东西,否则我不会在那里问它。。。(我是不是误解了你的评论?)。如果我从[a-Z0-9]中选择一个32个字符长的字符串,这难道不意味着有36^32个可能性,即使低于2^256,也高于2^128吗?(我不太擅长加密或数学,所以我很确定我错了,但我看不出有什么错)关于PBKDF2,我没有访问PHP5.5+,我发现许多不同的低版本实现,不确定选择哪个。你有机会得到推荐吗?或者我可以使用吗?你的任务是实现一个自制的加密协议,而他们甚至不允许你使用PHP的安全版本?WTF:任何人,从最无知的业余爱好者到最优秀的密码学家,都可以创建一个他自己无法破解的算法。@ScottArciszewski:我刚刚听说他们正在迁移这个项目,我将开始使用PHP5.6.17,好消息。扎夫,我没有收到你的报价。。。我并不是说我做了一些安全和牢不可破的东西,否则我不会在那里问它。。。(我是不是误解了你的评论?)