安全政策
Herkos 处理私钥和加密消息,因此我们认真对待安全报告,宁愿尽早而不是太晚得知问题。
报告漏洞
请不要为安全问题创建公开 issue。
请发送电子邮件至 security@herkos.email 私下报告。
建议包含以下内容:问题是什么、如何复现、你测试的平台和版本,以及攻击者能够达成什么。 提供概念验证会很有帮助。
切勿在报告中附上你自己的 nsec、私钥或 bunker 密钥。
我们力求在几天内确认收到报告。由于 Herkos 是一个小项目,请在公开披露之前给我们留出 合理的修复时间。除非你另有意愿,我们很乐意在安全公告中致谢你。
适用范围
Herkos 应用本身:密钥的处理与存储、消息的加密与解密(包括 local_packages/nostr_mail
中的 NIP-59 发件人校验和密送(Bcc)隔离)、应用锁、与中继和桥接服务的通信、附件处理,
以及构建与发布流程。对于 Herkos Drive,还包括它的协议包(packages/herkos_drive_protocol)
和打开其链接的页面(herkos.app/f/);见下文它自己的一节。
不在范围内
- Nostr 协议及其 NIP 本身——请向上游报告。
- 由第三方运营的中继、桥接服务和 Blossom 服务器。 Herkos 自带默认配置,但并不运营 它们;请向其运营者报告问题。
- 上游项目 Nostr Mail Client, 除非问题特定于 Herkos 所做的修改。
- 我们已作为已知局限记录在案的加固缺失(见下文)。
已知局限,直言不讳
这些是设计上的取舍,而不是漏洞。我们宁愿把它们写下来,也不愿让别人吃了亏才发现:
- 发往传统地址的邮件不是端到端加密的。 Nostr 用户之间的消息使用 NIP-17 gift wrap, 是端到端加密的。当你给普通电子邮件地址写信时,桥接服务会转换消息,并能读取它。
- 应用锁(PIN 和生物识别)是便利性的屏障,而非静态加密。它能阻止拿起一台已解锁 设备的人;但无法防范能够完全访问设备或其存储的攻击者。
- 在 Windows 上无法强制只使用生物识别验证。 Windows Hello 不允许选择验证方式, 因此系统 PIN 始终可作为备用方式。
- 丢失密钥就意味着失去账户。 设计上就没有恢复机制。
- 元数据并未完全隐藏。 中继可以观察连接模式,而且每个中继都能看到你的 IP 地址, 即使它们无法读取消息内容。Herkos 不会泄露的(自 2026 年 9 月 30 日起)是:当中继要求 NIP-42 认证时,谁在给谁写信:
- 查询投递地址。 收件人的中继列表和 Blossom 列表是通过一条从不标识你身份的独立连接
查询的,并优先查询不要求认证的中继(
purplepag.es、user.kindpag.es、nos.lol、offchain.pub)。 - 个人资料与定时服务。 显示的其他任何人的名称和头像(kind 0),以及你定时发送或 取消定时邮件时定时 DVM 的中继列表,都以同样的方式查询:先匿名查询,如果中继坚持 要求,则使用下文所述的临时密钥,绝不使用你的密钥(自 2026 年 10 月 1 日起;在此之前, 要求认证的中继会得到你的密钥,并能得知你在查看谁的资料)。只有你自己的个人资料 仍以你的身份读取。
- 投递。 gift wrap 会通过同一条独立连接发往收件人的 DM 中继。如果其中某个中继 要求认证,Herkos 会使用一个专门为此生成、只保存在内存中的密钥来应答,绝不使用你的 密钥;设备上的每个账户都有各自的临时密钥。中继仍然可以看到,同一台设备(相同的 IP、相同的临时密钥)在一次会话中发送了多个信封。
- 大邮件。 超过 32 KB 的邮件,其加密副本会上传到 Blossom 服务器,包括收件人的服务器。 只有你自己的服务器(你的 Blossom 列表)会收到用你的密钥授权的上传。其他任何服务器 都以匿名方式收到上传;如果它坚持要求授权,则使用与上文相同的临时密钥签名的授权 (自 2026 年 10 月 1 日起;在此之前,每台服务器都会得到你的密钥)。只接受已知密钥的 服务器会拒绝上传,副本则保留在其他服务器上。
- 你自己的数据。 同步你的邮箱、标签、设置和草稿时,如果中继要求,会以数据所属的 账户身份进行认证,即使在切换账户期间也是如此。对你自己的中继来说,这并没有告诉 它们任何新信息:这些请求本来就写明了你的密钥。你自己的中继列表和 Blossom 列表是 公开的,查询时不会标识你的身份,邮件链接中提到的中继也是如此。
- 已读状态和文件夹是公开元数据(目前如此)。 将邮件标为已读、加星标、归档或移动时, 会发布一个与你的公钥关联、未加密的 NIP-32 标签事件,其中包括自定义文件夹的名称。 知道自己发给你的某封邮件 id 的发件人可以得知你何时对它进行了操作。我们计划对这些 标签加密;在此之前,请把文件夹名称视为公开信息。
- 推送通知和定时发送使用第三方服务。 推送服务器(仅在你选择时使用;默认没有;如需要,可用
api.nmail.li加relay.nmail.li)会得知 你的公钥、推送令牌以及你何时收到邮件;定时 DVM 会得知你的公钥以及它需要发布的、 已加密的消息。两者都需要你主动开启,并在PRIVACY.md中有说明。推送通知的文本由 推送服务器决定,Herkos 只有在 UnifiedPush 以加密方式(RFC 8291)送达时才信任它; 未加密的内容只会唤醒应用,由应用自行获取邮件。 - 网页版把你的密钥保存在浏览器中,这是保管密钥最薄弱的地方。 已安装的应用会把 你的私钥交给操作系统的安全存储(Android Keystore、Windows 上的 DPAPI、libsecret、 iOS/macOS 钥匙串)。浏览器没有这些:密钥存放在该源(origin)的存储中,每次签名都会 经过 JavaScript,页面中运行的任何代码都能触及它——能访问所有网站的浏览器扩展、应用 或其依赖中的 XSS 漏洞、被篡改的部署——复制浏览器配置文件的任何窃密软件也能拿到它。 而且也不存在一个让你一次性验证代码的时刻:已签名的二进制文件在安装时接受检查,网页 则在每次访问时都下发新的代码。请使用远程签名器(NIP-46 bunker、Amber)登录网页版, 让密钥永远不进入浏览器;或者把它当作一次性身份,把你真正的密钥保存在已安装的应用中。
- 经桥接服务转发的邮件,其可信度取决于桥接服务本身。 Herkos 会验证标记为经桥接
服务转来的消息,确实是由你配置的某个桥接服务(或某个默认桥接服务)签名的。但它无法
对桥接服务转发的传统
From:地址做任何验证。 - 附件由操作系统打开。 Herkos 从不启动可执行文件或脚本类型的文件,并且在把其他任何 无法预览的附件交给系统默认应用之前都会先询问你,但打开文件的应用不在我们的控制范围内。
Herkos Local Relay:它保护什么,不保护什么
Herkos Local Relay 把你的应用的事件保存在你的设备上,私密事件也不例外(草稿、私密列表、 你收到的信封)。下面按平台说明是什么在保护它们,以及界限在哪里。中继的安全问题请按与其他 问题相同的方式报告(见上文)。
整个数据库都是加密的,连同其日志文件(SQLite3 Multiple Ciphers、AEGIS-256)。密钥是 在设备上生成的 32 个随机字节,保存在系统的安全存储中:Android 上是 Keystore,Windows 上是 DPAPI,Linux 上是密钥环(libsecret)。它不使用你的任何密码,因为中继必须能自行启动。没有 密钥,中继就不会启动,并会说明这一点:它绝不会打开或创建未加密的数据库,也绝不会删除它 无法打开的数据库。
| 如果… | Android | Windows | Linux |
|---|---|---|---|
| 有人复制了数据库文件(备份、同步文件夹、磁盘镜像) | 受保护 | 受保护 | 受保护 |
| 设备或磁盘在关机状态下被盗 | 受保护:密钥在 Keystore 中 | 受保护,除非对方知道你的 Windows 登录密码:DPAPI 用该密码保护密钥 | 受保护,除非对方知道你的密钥环密码(几乎总是你的会话密码) |
| 同一设备上的另一个用户账户 | 受保护 | 受保护:DPAPI 按用户区分 | 受保护:密钥环按用户区分 |
| 以你的用户身份运行的另一个应用或程序 | 受保护:Android 将每个应用相互隔离,Keystore 只把密钥交给中继 | 不受保护:DPAPI 按用户加密,而不是按应用;以你的身份运行的程序可以像中继一样请求密钥 | 不受保护:你会话中的密钥环不会把应用彼此隔开 |
| 已 root 的手机,或以该应用身份执行代码的工具 | 不受保护 | — | — |
| 有人拿着已解锁的设备 | 只有中继的 PIN 或指纹(如果你设置了) | 同上 | 同上 |
| 有人在中继运行时读取其内存 | 不受保护 | 不受保护 | 不受保护 |
在桌面系统上,DPAPI 和密钥环的界限与任何程序相同:它们能防范其他用户和拿走磁盘的人, 但无法防范已经以你的身份运行的恶意程序。如果你担心这种情况,能保护你的是系统盘加密 (BitLocker、LUKS),以及不运行你不信任的程序。在没有密钥环(没有 Secret Service)的 Linux 上,中继不会启动,并会说明原因:它绝不以明文保存密钥。
在设备本身上,谁能进入。 中继只在 127.0.0.1 上监听,而设备上的任何应用,或浏览器中的
网页,都能访问这个地址。因此:
- 应用必须先配对:它会出现在中继的屏幕上,由你批准(如果你设置了 PIN 或指纹,则用它们)。 任何应用都可以给自己起任何名字:只有在你刚刚从那个应用发起请求时才批准。
- 网页总是必须配对,而且配对只在发起配对的地方有效:设备上某个应用的配对不会为网页开放 任何东西,即使该网页使用相同的密钥签名。
- 已配对的应用只能读写你授予它的事件类型,也只能删除它可以写入的那些。撤销它会立即断开 它的连接。
- 未配对的应用只能读取你的公开事件(它们本来就是公开的),不能写入任何内容,除非你开启 允许设备上未配对应用进入的设置。
- 私密事件只交给能通过 NIP-42 证明自己持有其所属密钥的一方,信封只交给其收件人。
在这方面,它不能防范的是:
- 设备上的恶意应用可以拖慢中继,或让它消耗内存。但它无法借此读取任何私密内容。
- 中继休眠或未运行时,它的端口是空闲的。 在 Android 上,它在 10 分钟没有连接后休眠;在 桌面系统上,只要你还没启动它,端口就是空闲的。其他应用可能在那里监听并冒充中继。Herkos 应用将在向中继发送任何私密内容之前检查它的密钥;目前还没有这样做,在此之前这是一个 真实存在的局限。
- 在桌面系统上,这台电脑的其他用户可以作为未配对的应用连接:读取你的公开事件,并请求 配对。
本地网络,如果你开启它(默认关闭):
- 只用
wss://,使用中继自己的证书;在设备之外绝不使用未加密的ws://。 - 在用你列表中的密钥完成认证(NIP-42)之前,什么都不行。30 秒内未完成认证的连接会被关闭, 而且本地网络有自己的连接数量:绝不占用设备上应用的连接。
- 列表中的密钥可以读取你的公开事件和它自己的私密事件,并且只能写入由它签名的事件。把它从 列表中移除会断开它的连接。
- 证书只对家中的名称(
localhost、.local、私有地址)有效:即使有人窃取了它的密钥,也无法 在安装了该证书的设备上用它为互联网域名签名。
在这方面,它不能防范的是:同一网络中的任何人都能看到设备有一个开放端口,以及有多少流量 经过它,但看不到内容;如果设备有公网地址(中间没有路由器),这个端口可以从互联网上看到, 不过它仍然要求提供你列表中的密钥。
备份。 加密备份有密码(scrypt 和 XChaCha20-Poly1305):没有密码,任何人都无法打开它, 包括我们。JSONL 导出不加密,会以明文包含你的私密事件;应用会提醒你这一点。
锁定(PIN,加上指纹或 Windows Hello)会在打开应用时、离开 30 秒后,以及批准配对时要求 输入。它是一道便利性的屏障,和 Mail 中一样:它不加密任何东西。在 Android 上,设置 PIN 后 不能截屏,最近使用的应用中也不显示缩略图;而且从 Android 12 起,你使用中继时,其他应用的 窗口无法覆盖在中继的窗口之上。
Herkos Drive:它保护什么,不保护什么
Herkos Drive 把你的文件保存在 Blossom 服务器上,把你的文件和文件夹列表保存在 Nostr 中继上,两者都在你的设备上加密。
下面说明是什么在保护它们,以及界限在哪里。
完整细节见 packages/herkos_drive_protocol/ 中的 spec-drive.md 和威胁模型 amenazas-drive.md;每个中继和服务器能看到什么,见隐私政策。
Drive 的安全问题请按与其他问题相同的方式报告(见上文)。
中继和服务器做不到的事:
- 读取你的文件或文件名。 文件的每个数据块都在其所属修订版本自己的密钥下用 AES-256-GCM 加密;名称、文件夹、大小、日期和密钥在其所在文件夹的密钥下用 XChaCha20-Poly1305 密封后发送。 没有任何东西是从内容派生的:同一个文件上传两次会得到不同的数据块。
- 在不被察觉的情况下更改、调换或移动任何东西。 每个数据块都会与其文件条目中密封的清单进行核对,每个条目都由卷密钥签署,并针对它自己的位置(卷、标识符和文件夹)密封:中继无法把一个条目冒充成另一个条目,也无法把一个数据块冒充成另一个数据块。
- 恢复旧版本。 对于同一个标识符,应用从不接受比它已有条目更旧的条目。
- 仅凭卷密钥以你的身份写入。 你的设备写入的内容带有所有者标记,即一个使用任何链接都不会给出的密钥计算的 HMAC;没有该标记的条目或删除不会被接受,应用会提醒你。
它不保护的:
- 你的 Drive 的模式。 中继可以统计你的文件和文件夹数量,看到目录树的形状以及每个条目何时变化;服务器能看到每个文件的大致大小(数据块填充到 64 KiB,条目填充到 2 的幂)。 每个中继和服务器都能看到你的 IP 地址。如果这对你很重要,请在系统层面使用 Tor 或 Orbot。
- 别人已经下载的内容。 移除一个链接或一个人,会立即给他们能打开的内容换上新密钥,这样他们就打不开你之后添加的内容;但它无法收回他们已经保存的东西。
- 泄露的链接。 没有密码的链接就是密钥。在页面把它从地址栏移除之前,浏览器可能已将其保存在历史记录中。 对于任何敏感内容,请给链接设置密码,并通过其他途径发送,或者与对方的账户共享。弱密码假以时日可能被破解:拥有链接的人可以离线尝试。
- 页面
herkos.app/f/在打开链接的人的浏览器中运行。它在提供时使用严格的 Content-Security-Policy 和 Subresource Integrity,且没有任何第三方代码,但控制网站托管的人可以提供一个不同的页面。 这是所有在浏览器中解密的网页的共同界限。 - 曾经持有卷密钥的人(你自己的,或随文件夹链接给出的)仍然可以删除用它上传的数据块,直到这些数据块被重新上传。 你可以更换卷密钥(设置 → 卷密钥):你的其他设备会自动跟进。
- 你的设备。 文件列表加密缓存,其密钥保存在系统的安全存储中;你下载或打开的文件会以明文写入你选择的位置。 Drive 的 PIN 是一道便利性的屏障,和 Mail 中一样。
- 将来的量子计算机。 数据块和密封是对称加密(AES-256、XChaCha20),但你的定位器是用基于 secp256k1 的 NIP-44 加密的:今天保存了它、明天破解了 secp256k1 的人,就可能打开整个 Drive。
如何检验。 对照威胁模型进行的两次内部审查(2026 年 11 月 2 日)及其修复;对每个事件和数据块所暴露内容的测试;对每个读取外部来源内容(事件、密封、清单、链接、备份)的解析器进行模糊测试。 尚无外部审计:计划在公开测试版之前进行一次,其报告将全文公布。Drive 仍在开发中。
受支持的版本
安全修复只应用于最新发布的版本。鉴于项目规模,旧版本不再维护——报告前请先更新。