TinyNTRU
源码
1 | |
1 | |
分析
简易版的 NTRU 密码体制。多项式在
-
采样稀疏多项式
(在 的最高次数下只有 项系数不为零。生成 时传入avoid_zero=True以使后续构造 时常数项一定为 ) -
构造私钥多项式
。 的这种特殊形式保证了 ,进而直接得到 。保密私钥 。 -
计算
,公开公钥 。 -
针对明文多项式(系数属于
)采样稀疏的扰动多项式 (只有 项非零系数),计算密文 。 -
解密时,计算:
根据
展开:由于
都是稀疏或小因子多项式,系数项的绝对值远小于 。进行中心化提升后模 带来的影响被抹平,此时的 在整数环上。最终计算 ,得到明文多项式。为什么要做中心化提升?在有限域上,当最终多项式的系数产生负数时会发生回绕(
)。根据模运算,相加后取模等于取模后相加。 ,导致算出来的系数等于真实系数加 1,解密产生错误。而中心化提升就是把大于 的系数看作负数,只要参数选取正确,最终得到的 没有能够达到 的系数项,负数依然是负数,不会发生回绕,解密也就准确无误。调用原代码,看一下最终多项式
的真实大小(单个明文多项式最多能编码的字节数为 22,即chunk_bytes减去 2 字节的长度前缀):1
[-8, 7, -2, 0, 1, 12, 0, 5, 14, 1, 3, 14, 3, 17, -2, 10, 7, 9, 6, -10, 0, 7, -4, 7, -1, 5, 2, 13, 5, -1, 7, 4, 10, 11, -3, 2, 3, 10, 6, 2, -8, -8, 7, -1, 3, -1, -5, 9, -4, 13, 0, 6, 9, 7, -5, 11, -6, 10, 8, 10, 0, 0, 15, 4, 11, 5, 1, 1, 13, 10, -4, 8, 6, -6, 11, 12, 4, 12, 4, 4, -4, 2, 10, 8, 13, 1, 1, 10, 8, -7, -5, 1, 10, 8, 14, -1, -5, 1, -3, 10, 6, -4, 3, 3, -8, 6, 2, 4, 0, 2, 6, -1, -5, 0, 5, 5, 6, 9, 16, 13, 6, -6, 3, 12, 9, 0, -6]可以看到系数远小于
。
本题中参数太小了,直接 LLL 做约简找最短向量就能还原出私钥
根据 NTRU 的公钥生成式
但它们都是 127 项的多项式。那么核心问题在于,如何用向量与矩阵的乘法完全等价代替两个多项式的循环乘法?
根据环的定义,多项式运算是在模
观察每一项,当系数为
发现多项式每乘以一个
把多项式记为
用行向量
最终得到格基:
接下来讲一下 LLL 算法生效的条件。由高斯启发式和斯特林公式得到一般格基中最短向量的估计值:
最短向量上界为:
当格基维度增加时,LLL 算法面临着 Unique-SVP 问题:其能寻找到的最短向量相比于理论估计值具有放大倍数的关系。对于随机格或高维密码学格,LLL 输出向量长度的实证模型为:
其中
本题中
由高斯启发式,
EXP
很神奇啊,
1 | |
cold_forge
源码
frost_telemetry.json
1 | |
sealed_release.json
1 | |
分析
只给了两份 JSON,没看出来是什么,问了 AI 知道是 Schnorr 门限签名的多人版,即 FROST 协议。先浅析一下单人版的 Schnorr 签名算法,感觉比 ECDSA 更优雅(
单人版 Schnorr 签名的前身是一个交互式的零知识身份认证协议,后来被 Fiat-Shamir 变换改写为新的非交互式数字签名,因此它的各项变量名和 ECDSA 一样,带有零知识证明的色彩。算法运行在阶为素数的椭圆曲线群上(本题中是 secp256k1),基点为
签名流程
签名者持有私钥
- 选取随机数。从
上随机选取一个标量 ,绝对保密。 - 计算承诺。计算
对应的椭圆曲线点 。 - 生成挑战。利用哈希函数绑定承诺,公钥与消息,计算标量
。 - 计算响应。计算最终的标量响应
。 - 输出签名。签名通常为元组
。
验签流程
验证者持有消息
- 重新计算挑战值
。 - 验证等式
是否成立。若成立则验签成功,反之则证明数据被篡改。
为什么叫做承诺-挑战-应答?为什么明明是一个人在签名,却需要所谓的挑战?在交互式系统中:
验签的本质是校验等式
那如果固定
但是在单机签名生成过程中没有网络时序。Fiat-Shamir 变换将服务端换为了哈希函数,并将完全随机的挑战
最终总结一下,承诺用于声明自己已经固定了某个随机数,挑战用于不可预测地激活验证规则,响应用来给知晓私钥者一个快捷的计算途径,同时证明能够计算出它的人持有私钥。
再说一下 FROST 门限签名,它与普通 Schnorr 生成的最终签名完全不可区分,但是私钥被拆成
FROST 通过分布式密钥生成技术将一个主私钥拆分后分发给参与者,它的巧妙之处在于使用了多项式插值法。一个
-
分布式密钥生成。每个参与者
得到私钥分片 ,全局私钥 隐式存在,无任何人知晓。公开全局聚合公钥
,以及每个参与者各自的公钥 。 -
部分承诺生成。为了抵御并行攻击,FROST 要求每个参与者必须一次性生成两对随机数与承诺。
生成
,计算 , ,将 发送给组织者。 -
聚合承诺生成。当有具体消息
需要签名时,组织者收集到 个节点的承诺,拼装为承诺列表 ,并为每个参与者计算一个结合系数 ,并计算全局聚合承诺 。组织者将 下放给参与集合中的所有节点。 -
全局挑战计算。每个参与者接收到
后在本地计算并验证 ,接着利用 Fiat-Shamir 变换计算全局挑战值 。 -
插值系数计算。参与者计算插值系数
,其中 为参与者集合。 -
部分应答生成。参与者计算部分应答
(其中 也被记为复合随机数 ),将 返回给组织者。 -
个体验证。协调者利用每个人的公钥验证谁提交了错误数据(
),以剔除恶意节点。 -
签名聚合。产出
,以 为签名。
验签逻辑和普通 Schnorr 完全等同,且外部验证者完全无法知道签名的参与者组成。
回到题目。参照前面的 FROST 签名协议,本题公开了 2-of-2 门限下对应参与者的插值系数
transcripts 中,每一笔都有承诺点
nonce_msb 字段给出了复合随机数
FROST 的第
随机数低 104 位丢失。记高位为
将
记
直接就是标准格基(平衡系数为
构建基向量