Skip to content

NIP-17: 私信安全指南

了解 NIP-17,NIP-04 的安全替代品,以及如何在 Nostr 中迁移你的私人消息

12-15 分钟 高级 · 第 2 篇,共 3 篇 最后更新

NIP-17 代表了 Nostr 私信工作方式的重大安全升级。本指南解释为什么你应该关注这个协议改进,如何从旧的 NIP-04 标准迁移,以及如何保护你的通信安全。

什么是 NIP-17?

NIP-17 是一个 Nostr 协议规范,定义了使用称为 “seal + gift wrap” 的双层加密系统的私人直接消息。它是为了解决之前 NIP-04 加密方法的基本安全缺陷而创建的。

与使用单层 AES-256-CBC 加密的 NIP-04 不同,NIP-17 使用:

  1. Seal(kind 13):内层,用你的真实密钥签名,让收信人能确认这条消息真的出自你手
  2. Gift Wrap(kind 1059):外层信封,由一个用完即弃的一次性密钥签名。它把 seal 藏了起来,因此你的真实身份绝不会出现在中继所存储的那个事件上

这种分层意味着:

  • 消息内容保持私密
  • 中继看不出消息是谁发的。给 gift wrap 签名的是一把随机的一次性密钥,不是你的密钥
  • 时间戳经过随机化处理,消息的发送时机更难被关联分析

为什么 NIP-17 重要:NIP-04 安全问题

NIP-04 是 Nostr 的原始私信协议,但它有几个关键的安全问题,使其不适合真正私密的通信。

比较:NIP-04 vs NIP-17

功能NIP-04NIP-17
加密单层 AES-256-CBC双层(seal + gift wrap)
发送者元数据对中继可见隐藏(由一次性密钥签名)
接收者元数据对中继可见仍然可见(明文 p 标签)
消息内容加密加密
时间元数据真实时间戳可见随机往前推最多两天
前向保密否(NIP-44 不提供前向保密)
安全状态已弃用推荐
互操作性广泛支持支持度正在增长

NIP-04 的核心问题

NIP-04 消息把谁在跟谁说话暴露给每一个存储它们的中继。(Nostr 没有区块链,事件只是存放在中继上,任何人都可以从中继读取。)虽然消息正文是加密的,但信封包含:

# NIP-04 事件结构(简化)
{
  "pubkey": "<sender_public_key>",      # 任何人都能看到谁发送的
  "tags": [["p", "<recipient_pubkey>"]], # 任何人都能看到谁接收的
  "content": "<encrypted_content>"       # 只有内容是隐藏的
}

这意味着中继运营商、网络观察者和数据抓取者可以:

  • 构建社交图谱,显示谁与谁通信
  • 跟踪通信模式和频率
  • 从消息时间推断关系

NIP-17 把整条消息装进一个由一次性密钥签名的外层信封里,堵上了这个缺口的大部分,中继因此看不出是谁发的。有一样东西是故意留在明处的:接收者的公钥就挂在信封上的一个明文标签里,因为中继必须知道该把消息交给谁。所以 NIP-17 藏的是发送者,不是接收者。

NIP-17 如何工作:Seal + Gift Wrap

了解技术实现有助于理解安全改进。

Gift Wrap 层(外层)

Gift wrap 就是中继真正存下来的那个信封。你的客户端会为这一条消息现生成一把全新的密钥,用它给信封签名,然后把这把密钥扔掉。信封里的内容做了加密,只有收信人打得开。这一层携带:

  • 一把随机的一次性公钥,跟你没有任何牵连
  • 接收者的公钥,放在一个中继读得到的明文标签里
  • 一个随机化过的时间戳
  • 密封好的内层消息

Seal 层(内层)

Seal 待在 gift wrap 里面。作者身份就落在这一层,而中继永远看不到它。这一层:

  • 用你的真实密钥签名,收信人正是靠它确认这条消息是你发的
  • 用一把由你的私钥和收信人公钥共同推导出来的密钥加密,所以只有你们两个读得了
  • 装着消息正文
  • 带一个被你的客户端刻意往前挪了最多两天的时间戳,好让人没法按发送时间把消息归堆

Gift Wrap(外层)

随机公钥、接收者提示,中继能看到的就只有这些

Seal(内层)

由发送者的真实密钥签名,只有接收者读得到

实际消息内容

发送者:真实公钥 · 时间戳:1234567890

每一层都把内层藏了起来,中继除了接收者提示什么也读不到。

主要优势

  1. 发送者隐私:除了收信人,没人能确定这条消息是谁发的。但收信人是写在一个明文 p 标签里的,中继必须读得到它。
  2. 不可链接性:每条消息都由一把全新的一次性密钥签名,所以同一个人发出的消息之间看不出明显的关联。
  3. 没有前向保密:NIP-44 的会话密钥是由两把静态密钥推导出来的,所以日后拿到你 nsec 的攻击者,能解开他此前保存下来的每一条消息。一次性密钥藏的是”消息是谁发的”,它保护不了已经发过的消息。如果你在意这件事,就把旧对话删掉。

投递:私信中继列表(kind 10050)

Seal 和 gift wrap 描述的是消息如何打包。还有第三个部分:kind 10050 事件,它描述消息投递到哪里。它是一份小型的、公开的中继列表,列出接收你私信的中继。

规范在这一点上非常严格:发送方必须只把 gift wrap 发布到接收者 kind 10050 列表中的中继。如果你从未发布过这样一份列表,规范就把你视为”尚未准备好接收消息”,客户端甚至不应该尝试投递。发给你的私信因此会被静默丢弃,永远无法送达。两边都不会有任何报错。

两条实用规则:

  • 在期待收到任何 NIP-17 私信之前,先发布一份(见下方迁移指南的第 3 步)
  • 保持列表精简。规范建议 1-3 个中继,而且你列出的每一个中继都能看到谁在给你发消息

迁移指南:从 NIP-04 切换到 NIP-17

使用现代 Nostr 客户端迁移到 NIP-17 很简单。以下是切换方法。

第 1 步:检查你的客户端支持

只有当对话两端的客户端都会说 NIP-17 时,它才帮得上忙。以下四个客户端在自家文档或自家源码里明确说了自己支持:

客户端NIP-17运行平台
AmethystAndroid
0xchatAndroid、iOS
Coracle网页
Snort网页

Damus 需要单独提个醒。 截至 2026 年 9 月,Damus 公布的规范支持清单里仍然没有 NIP-17,只有旧的 NIP-04。这带来两个后果,而且都很要紧。你发出的 gift wrap 消息,在用 Damus 的人那里根本不会出现。而他们发给你的东西,是以普通的 kind 4 事件发出去的,你们两个人的公钥都明晃晃挂在外面,凡是存下这条事件的中继都读得到。如果一段对话是敏感的,把它挪到上面那几个客户端里去。

Primal、Iris 和 Nos 处在一个没定论的中间地带。Primal 公开场合两边都没表态,所以就当作不确定。Iris 的私聊用的是它自己的一套双棘轮方案,而不是标准的 NIP-17,这在 Iris 内部没问题,但对 Iris 之外的情况不构成任何保证。Nos 既没列 NIP-17,也没列它所依赖的那两份规范,而且这个项目从 2025 年初起就一直没动静了。

客户端的功能清单变得比指南快。如果这里没提到你用的那个,第 5 步的测试比翻更新日志更快给出答案。

第 2 步:通常没有什么开关要打开

这一步比你以为的短。上面那几个客户端都没有在文档里写”打开 NIP-17”的开关,因为压根就没有这么个东西可找。只要对面那个人能收,它们就会自动使用 gift wrap。

所以直接跳到第 3 步,那才是真正需要你动手的部分。你现有的 NIP-04 对话原样留在那儿,也照样读得到,没有任何东西会去转换它们。

第 3 步:发布你的私信中继列表(kind 10050)

NIP-17 的发送方只会投递到你在 kind 10050 事件中列出的中继。没有这份列表,发给你的消息会被静默丢弃(见上方 投递:私信中继列表)。

  1. 在你的客户端中,寻找私信、私人消息或消息中继设置
  2. 添加一到三个接收 gift wrap(kind 1059)的中继。有些中继会拒绝它们
  3. 保存,你的客户端会替你发布 kind 10050 列表

有些客户端会在你第一次打开私聊时替你发布这份列表。但别想当然认为你的客户端做了:在依赖它之前,先在第 5 步验证消息能够送达。

第 4 步:与你的联系人沟通

NIP-17 只有在双方都支持 NIP-17 时才有效。向经常联系的人发送一条消息:

"嘿!我正在升级到 NIP-17 以获得更好的私信隐私。
如果你还没有更新你的 Nostr 客户端,请更新。
我们未来的消息将更加安全!"

第 5 步:验证它是真的能用

真正有用的那个检查,一点技术都不需要。找一个用第 1 步里那些客户端的人给你发条消息,然后你回一条。两个方向都到了,就说明你的 kind 10050 列表已经发布出去,gift wrap 也确实能送到你手里。如果你的消息消失了,而且你们俩都没看到任何报错,那就是典型的”没有中继列表”症状,回到第 3 步。

你一个人也能做同样的测试:在第二个客户端上登录同一个账号,或者,如果你的客户端允许,就给自己发消息。

如果你好奇实际发出去的到底是什么,用 njump.me 这类 Nostr 事件浏览工具,可以看到原始事件。一个正常工作的 gift wrap 大致长这样:

// NIP-17 事件示例(简化)
{
  "kind": 1059, // Gift wrap 事件
  "pubkey": "<random_ephemeral_key>", // 不是真实发送者!
  "tags": [["p", "<recipient_pubkey>"]],
  "content": "<encrypted_seal_content>"
}

这里有两处值得看。pubkey 是一把你根本认不出来的一次性密钥,这正是发送者被藏起来的样子,也正是你想要的。p 标签里确实是接收者的真实密钥。这不是你哪里没配好,中继需要靠它才知道这条消息该送去哪儿。

安全最佳实践

在使用 NIP-17 时最大化你的隐私:

1. 在敏感通信前验证客户端支持

在分享任何敏感内容之前,始终确认你的联系人用的是支持 NIP-17 的客户端。把 gift wrap 发给一个只会 NIP-04 的人,消息不会变成乱码送到。它根本就不会送到:对方的客户端从来不会去找 kind 1059 事件,而且你们两个人都不会收到任何报错。

2. 退回 NIP-04 是一个需要认真掂量的决定

有些客户端会允许你把一段旧的 NIP-04 对话继续下去。偶尔这确实是务实的选择,但要知道代价:一条 NIP-04 消息会把两个人的公钥都明文写在一个每个中继都会存下来的事件上。把它留给那些”被公开联系到你身上也无所谓”的闲聊,凡是敏感的事,另起一段 NIP-17 对话。

3. 为高安全性对话使用新密钥

为了最大安全性:

  • 为敏感通信创建专用密钥对
  • 通过安全的外部渠道分享公钥
  • 定期轮换密钥

4. 注意其他事件类型中的元数据

NIP-17 只保护私信。其他事件类型(笔记、反应、关注)仍然暴露社交图谱数据。使用多个身份进行隔离。

5. 选择注重隐私的中继

即使使用 NIP-17,你的流量模式对中继也是可见的。使用:

  • Tor 或 VPN 获得额外的网络级隐私
  • 不记录或保留消息元数据的中继
  • 多个中继来分散你的流量

6. 了解局限性

NIP-17 是一次实打实的改进,但它不是隐身衣:

  • 中继仍然看得到你的 IP 地址(用 VPN 或 Tor)
  • 时间分析依然能揭示通信模式
  • 接收者的密钥是明文写在信封上的,这是设计如此
  • 手机或客户端一旦被攻破,什么协议都拦不住信息外泄

常见问题故障排除

「我的消息从未送达」:先检查你的私信中继列表

这是 NIP-17 最常见的故障,而且几乎从来不是加密问题。

NIP-17 的发送方不会投递到你平常使用的中继。他们会寻找一个 kind 10050 事件, 也就是你公开发布的、接收私信的中继列表,然后只把 gift wrap 发送到那里。如果你 从未发布过这样一份列表,发送方的客户端就无处投递,消息会被静默丢弃。两边的界面 都不会有任何提示。

修复方法: 在一个支持 NIP-17 的客户端里,找到私信中继设置并至少保存一个中继, 这会发布你的 kind 10050 列表。请选择真正接收 gift wrap 的中继,有些中继会直接 拒绝 kind 1059。 (这就是迁移指南的第 3 步。如果你跳过了它,请从那里开始。)

列表要短。你列出的每一个中继,都是一个能看到谁在给你发消息的中继。

“偏偏有一个联系人,我发什么他都收不到”

如果别人都收得到,只有一个人收不到,那问题出在他那一边,不在你的加密上。他的客户端几乎可以肯定不支持 NIP-17,所以它从来不会去订阅 gift wrap,也就永远看不到你的消息。不会有什么东西显示成乱码,因为压根什么都没出现。

修复方法: 请他换到第 1 步里的某个客户端。如果他做不到,而你们俩只能靠旧的 NIP-04 消息说话,那就先读一遍”安全最佳实践”里的那条警告:NIP-04 会把你们两个人的公钥明文交给每一个中继。

“看不到某人是否已读我的 NIP-17 消息”

原因:NIP-17 的已读回执尚未标准化 解决方案:这是预期行为。NIP-17 优先考虑隐私而非送达确认。

“消息顺序错乱”

原因:设备之间的时钟偏差 解决方案:确保你的设备时间已同步(启用自动时间同步)

“中继拒绝 NIP-17 事件”

原因:这个中继跑的是老版本软件,或者它干脆就拒绝存储 kind 1059 事件 解决方案:把它从你的私信中继列表里换掉,换一个别的。有些客户端会在中继界面上显示某个中继支持什么;如果你的客户端不显示,那就直接换一个中继试试消息通不通,这比去查证快得多。顺手告诉一声中继运营者,也值那一分钟。

“我的客户端让我选消息类型”

预期行为:在整个网络完成迁移之前,有些客户端仍然同时读写两种格式,并且允许你按对话选择。只要 NIP-17 摆在那儿,就选它。

Nostr 私信的未来

NIP-17 是目前 Nostr 上一对一私信的标准,今天你就应该在用它。不过它并不是终点,而它真正的两个缺口,正是人们在攻的方向:没有前向保密,也没有像样的群聊。

到目前为止最认真的答案是 Marmot 协议,它把 MLS(Signal 式群聊背后的那套群组消息标准)架在 Nostr 之上,同时保留 Nostr 密钥作为身份。Marmot 自己的仓库把这份规范列为已采纳,White Noise 就是基于它做的聊天应用。这条路子确实给出了前向保密,也确实处理了群组,恰好补上 NIP-17 缺的那两块。

有一点得澄清,因为这两个编号太容易引人误会:NIP-44 不是 NIP-17 的竞争者,也不会取代它。NIP-44 就是 NIP-17 两层加密所使用的那套加密方案。它们是同一件事的两个部分。

结论

相比 NIP-04,NIP-17 是一次实打实的改进,你也应该在用它。但要清楚你拿到的是什么。你的字句是加密的,中继也判断不出一条消息是谁发的。它仍然看得见这条消息是给哪个账号的,而同时盯着两头的人,光凭时间就能推出不少东西。把它当成私人信件,而不是一条查不到源头的暗线。

搬过去主要就是挑对客户端,再发布一份很小的列表。支持是真的存在,但参差不齐,而 iPhone 上用得最多的客户端之一 Damus 到现在还完全没有,所以确认对话另一头用的是什么,不是一个可选步骤。

行动项目:

  1. ✅ 用一个支持 NIP-17 的客户端(Amethyst、0xchat、Coracle、Snort)
  2. ✅ 发布你的私信中继列表(kind 10050)。没有它,什么都收不到
  3. ✅ 和一位联系人来回各发一条测试消息,确认投递没问题
  4. ✅ 谈任何敏感的事之前,先弄清楚对方用的是哪个客户端

记住:隐私靠的是日复一日的习惯,没有哪个产品能替你办到。NIP-17 把工具交到你手上,用得好不好还得看你自己。


测试你的 NIP-17 知识

准备好检查你对安全消息的理解了吗?

NIP-17 私密私信测验

NIP-17 的用途

问题 1 / 5

0/5 已回答

NIP-17 是什么?
关键

最后更新:2026年9月2日

有问题?在 Nostr 上加入讨论或在此文档仓库中提出问题。


继续阅读

改进此页面 发现错别字或不清楚的地方?在 GitHub 上编辑此指南。
在 Nostr 上关注我们