PHP 文件加密上传下载完整实现
在敏感业务场景中(如医疗、金融、政务系统),文件需在传输与存储环节全程加密。本文提供基于 OpenSSL 的轻量级、生产可用方案,兼顾安全性与可维护性。核心思路
✅ 使用 AES-256-CBC 对称加密(密钥由密码派生) ✅ 上传时加密后存为二进制文件 + JSON 元数据(含 IV、盐值) ✅ 下载时解密并设置正确 Content-Disposition 头关键代码示例
1. 加密上传(upload.php)
<?php
$key = hash_pbkdf2('sha256', $_POST['password'], $salt = random_bytes(16), 100000, 32);
$iv = random_bytes(16);
$encrypted = openssl_encrypt(file_get_contents($_FILES['file']['tmp_name']), 'AES-256-CBC', $key, 0, $iv);
// 存储:加密内容 + 元数据(JSON)
$data = [
'iv' => bin2hex($iv),
'salt' => bin2hex($salt),
'original_name' => $_FILES['file']['name'],
'mime' => $_FILES['file']['type']
];
file_put_contents("uploads/{$_FILES['file']['name']}.enc", $encrypted);
file_put_contents("uploads/{$_FILES['file']['name']}.meta", json_encode($data));
echo "✅ 上传并加密成功!";
?>
2. 安全下载(download.php)
<?php
$filename = basename($_GET['f']);
$encPath = "uploads/{$filename}.enc";
$metaPath = "uploads/{$filename}.meta";
if (!file_exists($encPath) || !file_exists($metaPath)) die('文件不存在');
$meta = json_decode(file_get_contents($metaPath), true);
$key = hash_pbkdf2('sha256', $_GET['p'], hex2bin($meta['salt']), 100000, 32);
$iv = hex2bin($meta['iv']);
$decrypted = openssl_decrypt(file_get_contents($encPath), 'AES-256-CBC', $key, 0, $iv);
// 强制下载(防止 XSS & MIME sniffing)
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . rawurlencode($meta['original_name']) . '"');
header('Content-Length: ' . strlen($decrypted));
header('X-Content-Type-Options: nosniff');
echo $decrypted;
exit;
?>
安全增强建议
- ✅ 使用 HTTPS 部署,杜绝明文传输密码与密文
- ✅ 将
uploads/目录置于 Web 根目录外,或通过.htaccess禁止直接访问 - ✅ 增加文件大小限制、MIME 白名单校验(
finfo_file()) - ✅ 生产环境使用独立密钥管理服务(如 HashiCorp Vault),而非硬编码或 URL 参数传密钥
⚠️ 注意:本文示例为简化教学版。实际项目中请严格校验输入、记录操作日志、启用 PHP OpenSSL 扩展,并定期审计加密流程。
通过以上实现,你已构建起端到端可控的文件加密通道——既满足合规要求,又无需引入复杂框架。安全不是功能,而是贯穿每一行代码的习惯。
```