PHP 文件加密上传下载完整实现
在敏感业务场景中(如医疗、金融、政务系统),文件需在传输与存储环节全程加密。本文提供基于 OpenSSL 的轻量级、生产可用方案,兼顾安全性与可维护性。核心思路
✅ 使用 AES-256-CBC 对称加密(密钥由密码派生) ✅ 上传时加密后存为二进制文件 + JSON 元数据(含 IV、盐值) ✅ 下载时验证并解密,流式输出避免内存溢出关键代码示例
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);
$meta = [
'original_name' => $_FILES['file']['name'],
'iv' => bin2hex($iv),
'salt' => bin2hex($salt),
'size' => strlen($encrypted)
];
file_put_contents("uploads/" . uniqid() . ".enc", $encrypted);
file_put_contents("uploads/" . uniqid() . ".meta", json_encode($meta));
?>
2. 安全下载(download.php?id=xxx)
<?php
$id = $_GET['id'] ?? '';
$encFile = "uploads/{$id}.enc";
$metaFile = "uploads/{$id}.meta";
if (!file_exists($encFile) || !file_exists($metaFile)) die('文件不存在');
$meta = json_decode(file_get_contents($metaFile), true);
$key = hash_pbkdf2('sha256', $_GET['pwd'], hex2bin($meta['salt']), 100000, 32);
$iv = hex2bin($meta['iv']);
$decrypted = openssl_decrypt(file_get_contents($encFile), 'AES-256-CBC', $key, 0, $iv);
if ($decrypted === false) die('解密失败:密码错误或文件损坏');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . rawurlencode($meta['original_name']) . '"');
header('Content-Length: ' . strlen($decrypted));
echo $decrypted;
exit;
?>
安全提醒:
• 密码绝不参与传输(建议前端 JS 加密或使用 HTTPS 表单)
• 生产环境禁用
display_errors,记录日志而非暴露错误
• 文件存储目录需置于 Web 根目录外(如 /var/data/uploads/)
• 建议配合临时 Token 验证下载权限,防止 URL 泄露导致未授权访问