加密密钥如何工作:文件安全的基础
用简单的语言了解加密密钥的工作原理。学习密钥生成、交换和管理如何实现安全文件共享。
加密密钥是一串随机比特,用于锁定和解锁数据。对于现代文件传输,这通常意味着一个 256 位的 AES 密钥——由密码学安全随机数生成器(CSPRNG)生成的 32 字节随机数据。同一算法可以将一个 10 GB 的视频加密成密文,也只有拿到完全相同的密钥才能解密还原。密钥的安全性决定着加密的成败:即便 AES-256 算法本身无懈可击,密钥一旦脆弱、可预测或泄露,一切防护都将化为乌有。本文梳理密钥在 HexaTransfer、Tresorit、Proton Drive 等真实服务中如何生成、共享、存储和销毁。
密钥本质上是随机数
一个 256 位密钥就是 32 字节。在浏览器中生成时,看起来像这样:
const key = crypto.getRandomValues(new Uint8Array(32));
// Uint8Array(32) [183, 45, 201, 77, ...]
让它成为"密钥"的,是算法使用它的方式。AES-256-GCM 接受 256 位密钥,通过密钥扩展算法展开为 15 个轮密钥,用这些轮密钥对 128 位数据块执行 14 轮置换操作。数学运算本身并不关心这些比特从何而来——它只要求这些比特是保密且不可预测的。
"不可预测"是更难实现的那一半。若攻击者能猜到随机数生成器的状态,便可重新生成你的密钥。2006 年 Debian 的 OpenSSL 漏洞将密钥熵压缩到 15 位长达两年才被发现,是随机性失效的典型案例。
密码学安全的随机性
浏览器提供的 crypto.getRandomValues() 从操作系统的 CSPRNG 取样:Linux 上的 /dev/urandom、Windows 上的 BCryptGenRandom、macOS 上的 SecRandomCopyBytes。这些接口进一步混合多种熵源——中断时序、磁盘寻道时间、Intel RDRAND 等硬件随机数芯片。
不要用 Math.random() 生成密钥。它是可预测的梅森旋转算法,几次输出便可反推其内部状态。
服务器端,Node.js 的 crypto.randomBytes() 和 Python 的 secrets.token_bytes() 封装了操作系统的 CSPRNG,可安全使用。NIST SP 800-90A 和 SP 800-90B 定义了 CSPRNG 的技术要求;Linux 内核 5.17+ 采用基于 BLAKE2s 的设计以满足这些要求。
对称密钥:一把钥匙,双向使用
AES 等对称算法使用同一密钥进行加密和解密。密钥长度选项:
- 128 位 — 2^128 种可能值,对大多数场景足够安全,NSA CNSSP-15 批准用于 SECRET 级别。
- 192 位 — 较少见,用于部分政府场景。
- 256 位 — 2^256 种值,批准用于 TOP SECRET 级别,是当前文件传输服务的默认选项。
密钥长度翻倍并不意味着暴力破解难度翻倍,而是呈指数级增长。2^128 本已超出任何算力的范围(以地球上所有计算机运行宇宙年龄十倍的时间来计算)。256 位是针对量子计算机的额外防护——Grover 算法会将对称密钥的有效强度减半。
对称密钥的核心难题:如何在不被截获的情况下,将同一密钥安全传达给通信双方。
非对称密钥:密钥对的巧妙设计
公钥密码学解决了密钥分发问题。每一方生成一对数学关联的密钥:公钥(可公开分享)和私钥(严格保密)。用公钥加密的内容,只有对应私钥才能解密。
常见非对称密钥类型:
- RSA-2048 — 2048 位模数,兼容性广,速度慢。用于 TLS 证书。
- RSA-4096 — 更高安全性,速度更慢。
- Curve25519(X25519) — 256 位椭圆曲线密钥,速度快,Signal 和 WireGuard 均采用。
- Ed25519 — 256 位签名密钥,用于 SSH 和 Git 提交签名。
私钥大小为 32–512 字节,取决于算法。RSA 私钥较大,因为包含多个质数;Curve25519 私钥就是 32 字节的随机数。
混合加密:实际系统的标准方案
任何实际系统都不会直接用 RSA 加密大文件。TLS、PGP、Age、Signal 等每一个严肃的文件传输协议都采用混合加密:
- 生成随机 256 位 AES 密钥("会话密钥"或"文件密钥")。
- 用 AES-256-GCM 加密文件。
- 用接收方公钥加密会话密钥。
- 将两者一起发送。
接收方用私钥解密会话密钥,再用会话密钥解密文件。同时获得对称加密的速度优势和非对称加密的密钥分发便利性。
对于基于浏览器的文件传输,"公钥"通常被 URL 片段取代:发送方生成会话密钥,嵌入 URL 的 # 部分,接收方浏览器在本地读取。更简单,且不要求接收方持有密钥对。
从密码派生密钥
用户输入的是密码,算法需要的是均匀分布的随机比特。密钥派生函数(KDF)在两者之间架桥:
- PBKDF2-HMAC-SHA-256 — 迭代哈希函数。OWASP 2023 建议 60 万次迭代。Web Crypto API 原生支持。
- scrypt — 内存硬化,抵抗 GPU 攻击。推荐参数:
N=2^17, r=8, p=1。 - Argon2id — 当前最佳实践,2015 年密码哈希竞赛获胜者。推荐参数:
内存=64 MB, 迭代=3, 并行度=4。
KDF 通过加盐(随机生成,与密文一起存储)和工作因子(迭代次数)来降低暴力破解速度。一个 12 位随机密码经过 Argon2id(64 MB 内存)处理后,GPU 集群穷举需要数千年。而弱密码如 summer2024 无论使用什么 KDF,都会在秒级被破解——KDF 无法凭空增加原本不存在的熵。
密钥存储:密钥住在哪里
密钥必须存储在某处,这个"某处"是安全的关键决策:
- 浏览器内存(仅限会话)。 临时文件传输的默认方式。密钥在页面生命周期内生成、使用、丢弃。
- URL 片段。 通过链接共享,存储在接收方浏览器历史记录中。有效期限至关重要。
- LocalStorage / IndexedDB。 持久存储,但源站的任何 JavaScript 均可访问。除非用另一密钥加密,否则有风险。
- 操作系统钥匙串 — macOS Keychain、Windows DPAPI、Linux libsecret。部分平台有硬件级支持。
- 硬件安全模块(HSM) — YubiKey、云端 HSM(AWS CloudHSM、Azure Dedicated HSM)。密钥永不离开硬件。
- 密钥管理服务(KMS) — AWS KMS、Google Cloud KMS、HashiCorp Vault。集中管理,可审计,价格约 1 美元/密钥/月。
对于零知识文件传输,密钥存在于 URL 片段和发送方的浏览器中,服务器从不存储它。
密钥轮换与销毁
长期使用的密钥积累风险。最佳实践是定期轮换:
- TLS 证书: 90 天轮换(Let's Encrypt 默认),自 2020 年起公共 CA 最长 398 天。
- 数据加密密钥: 在合规系统中通常每 90 天至 1 年轮换一次(PCI DSS 4.0 要求 3.6)。
- 主密钥: 每年轮换,或在人员变动时轮换。
销毁同样重要。简单删除密钥文件是不够的——固态硬盘可能在磨损均衡区域保留数据。安全销毁需要覆写或专用 HSM 删除命令。密码学擦除——丢弃密钥使加密数据永久不可读——通常是处理大量数据的最彻底方案。
文件传输服务通常使用每文件独立密钥,密钥仅在传输生命周期内(24 小时至 7 天)存在,到期后与密文一同销毁。
识别薄弱的密钥实践
三种常见失败模式值得警惕:
- 客户端代码中硬编码密钥。 如果所有用户共用同一密钥,那不是密钥——那是混淆。
- 密钥与密文存储在同一服务器或数据库中。 一旦发生数据泄露,两者同时暴露。
- 没有密钥轮换机制。 使用十年前加密密钥的遗留系统,承担着长达十年的累积泄露风险。
声誉良好的服务商会发布密码学技术白皮书,说明密钥生成、存储、轮换和销毁的机制,并接受 Cure53 或 Trail of Bits 等第三方机构的审计。
实际建议
对于敏感文件共享:选择通过 crypto.getRandomValues() 在客户端生成 256 位密钥、密钥仅嵌入 URL 片段(从不发送至服务器)、支持通过 PBKDF2 或 Argon2id 派生密码密钥、且密钥与密文均在 24 小时内自动过期的服务。
在 hexatransfer.com 上试试 — 免费、无需注册、最多 10 GB。