E2EMail中PGP/MIME邮件的构建、解析与解密:PgpMail库加密邮件实战全解析

📅 2026/8/23 11:45:17
E2EMail中PGP/MIME邮件的构建、解析与解密:PgpMail库加密邮件实战全解析
E2EMail中PGP/MIME邮件的构建、解析与解密PgpMail库加密邮件实战全解析【免费下载链接】e2emailE2EMail is a simple Chrome application - a Gmail client that exchanges OpenPGP mail.项目地址: https://gitcode.com/gh_mirrors/e2/e2emailE2EMail是一个基于 Chrome 的 Gmail 客户端应用专门用于收发OpenPGP 加密邮件。本文将带你完整解析 E2EMail 中PGP/MIME 加密邮件的全生命周期如何借助PgpMail 库构建加密邮件、如何解析收件箱中的加密附件、以及如何解密并验签。即使你零加密基础也能看懂这套加密邮件系统的实战流程 上图E2EMail 的端到端加密流程——发件人Sender的加密邮件通过云端传输给收件人Receiver只有持有私钥的一端才能解锁内容什么是 PGP/MIME为什么需要它PGP/MIME 是一种将 PGP 加密藏进标准 MIME 邮件格式的技术。它的核心结构长这样multipart/encrypted (外层容器) ├── application/pgp-encrypted (协议标记告诉收件人我是加密邮件) └── application/octet-stream (真正的加密数据通常存成 .asc 附件)E2EMail 的设计目标是连 Gmail 服务商本身都无法看到邮件内容。所有发信自动签名加密收信自动解密验签对非技术用户完全透明。构建加密邮件从明文字符串到 PgpMail MIME 树第一步加密与签名encryptSign发送流程的入口在 encryptAndSendMail()chrome/components/gmail/gmail-service.js把收件人列表补上自己自己也收一份并去重用withMyKey_()取出本地私钥用withPublicKeys_()取齐所有收件人的公钥调用 openpgp-service.js 中的 encryptSign() 对明文做签名 多收件人加密得到一段 ASCII armored 格式-----BEGIN PGP MESSAGE-----开头的密文 加密运算并不在页面主线程里跑而是由 OpenPgpService.initialize() 启动的独立Workere2e.async.Worker执行避免卡住 UI。第二步PgpMail 构建 PGP/MIME 邮件树拿到密文后sendPgpMimeMail_()会调用pgpMimeWrap_()组装完整邮件。真正的重活交给PgpMail 库e2e.openpgp.pgpmime.PgpMail构建时从 end-to-end 库拉取constructPgpMimeMessage_(content, subject, from, to, preamble, inReplyTo) └── new PgpMail({body, subject, from, to, inReplyTo}, preamble) └── pgpMime.buildPGPMimeTree() ← 生成标准 PGP/MIME 报文对应源码在 constructPgpMimeMessage_()chrome/components/gmail/gmail-service.js。注意三个细节主题、发件人、收件人都会先经过mimeSanitize_()即goog.i18n.mime.encode做 RFC 2047 编码保证中文主题不会破坏报文结构回复邮件会通过In-Reply-To头挂到原会话线程preamble前言是写给不支持加密的邮件客户端看的提示文案普通 Gmail 用户打开时看到的就是这段引导文字最后sendRFC2822Message_()把整封 RFC 2822 报文做 URL 安全 Base64 编码后 POST 到 Gmail API 的/messages/send端点完成发送。解析加密邮件如何从收件箱中识别 PGP/MIME解密前得先找到加密邮件。E2EMail 的策略分两层第一层服务端粗筛。refresh()刷新邮箱时用 Gmail 搜索语法直接过滤出可疑邮件见 GMAIL_SELECT_ATTACHMENTS_QUERY_(has:pgpencrypted OR (BEGIN PGP MESSAGE has:attachment filename:asc)) (in:inbox OR has:userlabels)第二层元数据校验。对每封候选邮件processMetaData_()只拉取 MIME 头不发全文确认Content-Type存在后才把它索引进本地邮箱模型并按线程thread分组展示。解密与验签打开一封加密邮件的完整链路点击某个线程时refreshThread()会为其中每封未取过正文的邮件启动一条解密流水线关键函数是 processPGPMimeAttachment_()步骤做什么关键代码位置1️⃣ 取发件人公钥走 TOFU首次信任/变更告警校验getVerifiedPublicKey_()2️⃣ 拉取全文通过 Gmail API 拿到payload.partsfetchAndDecryptMessage_()3️⃣ 定位密文部分校验 2 个 part 中恰有一个是application/pgp-encrypted标记取另一部分的attachmentIdprocessPGPMimeAttachment_()4️⃣ Base64 解码atob()还原出 armored 密文decryptData_()5️⃣ 解密验签decryptVerify(pgpData, 自己的私钥, 发件人公钥)openpgp-service.js6️⃣ 签名校验若成功签名列表中没有发件人指纹则打上invalidSignatureError警告hasGoodSignature_()第 5 步的decryptVerify()会同时完成两件事用私钥解密用发件人公钥验签。如果签名无效邮件仍能打开但界面上会显示醒目的警告——这正是加密保证机密性签名保证来源真实性的经典分工 解密后的渲染MIME 内容解析解密得到的明文本身还是一封 MIME 邮件因为发送端是用PgpMail包过 MIME 的。extractMimeContent_()负责把它变成界面元素判 MIMEisMime_()检查头部是否有Content-Type:不是 MIME 就直接当纯文本显示向后兼容建树e2e.openpgp.pgpmime.Utils.parseNode(message)把 MIME 报文解析成对象树遍历mimeTreeWalker_() 递归行走节点树text/plain→ 文本块直接渲染multipart/mixed→ 递归展开子节点Content-Disposition: attachment→ Base64 解码成 Blob生成可下载链接支持 txt 和 gif/jpeg/png/bmp/webp 图片预览其他类型 → 显示不支持提示解析结果最终写入 mail-model.js 定义的Mail.mimeContent数组由 Angular 视图渲染。核心文件速查表想深入源码的话按这条链路阅读效率最高模块路径职责邮件收发服务gmail-service.jsPGP/MIME 构建、索引、解密编排OpenPGP 服务openpgp-service.js加解密、密钥管理、恢复码邮件数据模型mail-model.jsMail/Thread/Mailbox 类型定义应用入口app.jsAngular 应用装配构建脚本do.sh./do.sh build一键构建本地构建只需三步git clone https://gitcode.com/gh_mirrors/e2/e2email cd e2email ./do.sh setup ./do.sh build然后在chrome://extensions开启开发者模式加载已解压的扩展程序并选择build/e2email目录即可。小结E2EMail 把一套完整的 PGP/MIME 加密邮件系统压缩成了三块拼图构建PgpMail.buildPGPMimeTree()一行调用自动生成合规的multipart/encrypted报文解析两层过滤服务端搜索语法 MIME 头校验精准定位加密附件解密Worker 线程内解密验签MIME 树递归渲染最精妙的设计在于对用户的隐形——你只管在 Gmail 里正常写信加密、签名、密钥查找、线程校验这些脏活累活全部由服务层自动完成。这就是面向普通用户的端到端加密应用应有的样子 ✉️【免费下载链接】e2emailE2EMail is a simple Chrome application - a Gmail client that exchanges OpenPGP mail.项目地址: https://gitcode.com/gh_mirrors/e2/e2email创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考