PHP加密更大的文件

时间:2017-06-16 21:14:09

标签: php encryption

我试图加密上传到服务器的所有文件,我的方法也可以;但是我注意到超过100kb的DECRYPTING文件只返回null,我很困惑为什么加密对这些文件起作用,但解密却没有。我的代码有问题,还是有另一种方法? php.ini中允许的上传大小没有任何问题,upload.php页面工作正常,并将文件上传到服务器。唯一的问题是文件超过100kb。我觉得它与PHP中的max变量长度有关,但我不确定。

// Encrypt Function
public static function mc_encrypt($encrypt, $key)
{
    $encrypt = serialize($encrypt);
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
    $key = pack('H*', $key);
    $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
    $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
    $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
    return $encoded;
}

// Decrypt Function
public static function mc_decrypt($decrypt, $key)
{
    $decrypt = explode('|', $decrypt.'|');
    $decoded = base64_decode($decrypt[0]);
    $iv = base64_decode($decrypt[1]);
    if(strlen($iv)!==mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)){ return false; }
    $key = pack('H*', $key);
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
    $mac = substr($decrypted, -64);
    $decrypted = substr($decrypted, 0, -64);
    $calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
    if($calcmac!==$mac){ return false; }
    $decrypted = unserialize($decrypted);
    return $decrypted;
}

应解密的地方:

try
    {
        $server = $db->prepare("SELECT * FROM `servers` WHERE `ServerIP` = :ip LIMIT 1");
        $server->execute([ ":ip" => $ip ]);
        $server = $server->fetch();
        $sftp = new SFTPConnection($server['ServerIP'], intval($server['ServerPort']));
        $sftp->login($server['ServerUser'], $server['ServerPassword']);
        $fileData = $sftp->receiveFile($path);

        //print $fileData;

        header('Content-type: text/plain');
        $fileName = $file['FileName'];
        header("Content-Disposition: attachment; filename=$fileName");

        //print $fileData; (returns the encrypted version)
        $fileData = Encryption::mc_decrypt($fileData, $file['EncryptionKey']);

        print $fileData; // (returns null on larger files)
    }
    catch (Exception $e)
    {
        echo $e->getMessage() . "\n";
    }

1 个答案:

答案 0 :(得分:1)

我不确定问题是什么,但我确实知道解决方案。首先,你可能想要在chucks中读取文件。你不想存储,例如RAM中的整部电影。所以你可以做的是将SFTP连接视为流:

根据示例代码:

$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'rb');

请注意,我使用'rb'来强制使用二进制模式。

所以现在你可以从流中读取块,你唯一需要做的就是加密/解密流。 Mcrypt does actually provide this functionality using a filter implementation

至于HMAC,you can stream that as well。你可能想要create a filter for it - 我找不到一个。

现在您可以流式传输所有内容,然后继续实施。

安全说明:

  • mcrypt是一个不应再使用的旧库;
  • 如果要使用AES,则使用MCRYPT_RIJNDAEL_128而不是使用MCRYPT_RIJNDAEL_256(256是块大小,而不是密钥大小,密钥大小由 - 等待它 - 所提供密钥的大小确定);
  • HMAC是安全的,但应该通过密文和IV执行;
  • 这不是一个完整的传输协议 - 但如果你通过sftp发送文件并不重要。