dongming0505 2017-06-16 21:14
浏览 70
已采纳

PHP加密更大的文件

I'm trying to encrypt all files being uploaded to the server, and my method of doing it works; but I've noticed DECRYPTING files over 100kb just returns null, and I'm confused why encrypting works on these files, but decrypting doesn't. Is there something wrong with my code, or is there another approach to this? There is nothing wrong with the allowed upload sizes in php.ini, the upload.php page works perfectly fine, and uploads the files to the server. The only issue is with files over 100kb. I have a feeling it has something to do with the max variable length in PHP, but I'm not sure.

// 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;
}

Where it should be 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() . "
";
    }
  • 写回答

1条回答 默认 最新

  • duanrongpai9556 2017-06-17 21:36
    关注

    I'm not sure what the issue is, but I do know a solution. First of all, you probably want to read in the file in chucks. You don't want to store e.g. an entire movie in RAM. So what you can do is to treat the SFTP connection as stream:

    According to the sample code here:

    $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');
    

    Note that I used 'rb' to force binary mode.

    So now you can read in chunks from the stream, the only thing you need to do is to encrypt/decrypt the stream. Mcrypt does actually provide this functionality using a filter implementation.

    As for the HMAC, you can stream that as well. You may want to create a filter for it - I could not find one.

    So now that you can stream everything, go ahead and implement it.


    Security notes:

    • mcrypt is an old library that should not be used anymore;
    • use MCRYPT_RIJNDAEL_128 instead of using MCRYPT_RIJNDAEL_256 if you want to use AES (the 256 is the block size, not the key size, the key size is determined by - wait for it - the size of the provided key);
    • HMAC is secure, but it should be performed over the ciphertext and the IV;
    • this is not a full transport protocol - but that doesn't matter much if you send the file over sftp.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Oracle触发器记录修改前后的字段值
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器