关于 crypto-protocol-diagram
这是一个从源代码或规范提取加密协议流程并生成 Mermaid 与 ASCII 时序图的技能,面向协议分析和安全审查,重点呈现消息语义与加密步骤,而非代码结构。
主要功能
- 01读取协议代码与规范
- 02识别参与方和消息流程
- 03标注加密操作
- 04呈现协议阶段与中止路径
- 05生成 Mermaid 和 ASCII 图
适用场景
- 01从源代码可视化握手流程
- 02绘制 RFC 或形式化模型
- 03对照实现与协议规范
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trailofbits/ skills --skill crypto-protocol-diagram安装后在 Claude Code 中输入/crypto-protocol-diagram确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlassets/trail-of-bits-mark.svgexamples/simple-handshake/expected-output.mdprotocol.pyexamples/simple-proverif/expected-output.mdmodel.pvreferences/ascii-sequence-diagram.mdmermaid-sequence-syntax.mdprotocol-patterns.mdspec-parsing-patterns.md详细介绍
加密协议图
生成 Mermaid sequenceDiagram(写入文件)和 ASCII 时序图(内联打印),输入可以是:
- 实现加密协议的源代码,或
- 规范——RFC、学术论文、伪代码、非正式说明、ProVerif(
.pv)或 Tamarin(.spthy)模型。
使用的工具: Read、Write、Grep、Glob、Bash、WebFetch(用于 URL 规范)。
与可视化代码结构的 diagramming-code 技能不同,此技能提取的是协议语义:谁向谁发送什么、每个步骤会发生哪些加密转换,以及协议包含哪些阶段。
如需绘制调用图、类层次结构或模块依赖关系图,请改用 diagramming-code 技能。
适用场景
- 用户要求绘制、可视化或提取加密协议
- 输入是实现握手、密钥交换或多方协议的源代码
- 输入是 RFC、学术论文、伪代码或形式化模型(ProVerif/Tamarin)
- 用户指定了某个协议(TLS、Noise、Signal、X3DH、FROST)
不适用场景
- 用户需要调用图、类层次结构或模块依赖关系图——请改用
diagramming-code - 用户需要对协议进行形式化验证——请使用
mermaid-to-proverif(生成图之后) - 输入不包含加密协议语义(没有参与方,也没有消息交换)
应避免的错误理由
| 理由 | 错误原因 | 必须采取的行动 |
|---|---|---|
| “协议很简单,我可以凭记忆绘图” | 凭记忆绘制的图会遗漏步骤并反转箭头 | 系统地阅读源代码或规范 |
| “既然有代码,我就跳过规范流程” | 代码可能与规范不一致——两种流程能发现不同的错误 | 两者都存在时,先执行规范工作流,再标注代码中的差异 |
| “加密注释只是可有可无的装饰” | 没有加密注释,图就只展示消息流,对安全审查毫无用处 | 为每项加密操作添加注释 |
“中止路径很明显,不需要 alt 块” | 隐式处理中止会掩盖缺失的错误检查 | 使用 alt 块展示所有中止/错误路径 |
| “我不需要先查看示例” | 示例定义了预期输出质量标准 | 处理不熟悉的输入前,先研究相关示例 |
| “ProVerif/Tamarin 模型是代码,不是规范” | 形式化模型就是规范——它们描述预期行为,而非实现 | 对 .pv 和 .spthy 文件使用规范工作流(S1–S5) |
工作流
Protocol Diagram Progress:
- [ ] Step 0: Determine input type (code / spec / both)
- [ ] Step 1 (code) or S1–S5 (spec): Extract protocol structure
- [ ] Step 6: Generate sequenceDiagram
- [ ] Step 7: Verify and deliver
步骤 0:确定输入类型
开始前,先对输入进行分类:
| 特征 | 输入类型 |
|---|---|
源文件扩展名(.py、.rs、.go、.ts、.js、.cpp、.c) | 代码 |
| 函数/类定义、导入语句 | 代码 |
RFC 风格的章节标题(§、Section X.Y、MUST/SHALL 等关键词) | 规范 |
Algorithm/Protocol/Figure 标签、数学符号 | 规范 |
包含 process、let、in/out 的 ProVerif 文件(.pv) | 规范 |
包含 rule、--[...]-> 的 Tamarin 文件(.spthy) | 规范 |
| 描述协议的普通文本或编号步骤 | 规范 |
| 同时有源文件和规范文档 | 两者(使用 ⚠️ 标注差异) |
- 仅代码 → 跳转到下方的步骤 1
- 仅规范 → 跳转到下方的规范工作流(S1–S5)
- 两者都有 → 先执行规范工作流,然后使用代码阅读步骤对照规范图验证实现,并使用
⚠️标注任何差异 - 不明确 → 询问用户:“这是源代码文件、规范文档,还是两者都有?”
步骤 1:定位协议入口
使用 Grep 搜索能够揭示协议的函数名、类型名和注释:
# Find handshake, session, round, phase entry points
rg -l "handshake|session_init|round[_0-9]|setup|keygen|send_msg|recv_msg" {targetDir}
# Find crypto primitives in use
rg "sign|verify|encrypt|decrypt|dh|ecdh|kdf|hkdf|hmac|hash|commit|reveal|share" \
{targetDir} --type-add 'src:*.{py,rs,go,ts,js,cpp,c}' -t src -l
从最高层级的编排函数开始阅读——也就是调用握手阶段或主协议循环的函数。
步骤 2:识别参与方和角色
从以下内容中提取参与方名称:
- 结构体/类名称:
Client、Server、Initiator、Responder、Prover、Verifier、Dealer、Party、Coordinator - 承载角色状态的函数参数名称
- 声明协议角色的注释
- 用于设置双方或 N 方场景的测试夹具
将这些名称映射为 Mermaid participant 声明。使用简短易读的别名:
participant I as Initiator
participant R as Responder
步骤 3:追踪消息流
跟踪状态转换以及网络发送/接收操作。查找以下模式:
| 模式 | 含义 |
|---|---|
send(msg) / recv() | 直接消息交换 |
serialize + transmit | 发送结构化消息 |
| 将返回值传递给另一方的函数 | 逻辑消息(进程内) |
round1_output → round2_input | 基于轮次的 MPC 步骤 |
名为 ephemeral_key、ciphertext、mac、tag 的结构体字段 | 消息内容 |
对于进程内的协议实现(双方在同一进程中运行),如果函数调用边界在部署时对应网络边界,则将其视为逻辑消息发送。
步骤 4:标注密码学操作
在每个协议步骤中识别并标注:
| 操作 | 图表标注 |
|---|---|
| 密钥生成 | Note over A: keygen(params) → pk, sk |
| DH / ECDH | Note over A,B: DH(sk_A, pk_B) |
| KDF / HKDF | Note over A: HKDF(ikm, salt, info) |
| 签名 | Note over A: Sign(sk, msg) → σ |
| 验证 | Note over B: Verify(pk, msg, σ) |
| 加密 | Note over A: Enc(key, plaintext) → ct |
| 解密 | Note over B: Dec(key, ct) → plaintext |
| 承诺 | Note over A: Commit(value, rand) → C |
| 哈希 | Note over A: H(data) → digest |
| 秘密分享 | Note over D: Share(secret, t, n) → {s_i} |
| 门限合并 | Note over C: Combine({s_i}) → secret |
标注应简洁,使用数学简写,而非代码。
步骤 5:识别协议阶段
使用 rect 或 Note 块将消息步骤归入命名阶段:
常见阶段包括:
- 设置/密钥生成:参与方密钥创建、可信设置、参数生成
- 握手/初始化:临时密钥交换、随机数交换、版本协商
- 身份验证:身份证明、证书交换、签名验证
- 密钥派生:从共享秘密派生会话密钥
- 数据传输/主协议:加密的应用数据交换
- 结束/拆除:关闭会话、MAC 验证、中止处理
识别中止/错误路径,并使用 alt 块展示。
规范工作流(S1–S5)
当输入是规范文档而非源代码时,使用此路径。 完成 S1–S5 后,继续执行上述代码工作流中的步骤 6(生成 sequenceDiagram)和步骤 7(验证并交付)。
步骤 S1:读取规范
获取完整的规范文本:
- 提供了文件路径 → 使用 Read 工具读取
- 提供了 URL → 使用 WebFetch 获取
- 直接粘贴了内容 → 根据对话上下文直接处理
然后识别规范格式,并阅读 references/spec-parsing-patterns.md 以获取针对该格式的提取指导:
| 格式 | 特征 |
|---|---|
| RFC | RFC XXXX、MUST/SHALL/SHOULD、ABNF 语法、带章节编号的正文 |
| 学术论文/伪代码 | Algorithm X、Protocol X、Figure X、编号步骤、数学模式中的 ←/→ |
| 非正式文本 | 编号列表、“A sends B ...”、自然语言描述 |
ProVerif (.pv) | process、let、in(ch, x)、out(ch, msg)、!(复制) |
Tamarin (.spthy) | rule、--[ ]->、Fr(~x)、!Pk(A, pk)、In(m)、Out(m) |
如果规范引用了已知的命名协议(TLS、Noise、Signal、X3DH、Double Ratchet、FROST),也请阅读 references/protocol-patterns.md,将其规范流程用作骨架,并补充规范中的具体细节。
步骤 S2:提取参与方和角色
识别所有协议参与者。查找:
- 正文或伪代码中命名的角色:
Alice、Bob、Client、Server、Initiator、Responder、Prover、Verifier、Dealer、Party_i、Coordinator、Signer - 章节标题:"Parties"、"Roles"、"Participants"、"Setup"、"Notation"
- ProVerif:顶层的进程名称(
let ClientProc(...)、let ServerProc(...)) - Tamarin:规则名称和事实参数(例如
!Pk($A, pk)——$A是一个参与方)
将每个角色映射为 Mermaid participant 声明。使用简短 ID 和描述性别名(参见命名约定:
references/mermaid-sequence-syntax.md)。
步骤 S3:提取消息流
追踪每个参与方按什么顺序向谁发送消息。不同格式的提取模式:
RFC / 非正式说明:
- 箭头表示法:
A → B: msg、A -> B - 句式模式:"A sends B ..."、"B responds with ..."、"A transmits ..."、 "upon receiving X, B sends Y"
- 编号步骤:按顺序提取,并根据上下文推断发送方和接收方
伪代码:
- 带有显式
sender/receiver参数的函数签名 send(party, msg)/receive(party)调用- 在下一步中,作为另一方函数输入传递的返回值
ProVerif(.pv):
out(ch, msg)——在通道ch上发送in(ch, x)——在通道ch上接收,并将消息绑定到x- 匹配同一通道上的
out/in对,以确定消息流 !(重复)表示能够处理多个会话的角色
Tamarin(.spthy):
In(m)前提——接收消息mOut(m)结论——发送消息m- 规则名称和顺序揭示协议轮次
Fr(~x)——参与方生成的新鲜随机值--[ Label ]->事实——安全注解,而非消息
保留顺序和轮次结构。在最终图示中,使用 par 块将并发发送(广播)归为一组。
步骤 S4:提取加密操作
针对每个协议步骤,识别执行的加密操作及执行该操作的参与方:
| 规范记法 | 操作 | 图示注解 |
|---|---|---|
keygen()、Gen(1^λ) | 密钥生成 | Note over A: keygen() → pk, sk |
DH(a, B)、g^ab | DH / ECDH | Note over A,B: DH(sk_A, pk_B) |
KDF(ikm)、HKDF(...) | 密钥派生 | Note over A: HKDF(ikm, salt, info) → k |
Sign(sk, m)、σ ← Sign | 签名 | Note over A: Sign(sk, msg) → σ |
Verify(pk, m, σ) | 验证 | Note over B: Verify(pk, msg, σ) |
Enc(k, m)、{m}_k | 加密 | Note over A: Enc(k, plaintext) → ct |
Dec(k, c) | 解密 | Note over B: Dec(k, ct) → plaintext |
H(m)、hash(m) | 哈希 | Note over A: H(data) → digest |
Commit(v, r)、com | 承诺 | Note over A: Commit(value, rand) → C |
ProVerif senc(m, k) | 对称加密 | Note over A: Enc(k, m) → ct |
ProVerif pk(sk) | 公钥派生 | Note over A: pk = pk(sk) |
ProVerif sign(m, sk) | 签名 | Note over A: Sign(sk, m) → σ |
识别安全条件和中止路径:
- 正文:"if verification fails, abort"、"only if ..."、"reject if ..."
- 伪代码:
assert、require、if ... abort - ProVerif:
if m = expected then ... else 0 - Tamarin:相互矛盾的事实或限制引理
这些内容应在最终图示中用 alt 块表示。
步骤 S5:标记规范中的歧义
进入步骤 6 之前,检查是否存在遗漏:
- 消息顺序不明确:根据轮次结构或章节顺序推断;
添加注释
⚠️ ordering inferred from spec structure - 隐含参与方:如果某一方的角色虽有暗示但未命名,请为其指定一个 描述性名称,并注明这是推断
- 缺少步骤:如果规范省略了该协议的规范模式所要求的某个步骤,请添加注释:
⚠️ spec omits [step] — canonical protocol requires it - 加密方案未充分说明:如果规范仅写了“加密”,却未指定方案,请添加注释:
⚠️ encryption scheme not specified - ProVerif/Tamarin:私有信道(用
new c声明的c,或作为私有自由名称的c)表示带外信道 — 请注明
步骤 6:生成 sequenceDiagram
按照 references/mermaid-sequence-syntax.md 中的规则生成 Mermaid 语法。
完整性优先于简洁性。 展示每种不同的消息类型。省略重复的
循环迭代(改用 loop 块),但绝不要省略不同的协议步骤。
正确性优先于美观。 图表必须与代码的实际行为一致。如果代码与已知规范不符,请注明这种差异:
Note over A,B: ⚠️ spec requires MAC here — implementation omits it
步骤 7:验证并交付
交付之前:
- 每个已声明的参与方都实际发送或接收了至少一条消息
- 箭头方向正确(发送方 → 接收方)
- 加密操作位于正确的一方(执行计算的一方)
- 如果使用了协议阶段,阶段块之外不得出现箭头
-
alt块涵盖已知的中止/错误路径 - 图表渲染时没有语法错误(检查 references/mermaid-sequence-syntax.md 以了解常见问题)
- 如果发现与规范不符之处,已添加
⚠️注释
将图表写入文件。 选择一个根据协议名称生成的文件名,例如 noise-xx-handshake.md 或 x3dh-key-agreement.md。编写 Markdown 文件,结构如下:
# <Protocol Name> Sequence Diagram
\`\`\`mermaid
sequenceDiagram
...
\`\`\`
## Protocol Summary
- **Parties:** ...
- **Round complexity:** ...
- **Key primitives:** ...
- **Authentication:** ...
- **Forward secrecy:** ...
- **Notable:** [spec deviations or security observations, or "none"]
写入文件后,在回复中内联打印一份 ASCII 时序图,然后附上协议摘要。注明输出文件名,让用户知道在哪里可以找到 Mermaid 源文件。
遵循 references/ascii-sequence-diagram.md 中的所有绘图约定,包括内联输出格式。
决策树
── Input is a spec document (not code)?
│ └─ Step S1: identify format, read references/spec-parsing-patterns.md
│
── Input is source code (not a spec)?
│ └─ Step 1: grep for handshake/round/send/recv entry points
│
── Both spec and code provided?
│ └─ Run Spec Workflow (S1–S5) first to build canonical diagram,
│ then read code and annotate divergences with ⚠️
│
── Spec is a known protocol (TLS, Noise, Signal, X3DH, FROST)?
│ └─ Read references/protocol-patterns.md and use canonical flow as skeleton
│
── Spec is ProVerif (.pv) or Tamarin (.spthy)?
│ └─ Read references/spec-parsing-patterns.md → Formal Models section
│
── Spec message ordering is ambiguous?
│ └─ Infer from round/section structure, annotate with ⚠️
│
── Can't identify parties from spec?
│ └─ Check "Parties"/"Notation" sections; for ProVerif read process names;
│ for Tamarin read rule names and fact arguments
│
── Don't know which code files implement the protocol?
│ └─ Step 1: grep for handshake/round/send/recv entry points
│
── Can't identify parties from struct names?
│ └─ Read test files — test setup reveals roles
│
── Protocol runs in-process (no network calls)?
│ └─ Treat function argument passing at role boundaries as messages
│
── MPC / threshold protocol with N parties?
│ └─ Read references/protocol-patterns.md → MPC section
│
── Mermaid syntax error?
│ └─ Read references/mermaid-sequence-syntax.md → Common Pitfalls
│
└─ ASCII drawing conventions?
└─ Read references/ascii-sequence-diagram.md
示例
代码路径 — examples/simple-handshake/:
protocol.py— 双方认证密钥交换(X25519 DH + Ed25519 签名 + HKDF + ChaCha20-Poly1305)expected-output.md— 该协议对应的完整 ASCII 图和 Mermaid 文件, 也是该技能应生成的内容
规范路径(ProVerif) — examples/simple-proverif/:
model.pv— 在 ProVerif 中建模的 HMAC 挑战-响应认证expected-output.md— 逐步提取说明(参与方、 消息流、加密操作),以及该技能应生成的准确 ASCII 图和 Mermaid 文件
处理不熟悉的输入之前,请先研究相关示例。
配套文档
- references/spec-parsing-patterns.md — RFC、学术论文/伪代码、非正式文本、ProVerif 和 Tamarin 输入格式的提取规则;在步骤 S1 中阅读
- references/mermaid-sequence-syntax.md — 参与者语法、箭头类型、激活、分组块、转义规则 和常见的渲染问题
- references/protocol-patterns.md — TLS 1.3、Noise、X3DH、Double Ratchet、Shamir 秘密共享、承诺-揭示和通用 MPC 轮次的规范消息流;与规范对照实现时可作参考
- references/ascii-sequence-diagram.md — ASCII 图表的列布局、箭头约定、自循环、阶段标签和行内 输出格式