You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现PHP服务端加密文件并在JavaScript客户端解密?

PHP服务端加密文件,JavaScript客户端解密方案

问题背景

你已实现PHP端文件加密接口,返回包含IV与密文的Base64编码数据,需在浏览器端通过JavaScript完成解密并还原原始文件。

PHP端已实现的加密代码

加密函数

function encryptFile($path, $key)
{
    $iv = openssl_random_pseudo_bytes(16);
    // 注意:AES-256-CBC要求32字节密钥,若直接使用短字符串密钥,PHP会自动用0填充至32字节
    // 推荐优化:将密钥哈希为标准32字节,避免兼容性问题:$key = hash('sha256', $key, true);
    $encrypted = openssl_encrypt(file_get_contents($path), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv . $encrypted);
}

加密文件下载接口

public function downloadEncryptedFile()
{
    $key = 'fee-fi-fum';
    $path = storage_path('app/public/nicesong.mp3');
    $encrypted = encryptFile($path, $key);
    return response($encrypted, 200, [
        'Content-Type' => 'application/octet-stream',
        'Content-Disposition' => 'attachment; filename="your-file.encrypted"'
    ]);
}

JavaScript客户端解密实现

核心逻辑

  1. 读取下载的加密文件(Base64格式字符串)
  2. 解码Base64为二进制数据,分离出前16字节的IV与剩余密文
  3. 将密钥处理为符合AES-256要求的32字节格式(与PHP端逻辑对齐)
  4. 使用浏览器原生Web Crypto API完成解密
  5. 还原为原始文件并触发下载

完整代码示例

// 解密主函数
async function decryptEncryptedFile(file, password) {
    // 1. 读取加密文件内容(Base64字符串)
    const fileContent = await readFileAsText(file);
    
    // 2. Base64解码为二进制数组
    const binaryData = base64ToUint8Array(fileContent);
    
    // 3. 拆分IV(前16字节)和密文
    const iv = binaryData.slice(0, 16);
    const ciphertext = binaryData.slice(16);
    
    // 4. 处理密钥:和PHP端逻辑对齐
    // 场景1:PHP端直接使用短密钥字符串(自动补0到32字节)
    const keyBytes = new TextEncoder().encode(password);
    const paddedKey = new Uint8Array(32);
    paddedKey.set(keyBytes, 0); // 用0填充至32字节,匹配PHP行为
    const key = await window.crypto.subtle.importKey(
        'raw',
        paddedKey,
        { name: 'AES-CBC', length: 256 },
        false,
        ['decrypt']
    );

    // 场景2:若PHP端已将密钥转为SHA256哈希(推荐),替换为以下代码:
    // const keyMaterial = await window.crypto.subtle.importKey(
    //     'raw',
    //     new TextEncoder().encode(password),
    //     { name: 'PBKDF2' },
    //     false,
    //     ['deriveKey']
    // );
    // const key = await window.crypto.subtle.deriveKey(
    //     { name: 'PBKDF2', salt: new Uint8Array(0), iterations: 1, hash: 'SHA-256' },
    //     keyMaterial,
    //     { name: 'AES-CBC', length: 256 },
    //     false,
    //     ['decrypt']
    // );
    
    // 5. 执行解密
    const decryptedBuffer = await window.crypto.subtle.decrypt(
        { name: 'AES-CBC', iv: iv },
        key,
        ciphertext
    );
    
    // 6. 还原为原始文件并下载
    const decryptedBlob = new Blob([decryptedBuffer], { type: 'audio/mpeg' }); // 替换为原始文件的MIME类型
    downloadBlob(decryptedBlob, 'nicesong.mp3');
}

// 辅助函数:读取文件为文本
function readFileAsText(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsText(file);
    });
}

// 辅助函数:Base64转Uint8Array
function base64ToUint8Array(base64) {
    const binaryString = window.atob(base64);
    const bytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes;
}

// 辅助函数:触发文件下载
function downloadBlob(blob, filename) {
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(link);
}

// 使用示例:绑定文件选择事件
document.getElementById('encrypted-file-input').addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    const password = 'fee-fi-fum'; // 与PHP端一致的密钥
    await decryptEncryptedFile(file, password);
});

关键注意事项

  • 密钥一致性:PHP与JS端的密钥处理逻辑必须完全对齐,否则解密会失败。优先推荐将密钥转为SHA256哈希的标准32字节格式。
  • MIME类型:创建Blob时需指定原始文件的正确MIME类型(如MP3对应audio/mpeg)。
  • 环境限制:Web Crypto API仅在HTTPS环境或localhost下可用,避免明文传输密钥。

内容的提问来源于stack exchange,提问作者3m1n3nc3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:27:50