6.3 安全邮件与文件加密:PGP 与混合加密


6.3 安全邮件与文件加密:PGP 与混合加密

本节摘要:PGP 在 1991 年把"对称快、非对称解决分发"的混合加密格局带给普通人,也把密码学推上了与出口管制对簿公堂的舞台;三十年后,同样的信封结构支撑着文件加密工具与全盘磁盘加密。本节拆解数字信封的组装方式、信任网与证书路线的分野,并给出当下工具选型的务实建议。

在没有平台兜底的地方自建保密

TLS 保护的是"传输途中",但邮件的历史包袱让端到端保密很难搭便车:邮件会在多台服务器间转发、被服务器存档索引,发件与收件之间隔着不设防的明文地带。1991 年,菲尔·齐默曼写出 Pretty Good Privacy(PGP),让两个普通人在没有任何基础设施的情况下互发保密邮件——这直接踩中了当时的敏感神经:强加密在美国出口管制下被视为军火,司法部以"未经许可出口军火"对齐默曼立案调查,直到 1996 年撤诉。这段"密码战争"史在 7.4 节还会回响,它确立了一件今天看来理所当然的事:个人使用强加密合法且正当。

PGP 的技术遗产是一副数字信封,组装次序与第 4 章的结论严丝合缝:

  • 发送方现场生成一把一次性对称会话密钥(数据量再大,非对称运算也只有这一把钥匙的份);
  • 用会话密钥以对称算法(AES 之类)加密全部正文——重活交给快的;
  • 用每位收件人的公钥分别加密这把会话密钥,附在密文前——"信封"封口交给慢的;
  • 若需认证,发送方再用自己的私钥对内容签名,构成"签了名的信封"。

收件人反向拆封:私钥解出会话密钥,对称解出正文。多收件人场景只是多贴几层封口,正文密文只存一份——这正是 PGP、OpenPGP(其开放标准)、S/MIME 以及现代文件加密工具共用的骨架。

二、信任的两种路线:信任网与证书树

PGP 与 6.2 节的 WebPKI 走了截然不同的信任路线。PGP 没有中心 CA,采用信任网(Web of Trust):用户之间互相签署对方的公钥,信任沿着签名链传递;公钥真伪靠指纹(公钥的 SHA-1 或 SHA-256 摘要)当面或带外核对。它浪漫而彻底地去中心化,代价是可用性——密钥管理、指纹核对、密钥丢失后的吊销传播,每一步都在劝退普通用户;学者对 PGP 易用性的著名研究标题就叫"为什么 Johnny 还不会加密"。现实中,邮件端到端加密始终是极客的圈子,即时通讯领域改由 Signal 协议(双棘轮密钥轮换)接棒,把密钥管理全部自动化后才真正普及了端到端。

企业邮件的答案是 S/MIME:沿 X.509 路线,证书由公司内部 CA 或公共 CA 签发,信任模型与 WebPKI 同构。两种路线的取舍见下表:

维度 PGP / OpenPGP S/MIME
信任模型 信任网,用户互签 CA 层级,同 WebPKI
公钥核对 指纹带外比对 验证书链
部署成本 零基础设施,自管理 需要证书签发体系
典型场景 个人、开源社区 企业邮件与合规审计
易用性 密钥管理全靠自觉 与既有 PKI 体系融合

文件与磁盘加密走的则是信封结构的第三种落地。文件加密:老牌的 GPG 既可对称口令加密也可公钥信封;新工具 age 把这套模式精简到两条命令,内部就是 X25519 信封加 ChaCha20-Poly1305。全盘磁盘加密(BitLocker、FileVault、LUKS)同样是一个信封:数据用 AES-XTS 加密,而解锁数据密钥的"信封钥匙"由口令派生密钥或可信平台模块(TPM)保管——开机输入的那次口令,换来整块硬盘的静态安全。下面用标准库把口令信封完整复刻一遍:

import hashlib, os, hmac def envelope_encrypt(data: bytes, password: str) -> bytes: salt, nonce, dek = os.urandom(16), os.urandom(12), os.urandom(32) kek = hashlib.scrypt(password.encode(), salt=salt, n=2**15, r=8, p=1, dklen=32) stream = bytearray() counter = 0 # 以 kek+nonce 造流,演示信封结构 while len(stream) < len(data): stream += hashlib.sha256(kek + nonce + counter.to_bytes(8, "big")).digest() counter += 1 wrapped = bytes(a ^ b for a, b in zip(data, stream)) # DEK 之外:数据用会话密钥流加密 tag = hmac.new(kek, salt + wrapped, hashlib.sha256).digest() # 完整性标签 return salt + nonce + tag + wrapped def envelope_decrypt(blob: bytes, password: str) -> bytes: salt, nonce, tag, wrapped = blob[:16], blob[16:28], blob[28:60], blob[60:] kek = hashlib.scrypt(password.encode(), salt=salt, n=2**15, r=8, p=1, dklen=32) if not hmac.compare_digest(hmac.new(kek, salt + wrapped, hashlib.sha256).digest(), tag): raise ValueError("口令错误或数据被篡改") # 先验标签,再解数据 stream, counter = bytearray(), 0 while len(stream) < len(wrapped): stream += hashlib.sha256(kek + nonce + counter.to_bytes(8, "big")).digest() counter += 1 return bytes(a ^ b for a, b in zip(wrapped, stream)) blob = envelope_encrypt("绝密会议纪要".encode(), "我的口令") print(envelope_decrypt(blob, "我的口令").decode())

⚠️ 常见坑:把加密压缩包(如某些压缩工具的旧默认)当成安全文件加密——历史版本多用弱密钥派生且无认证标签。文件加密请用 age 或 GPG 这类专用工具,它们内部替你把信封、AEAD 与密钥派生全部做对。

本节要点回顾

  • 数字信封:随机会话密钥加密正文、各收件人公钥分别封口,PGP、S/MIME、age 与磁盘加密共用这一骨架;
  • PGP 的遗产:技术上是信封结构的普及,历史上是"个人加密权"经司法程序确认的分水岭;
  • 信任分野:信任网去中心但难用,S/MIME 沿 CA 路线好管理;即时通讯的端到端最终由 Signal 协议的自动化密钥管理破局;
  • 静态数据:磁盘加密的口令只解锁密钥层级顶端,数据面永远是对称算法的天下。

从传输到静态存储,密码学的"防御性应用"还有一块最年轻的大陆。下一节看区块链如何把哈希与签名从"保护通信"改造成"构建共识"。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U