news 2026/10/31 21:21:37

零知识证明从原理到实践:Sigma协议、zk-SNARK选型与踩坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零知识证明从原理到实践:Sigma协议、zk-SNARK选型与踩坑

零知识证明这个词第一次砸到我面前,是在一次需求评审上:业务方要验证用户“符合某个条件”,但用户死活不愿意把原始数据交出来。当时会议室里有人提了加密,有人提了脱敏,最后落到一个更根本的问题上——能不能只让对方相信“结论成立”,而不暴露“结论为什么成立”。这就是零知识证明要解决的事。它不是一个具体的加密算法,而是一类协议的设计思想:证明者向验证者证明自己知道某个秘密,或者某个命题为真,但整个过程中除了“命题为真”这个结论,验证者拿不到任何额外信息。它适合谁?适合那些手里有敏感数据、又必须向外界自证清白的人;也适合做隐私身份、链下计算验证、数据协作的开发者。下面我按自己实际做项目的顺序,从原理拆到代码,再聊选型和踩过的坑。

1. 先把“零知识”拆成三件事:证明、验证、不泄露

1.1 一个环形洞穴的思想实验

我习惯用环形洞穴来解释零知识证明,因为它把“交互”和“随机挑战”这两个关键点都装进去了。想象一个环形的洞穴,入口只有一个,洞穴深处有一扇门,门需要一句咒语才能打开。证明者说自己知道咒语,但不想把咒语告诉验证者。怎么办?让证明者先走进洞穴,随机选择从左通道或右通道走到门边;验证者在洞口外,看不到证明者选了哪条路,然后随机喊“从左出来”或“从右出来”。如果证明者真知道咒语,他总能打开门,从被喊的那一侧出来;如果他不知道,每轮只有一半概率蒙对。重复二十轮,蒙对的概率就是百万分之一。

这个实验里,验证者得到的全部信息是“每一轮证明者都从指定侧出来了”,他并不知道证明者一开始走的是哪边,也不知道咒语是什么。零知识证明的“零知识”就体现在这里:验证者被说服了,但没有拿到任何可用于复现或泄露秘密的信息。生活里类似的场景很多,比如你证明自己会开车,不需要把驾驶技巧的全部细节讲出来,上车跑一圈就行;但零知识证明更严格,它要求连“你具体怎么开”的过程都不留痕迹。

1.2 完备性、可靠性、零知识性到底在说什么

任何零知识证明协议,至少要满足三个性质,我在评审方案时也是按这三条逐项问。第一是完备性:如果命题是真的,证明者老老实实按协议走,验证者必须接受。这条最基础,相当于“真话一定能说通”。第二是可靠性:如果命题是假的,证明者不管怎么作弊,验证者接受的概率必须低到可以忽略。注意,这里的“低”不是“零”,而是可忽略,比如 2 的负 128 次方。第三是零知识性:验证者从交互记录里学不到除命题为真之外的任何东西。形式上,存在一个模拟器,它不需要知道秘密,也能生成与真实交互不可区分的记录。

很多方案还会加一条知识可靠性:证明者不仅能让验证者相信“存在某个解”,而且证明者自己确实“知道”那个解。这条在简洁非交互证明里经常被强调,因为有些协议只能证明“命题为真”,不能证明“证明者掌握 witness”。我在做身份凭证类需求时特别看重这条,否则可能出现“证明是别人代做的,但凭证被转手”的问题。

1.3 它和普通加密、签名的边界在哪里

刚接触的人容易把零知识证明和加密混在一起。加密解决的是“内容别被看见”,签名解决的是“内容没被篡改、来源可确认”,零知识证明解决的是“我让你相信一个结论,但不告诉你支撑结论的数据”。举个例子:加密像把信锁进保险箱,签名像在信封上盖火漆印,零知识证明像你站在门口告诉保安“我有进入权限”,保安信了,但你的门禁卡号、权限等级、有效期他都没看到。

这个边界很重要,因为零知识证明不是万能药。它不能替代加密,因为证明过程本身可能泄露元信息;它也不能替代访问控制,因为验证者信的是数学关系,不是你的身份系统。实际项目里,零知识证明通常和承诺、签名、哈希一起用:先用承诺把数据锁住,再用证明说明承诺里的数据满足某个条件,最后用签名绑定证明者的身份。单独上一个零知识证明库,往往解决不了完整的业务问题。

2. 从交互式协议到非交互证明:核心机制怎么跑起来

2.1 承诺、挑战、响应:Sigma协议的三拍节奏

最经典的一类零知识证明叫 Sigma 协议,结构非常固定,就三拍:承诺、挑战、响应。以“证明自己知道离散对数”为例,公开参数是一个循环群、生成元和公开值 y,证明者知道 x,使得 y 等于生成元的 x 次方。第一拍,证明者随机选一个 r,计算承诺 t,把 t 发给验证者;第二拍,验证者随机选一个挑战 c,发回去;第三拍,证明者计算响应 s,把 s 发回去。验证者最后检查一个等式,等式成立就接受。

这三拍的精髓在于“顺序不能乱”。证明者先承诺,相当于把答案锁进盒子再把盒子交出去;验证者后给挑战,相当于随机抽题;证明者最后开盒,相当于按题作答。如果证明者先知道题再锁盒,他就可以针对题目编一个能过的答案,协议就废了。我见过有人为了省一次网络往返,把承诺和响应合并发送,结果整个协议的安全性直接归零,这个后面会细说。

2.2 为什么必须“先承诺后挑战”

先承诺后挑战,本质上是让证明者没有机会根据挑战来调整承诺。假设顺序反过来:验证者先给挑战 c,证明者再给承诺 t 和响应 s。证明者完全可以随便选一个 s,然后反推出一个 t,让等式成立,而他根本不需要知道秘密。这在数学上叫“模拟”,但模拟出来的记录和真实记录不可区分,验证者就无法分辨证明者是不是在作弊。

我在代码 review 时有个习惯:看到零知识证明的实现,先看随机数生成和挑战生成的位置。如果挑战是在承诺之前生成的,或者承诺和响应用了同一个随机数,基本可以直接打回。这个顺序不是形式主义,它是整个安全性证明的支点。你可以把它理解成考试:先发卷子再答题,和先知道答案再出卷子,难度完全不是一回事。

2.3 哈希挑战变换:把对话压成一条证明

交互式协议有个麻烦:验证者必须在线,而且每轮都要真随机。实际系统里,我们更希望证明者生成一条证明,贴到公告板上,任何人随时可验证。这就需要把“验证者的随机挑战”替换成“哈希函数的输出”。做法是把公开参数、承诺、命题上下文拼成一个字节串,做一次哈希,把哈希结果当作挑战。这样挑战看起来是随机的,但实际上由承诺和上下文唯一决定,证明者没法预先操纵。

这个变换叫哈希挑战变换,也有人叫非交互化变换。它把多轮交互压成一条证明,验证者只需要重算哈希、验一个等式。但这里有个坑:哈希输入必须把所有相关上下文都绑进去,包括命题、公开值、协议版本、甚至链 ID 或域名。少绑一个字段,就可能出现跨场景重放。比如同一个证明在 A 业务里有效,被搬到 B 业务里也能过,因为挑战没绑定业务标识。我在实际项目里会要求把“证明用途”写进哈希输入,这相当于给证明加了一个不可伪造的标签。

2.4 模拟器视角:零知识性不是“感觉安全”

零知识性的严格定义,是存在一个多项式时间的模拟器,它不需要知道 witness,就能生成一个与真实交互不可区分的记录。这句话听起来绕,但它的实际意义是:验证者即使把交互记录拿回去反复分析,也找不到任何关于 witness 的信息,因为模拟器在没有 witness 的情况下也能造出一样的记录。换句话说,记录本身不携带 witness 信息。

这个视角帮我排除过很多“伪零知识”方案。有些方案只是把敏感字段哈希了一下,就宣称零知识,但验证者可以通过穷举或关联分析还原出原始值,这就不满足零知识性。判断方法很简单:问一句“如果我是验证者,我能不能用这条证明去推断 witness 的任何一位?”如果答案是能,那它就不是零知识证明,只是某种承诺或脱敏。真正的零知识证明,安全性不依赖于验证者“不去分析”,而依赖于数学上的不可区分。

3. 技术路线选型:不是所有场景都适合上zk-SNARK

3.1 四类主流方案的能力边界

市面上的零知识证明方案很多,名字也花哨,但按能力边界大致可以分成四类。我在选型时不看宣传语,只看四个指标:证明大小、验证成本、是否需要可信设置、开发难度。下面这张表是我内部评审时常用的对照,具体参数会随实现变化,但量级关系基本稳定。

方案类别证明大小验证成本可信设置开发难度典型适用场景
基于配对与多项式承诺的简洁证明几百字节,常数级很低,毫秒级通常需要高,需要电路设计链上验证、凭证系统
透明设置的哈希型证明几十 KB 到几百 KB中等,随规模增长不需要中高抗信任假设、长期可验证
内积论证类方案几百字节到几 KB对数或线性不需要中范围证明、聚合证明
多方计算生成证明较小低依赖参与方高特定隐私计算场景

这张表里没有“最好”的方案,只有“最合适”的方案。链上验证对证明大小和验证成本极度敏感,哪怕证明生成慢一点,也愿意选常数大小方案;离线审计场景更看重长期可验证性,不愿意引入一次性可信设置,那就倾向透明设置;移动端或嵌入式设备则要反过来,证明生成不能太重,宁可证明大一点。

3.2 可信设置与非可信设置的取舍

可信设置是很多人心里的疙瘩。简单说,这类方案需要一次性生成公共参数,生成过程中会产生一些“有毒废料”,如果这些废料没被销毁,持有者理论上可以伪造证明。实际项目里通常用多方计算仪式来分散风险,只要有一个参与方诚实地销毁了自己的份额,参数就是安全的。但“信任”这件事很难向普通用户解释,所以我在面向公众的场景里会非常谨慎地使用“需要可信设置”这个说法。

透明设置方案不需要这种一次性仪式,它只依赖哈希函数,公共参数可以由任何人用公开随机数生成。代价是证明更大、验证更贵。我的经验是:如果验证方是链上合约,且证明调用频繁,可信设置带来的性能优势很难被替代;如果验证方是审计机构或监管方,且系统生命周期很长,透明设置的“无信任假设”更省心。选型时不要只算技术账,还要算沟通账。

3.3 算术化:把业务逻辑翻译成电路

零知识证明本身只认数学关系,不认业务语言。要把“用户余额大于零”“身份证有效期在范围内”“模型输出等于某值”变成证明,中间必须做算术化。最常见的形式是 R1CS,每个约束长这样:A 向量点乘 witness,乘以 B 向量点乘 witness,等于 C 向量点乘 witness。加减乘都能表示,比较和范围检查则要拆成比特。

举个例子,证明 x 在 0 到 100 之间。你不能直接写一个“x < 100”的约束,因为电路里没有原生的比较指令。常见做法是把 x 拆成若干比特,约束每个比特只能是 0 或 1,即 b 乘以 b 减 1 等于 0;再用二进制权重把比特加回 x;最后约束 x 小于 100。这个过程中,比特位数、边界条件、符号处理都容易出错。我见过一个范围证明漏了最高位约束,导致用户可以声称一个负数在范围内,链上验证还通过了,因为电路根本没检查符号。

3.4 选型清单:按证明规模、验证成本、开发周期排序

我自己的选型顺序是这样的:先问证明在哪验证。链上验证优先看证明大小和验证 gas;服务端验证可以放宽到几十 KB;移动端验证则要避免复杂配对运算。再问能不能接受可信设置。面向公众、生命周期长的系统,优先透明设置;内部系统、性能敏感的场景,可以接受多方仪式。最后问团队熟悉什么。电路开发不是普通业务开发,学习曲线很陡,选一个团队能维护的方案,比选一个纸面参数最漂亮的方案更重要。

还有一条经验:不要一上来就上通用电路方案。很多需求用 Sigma 协议、范围证明、哈希树成员证明就能解决,代码量小、审计成本低、出错面窄。通用电路方案适合逻辑复杂、约束多的场景,但开发周期可能是前者的五到十倍。先做威胁模型,再看能不能用简单协议覆盖,覆盖不了再上电路。

4. 手写一个可验证的零知识证明Demo

4.1 环境与参数准备

下面这段代码只依赖 Python 标准库,目的是把协议跑通,不是生产实现。教学参数我故意选得很小:模数 23,子群阶 11,生成元 4。小参数方便手算和打印,但绝对不安全,生产环境必须用大素数群或椭圆曲线群,并且使用经过审计的库。我之所以坚持手写一遍,是因为很多坑只有自己实现过才会真正记住,比如随机数复用、挑战空间、哈希绑定。

先准备参数和基础函数。secrets模块用于生成密码学安全的随机数,不要用random。pow的三参数形式做模幂,Python 自带的大整数运算足够演示。

import hashlib import secrets # 教学参数,禁止用于生产 P = 23 # 模数 Q = 11 # 子群阶 G = 4 # 生成元 def keygen(): x = secrets.randbelow(Q - 1) + 1 y = pow(G, x, P) return x, y

这段代码里,私钥 x 落在 1 到 Q-1 之间,公钥 y 是生成元的 x 次方。这里有一个细节:x 不能取 0,否则公钥恒为 1,证明就失去意义。实际系统里还要检查公钥是否在正确的子群内,防止小群攻击。教学代码省略了这些检查,但你在生产实现里必须补上。

4.2 交互式离散对数证明

交互式版本分三步。证明者先选随机 r,算承诺 t;验证者给挑战 c;证明者算响应 s,验证者验等式。代码很短,但每一步都有讲究。

def commit(): r = secrets.randbelow(Q) t = pow(G, r, P) return r, t def respond(r, x, c): return (r + c * x) % Q def verify(y, t, c, s): left = pow(G, s, P) right = (t * pow(y, c, P)) % P return left == right

验证等式的原理是:左边是生成元的 s 次方,右边是承诺乘以公钥的 c 次方。把 s 展开,右边等于生成元的 r 加 c 乘 x 次方,正好等于左边。这个等式成立,说明证明者知道 x,因为只有知道 x 的人才能算出正确的 s。但验证者看到的只有 t、c、s,他不知道 r,也不知道 x,所以没有泄露秘密。

这里最容易犯的错是 r 复用。如果同一个 r 用在两个不同的挑战上,攻击者拿两组响应一减,就能解出 x。我在 code review 里看到过有人把 r 存在全局变量里“省性能”,这是典型的省小钱赔大钱。每次证明都必须重新生成 r,而且要用密码学安全的随机源。

4.3 非交互版本与挑战绑定

把交互式协议变成非交互,核心是把验证者的随机挑战换成哈希输出。哈希输入要包含公开参数、公钥、承诺和命题上下文。我通常还会加一个域分隔字符串,防止不同协议之间的哈希碰撞。

def challenge(y, t, statement): data = f"zk-demo-v1:{P}:{G}:{y}:{t}:{statement}".encode() return int(hashlib.sha256(data).hexdigest(), 16) % Q def nizk_prove(x, y, statement): r = secrets.randbelow(Q) t = pow(G, r, P) c = challenge(y, t, statement) s = (r + c * x) % Q return t, s def nizk_verify(y, statement, t, s): c = challenge(y, t, statement) return pow(G, s, P) == (t * pow(y, c, P)) % P

这段代码里,statement是证明用途,比如“证明我是某个凭证的持有者”。把它绑进哈希,意味着同一个证明换一个用途就失效,攻击者不能把 A 场景的证明搬到 B 场景。这个细节在实际系统里非常关键,我见过因为没绑上下文导致证明被跨系统重放的案例,修复成本很高。

还有一个坑:挑战取模后的空间。教学参数 Q 只有 11,挑战空间太小,伪造成功率是十一分之一,多试几次就能蒙混过关。生产环境挑战至少 128 位,通常 256 位。不要因为哈希输出很长就直接用,取模之后的空间才是实际安全边界。

4.4 哈希树成员证明:隐藏“我是谁”

很多场景不需要通用电路,只需要证明“我在这棵树的某个叶子里”,但不想暴露具体是哪个叶子。哈希树成员证明就能做这件事。先把每个叶子做哈希,再两两合并成父节点,一直到根。证明者给出叶子、路径上的兄弟节点和方向,验证者从叶子一路算到根,看是否等于公开的根。

def h(data: bytes) -> bytes: return hashlib.sha256(data).digest() def build_tree(leaves): level = [h(x) for x in leaves] tree = [level] while len(level) > 1: nxt = [] for i in range(0, len(level), 2): left = level[i] right = level[i + 1] if i + 1 < len(level) else left nxt.append(h(left + right)) tree.append(nxt) level = nxt return tree def merkle_path(tree, index): path = [] for level in tree[:-1]: sibling = index ^ 1 if sibling < len(level): direction = "left" if sibling < index else "right" path.append((direction, level[sibling])) else: path.append(("self", level[index])) index //= 2 return path def verify_path(root, leaf, path): cur = h(leaf) for direction, node in path: if direction == "left": cur = h(node + cur) elif direction == "right": cur = h(cur + node) else: cur = h(cur + cur) return cur == root

这段代码能证明成员关系,但它本身不是零知识的,因为路径会泄露叶子在树中的位置,叶子内容也可能被猜到。要变成零知识,通常要把叶子换成承诺,或者用零知识电路重新包装成员证明。我在实际项目里会先问一句:验证者到底需要知道“某个人在名单里”,还是需要知道“名单里某个人满足条件”?前者用承诺加路径就够,后者往往要上电路。

4.5 跑测试与性能观察

测试时我关注三件事:正确性、伪造成功率、耗时。正确性用固定向量跑通;伪造成功率用随机响应去撞验证等式;耗时用time.perf_counter粗略观察。教学参数下,一次证明和验证都在微秒到毫秒级,看不出真实性能。生产环境里,瓶颈通常在模幂运算和电路规模,而不是哈希。

观察项教学参数表现生产环境关注点
证明生成耗时微秒级电路规模、模幂次数、并行度
验证耗时微秒级配对运算次数、哈希次数
证明大小几十字节常数大小还是随规模增长
伪造成功率约 1/Q挑战空间至少 128 位

我建议你在本地至少跑三组:正常证明、篡改承诺、篡改响应。正常证明必须过;篡改承诺或响应必须挂。如果篡改后还能过,说明验证等式写错了,或者挑战没绑进承诺。这个自测习惯能提前发现大部分低级错误。

5. 踩坑实录:那些让证明“看起来能过”的陷阱

5.1 随机数复用是头号杀手

随机数复用是零知识证明里最致命的错误,没有之一。还是用离散对数证明举例:同一个 r 生成承诺 t,面对两个不同挑战 c1 和 c2,得到两个响应 s1 和 s2。攻击者把两个响应相减,得到 s1 减 s2 等于 c1 减 c2 乘以 x,直接解出私钥 x。整个过程不需要破解哈希,也不需要攻破群,只要拿到两条用同一随机数的证明就行。

我在项目里见过两种复用:一种是开发者图省事,把 r 缓存在对象里,多次证明复用;另一种是随机数生成器 seeded 不当,不同进程生成相同序列。修复方法很直接:每次证明都调用密码学安全的随机源,不要缓存,不要用时间戳做种子。还有一条:如果协议需要多轮,每轮的随机数必须独立,不能从上一轮推导。

5.2 挑战空间太小等于没挑战

挑战空间决定了伪造成功率。如果挑战只有 8 位,伪造者随机猜一个响应,有 256 分之一概率通过;重复几百次就能蒙中。有人觉得“我可以多验几轮”,但多轮验证会带来交互成本和状态管理问题,不如直接把挑战空间做大。生产环境里,挑战至少 128 位,通常 256 位,取模后的空间也要足够大。

这里还有一个隐蔽问题:哈希输出取模后的分布。如果模数不是 2 的幂,取模会带来微小偏置,严格来说需要用拒绝采样或大整数映射。教学代码为了简洁直接取模,生产实现要用标准做法。安全参数不是拍脑袋定的,128 位是底线,256 位更稳妥。

5.3 电路约束漏写:证明对了,业务错了

通用电路方案最怕约束漏写。验证者看到证明通过了,以为业务逻辑也对了,其实电路只约束了一部分。比如证明“我知道一个数 x,使得公开值等于生成元的 x 次方”,但电路没约束 x 的范围,攻击者可以拿 x 加上子群阶来构造另一个 witness,证明照样过,但业务语义变了。再比如范围证明漏了符号位,负数也能通过“大于零”的检查。

我现在的做法是:电路写完后,先做一轮“反例测试”。故意构造边界值、负数、超大数、零点,看证明能不能过。能过就说明约束有漏洞。然后再做一轮“约束覆盖检查”,把业务规则逐条映射到约束,确保每条规则至少有一个约束对应。电路审计比普通代码审计更贵,因为错误往往不是崩溃,而是“静默通过”。

5.4 常见问题速查表

下面这张表是我自己整理的排查顺序,遇到证明异常时从前往后查,基本能覆盖八成问题。

现象可能原因排查方法修复建议
真证明通不过挑战没绑全上下文打印哈希输入逐字段比对把命题、公钥、承诺、版本号全绑进去
假证明也能过验证等式写错或挑战空间太小用随机响应撞验证检查等式,挑战至少 128 位
同一证明可跨场景重放哈希没绑业务标识换一个 statement 重验加入域分隔和用途字段
证明生成偶尔失败随机数越界或模运算错误检查 r 的范围和取模用密码学安全随机源,范围对齐子群阶
验证耗时波动大群运算未预计算压测不同输入规模预计算生成元幂表,或换更高效曲线

这张表不是万能的,但它能帮你快速定位“是协议问题还是实现问题”。我的经验是:先怀疑实现,再怀疑协议。大部分线上问题不是数学被攻破,而是随机数、绑定、范围这些工程细节出了错。

6. 应用场景与影响范围:它到底能落到哪里

6.1 身份与凭证:只回答“是/否”

零知识证明在身份场景里最自然的用法,是把“出示全部信息”变成“回答一个布尔问题”。比如验证者只想知道“这个人是否年满十八岁”,证明者不需要给出出生日期,只需要给出一个证明,说明自己持有的凭证里的出生日期满足某个范围。再比如会员资格、权限等级、白名单成员,都可以做成“只回答是/否”的凭证。

这类系统的关键不是证明本身,而是凭证的签发和撤销。凭证需要被签名,证明里要绑定签发者公钥和撤销状态,否则攻击者可以拿过期凭证生成证明。我在设计这类方案时,会把“凭证有效期”和“撤销根”作为公开输入绑进电路,验证者每次验证时检查最新状态。这样证明仍然零知识,但业务上不会出现过期凭证蒙混过关。

6.2 扩容与批量验证:把计算搬到链下

另一大类场景是扩容。思路很直接:把大量计算搬到链下,生成一个证明,链上只验证这个证明。验证成本从“随交易数量线性增长”变成“常数级”,这就是很多人说的批量验证。某类公链项目会用这种方式把成百上千笔状态转换压成一个证明,链上合约只验一次。

但这里有个现实问题:证明生成很贵。电路越大,生成时间越长,内存占用越高。我见过一个团队把几百兆的电路直接丢到普通服务器上跑,结果内存爆了。实际项目里要做电路拆分、并行生成、证明聚合,还要考虑证明生成失败时的回退策略。扩容不是“上个零知识证明就完了”,它是一整套工程体系。

6.3 数据协作与模型推理

数据协作场景里,零知识证明可以用来证明“我的数据满足某个统计性质”,而不交出原始数据。比如证明一组数据的平均值在某个区间,或者证明某个模型在私有数据集上的输出等于公开结果。这类应用听起来很美好,但边界要划清楚:零知识证明不加密数据本身,它只保证证明过程不泄露 witness。如果数据在传输或存储环节没加密,证明再漂亮也没用。

模型推理场景还要注意“证明的是什么”。你可以证明“输出等于模型对输入的计算结果”,但很难证明“模型是某个公开模型”,因为模型权重本身可能也是私有的。实际做法通常是把模型哈希或承诺作为公开输入,证明者证明自己用的模型承诺匹配,再证明计算结果正确。这套组合拳的复杂度不低,适合对信任要求极高的场景,不适合普通业务。

6.4 边界:延迟、证明大小与开发成本

零知识证明不是免费的。证明生成延迟可能从几百毫秒到几分钟不等,证明大小从几百字节到几百 KB,电路开发周期可能是普通业务的数倍。我在评估一个需求是否值得上零知识证明时,会问三个问题:验证方是否真的不需要原始数据?信任缺失是否严重到必须用数学证明?业务能否接受证明生成的延迟和成本?

如果三个答案都是“是”,再考虑技术选型。如果只是“不想让日志里出现明文”,那加密和脱敏更合适;如果只是“想让对方相信我们没作弊”,那审计和签名可能更便宜。零知识证明的价值在于“在不泄露秘密的前提下建立信任”,它的成本也在这里。想清楚这一点,就不会为了用而用。

我个人在实际项目里的体会是:先做威胁模型,再选协议,最后才写电路。威胁模型里把“证明者可能作弊”“验证者可能重放”“凭证可能过期”这些场景列清楚,比急着调库更重要。很多坑不是数学问题,而是边界没想明白。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/31 21:18:15

Claude Code架构解析:Routine脚本化与多Agent编排原理

1. 项目概述&#xff1a;这不是一个“插件安装教程”&#xff0c;而是一次对 Claude Code 架构本质的手术式解剖你点开 VS Code&#xff0c;装上那个叫 Claude Code 的插件&#xff0c;敲下CtrlShiftP&#xff0c;输入 “Claude: Start Chat”&#xff0c;然后开始和一个看似聪…

作者头像 李华
网站建设 2026/10/31 21:16:40

JavaScript继承机制详解与最佳实践

1. 继承的概念与本质继承是面向对象编程中最基础也最重要的特性之一。简单来说&#xff0c;继承就是子类自动拥有父类的属性和方法的过程。就像现实世界中孩子会继承父母的基因特征一样&#xff0c;在编程中&#xff0c;子类会继承父类的字段、属性和方法。继承的核心价值在于代…

作者头像 李华
网站建设 2026/10/31 21:15:48

AI Agent故障排查:对话记录不够,可观测性来救场

1. 从一次线上事故说起&#xff1a;对话记录为什么不够用去年冬天&#xff0c;我负责的一个客服类 AI Agent 在凌晨两点突然开始给用户回复完全无关的内容。用户问退货政策&#xff0c;它回答天气&#xff1b;用户问订单状态&#xff0c;它开始背诵产品说明书。值班同事第一反应…

作者头像 李华
网站建设 2026/10/31 21:07:44

MQTT协议与Mosquitto代理实战指南

1. Mosquitto与MQTT协议初探2009年&#xff0c;当Roger Light首次发布Mosquitto时&#xff0c;可能没想到这个轻量级MQTT代理会成为物联网通信领域的基石工具。作为最早开源的MQTT实现之一&#xff0c;Mosquitto凭借其不足2MB的二进制体积和毫秒级的消息延迟&#xff0c;迅速在…

作者头像 李华
网站建设 2026/10/31 21:04:28

Agent长期记忆方案对比:六大主流框架的记忆机制与选型指南

1. 先聊清楚&#xff1a;Agent 的“记忆”到底难在哪如果你上手写过几个 Agent&#xff0c;一定会碰到这个场景&#xff1a;对话刚开始&#xff0c;Agent 表现得像个聪明的助手&#xff0c;上下文里塞了多少信息都能记住。但聊着聊着&#xff0c;它就开始“失忆”——用户五分钟…

作者头像 李华
网站建设 2026/10/31 20:59:07

如何正确理解与使用项目标题生成技术博文

我无法根据您提供的输入内容生成符合要求的博文。原因如下&#xff1a;输入中缺失关键结构化字段&#xff1a;按照规定&#xff0c;必须提供项目标题:、项目正文:、关键词:、摘要描述:四个明确字段&#xff0c;但当前输入仅包含一个长标题字符串和空置的“相关热搜词”“最新网…

作者头像 李华