Tok*_*ger 5 php encryption bash openssl laravel
我正在开发一个文件存储和共享 Web 应用程序,其中 API 后端使用 Laravel,前端应用程序使用 VueJS。
我必须使用 CRON 例程每分钟启动一个 BASH 脚本来加密上传的文件,但我需要使用 Laravel/PHP 将它们从控制器解密到 StreamDownload 响应中(我需要逐块解密文件,因为大文件我们的服务器使用了太多内存)。
我们决定从外部例程对文件进行加密,以防止用户等待加密,有时在文件上传后等待几分钟。
我在 Debian 4.9 服务器上使用 Laravel 5.7 和 PHP 7.3,但我在 Windows 10 上的本地计算机上使用 WAMP 和 PHP 7.3 进行测试。我正在使用 Git Bash 来运行和测试我的 shell 命令。
我当前的 FileController 包含许多方法,包括“创建”和“下载”。
“创建”只是将文件存储到 Laravel 的存储目录中,并在数据库中创建一个新的“文件”资源,而“下载”则尝试检索加密文件,解密并将其发送到客户端。
这是我的创建方法。它只是创建资源并存储带有“.decrypted”前缀扩展名的文件。(我留了很多空白,因为这个方法的逻辑不是关于加密的)
//App\Http\Controllers\Files\FileController.php
public function create(Request $request)
{
...
$file = File::create([
'name' => $name,
'uuid' => $uuid,
...
]);
...
$output->move($userPath, $uuid.'.decrypted');
...
return new FileResource($file);
}
Run Code Online (Sandbox Code Playgroud)
然后,这是我编写的用于每分钟加密后缀文件的 BASH 脚本(我用一些“###”替换了敏感信息,不用担心。)
#encrypt.sh
#!/bin/bash
set -euo pipefail
# PARAMETERS
APP_KEY='######'
FILES_PATH='/###/.../storage/app/files/'
FILES_LIST=$(find "$FILES_PATH" -type f -name '*.decrypted' )
KEY=$(echo "$APP_KEY" | base64 -d -i | xxd -p -c 64)
while read -r file; do
INPUT_PATH=$file
OUTPUT_PATH=${file%.decrypted}
IV=$(openssl rand -hex 16)
openssl AES-256-CBC -K $KEY -iv $IV -in $INPUT_PATH -out $OUTPUT_PATH
done < <(echo "$FILES_LIST")
echo 'Done'
Run Code Online (Sandbox Code Playgroud)
据我所知,这段代码运行良好。
然后,这是我的最后一段代码:Download 方法。
//App\Http\Controllers\Files\FileController.php
public function download(File $file, Request $request)
{
...
$dlFile = Storage::disk('files')->path($file->path);
...
return response()->streamDownload(
/* Note: $dlFile is the path, $file is the Laravel resource */
function () use ($dlFile, $log, $file) {
$cipher = config('app.cipher'); // AES-256-CBC
/* Note: the app key is stored in format "base64:#####...", this is why there's a substr() inside a base64() */
$key = base64_decode(substr(config('app.key'), 7));
if ($fpIn = fopen($dlFile, 'rb')) {
$iv = fread($fpIn, 16);
while (!feof($fpIn)) {
$ciphertext = fread($fpIn, $this->memoryLimit());
$plaintext = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv);
print($plaintext);
}
fclose($fpIn);
}
},
$fileName,
[
'Content-Type' => $file->mime,
'Content-Length' => $file->size
],
'inline'
);
}
Run Code Online (Sandbox Code Playgroud)
我从这个页面得到了最后一段代码。
我猜我的 PHP 脚本制作得不好,因为解密的输出是错误的。有人有想法可以帮助我吗?
由于 Laravel 加密的设计方式,这个问题没有一个简单的答案。
您可以重新实现Defuse Security 的 PHP 加密库用于加密/解密低内存设备上的大文件的逻辑。然而,这是一个需要解决的非常复杂的问题,您还必须模拟输入到 HMAC 中的 JSON 序列化。
对于这些文件,您还可以从 Laravel 的内置加密库切换到 Defuse 的库。它具有内置FileAPI,可以满足您的需求。这可能是最省力的解决方案。
| 归档时间: |
|
| 查看次数: |
960 次 |
| 最近记录: |