Skip to content

算法Algorithm

RSA-PSS 签名编码与严格验证

RSA-PSS · RSASSA-PSS · EMSA-PSS

用PSS盐、掩码与保留高位把消息编码成RSA输入,逐字段验证并区分模数字节长与编码消息长度。

形式陈述 ​

固定参数与两种长度 ​

RSA-PSS是把PSS消息编码和RSA函数组合成数字签名的方案。本页固定RFC8017(2016年11月,PKCS#1 v2.2)§8.1及§9.1,使用SHA-256、MGF1-SHA-256、盐长sLen=32字节。验证者从可信的算法政策获得这些参数,不靠签名输入自动猜测盐长或哈希。

设模数N有modBits位,定义

k=⌈modBits/8⌉,emBits=modBits−1,emLen=⌈emBits/8⌉.

签名字节数是k,编码消息EM的字节数是emLen。当modBits≡1(mod8)时两者差一。EM所代表整数最多有emBits位,所以严格小于N;这比“长度看起来能装下”更强。

RSA密钥采用不同素数p,q及ed≡1(modlcm(p−1,q−1))。PSS的EM不要求落在单位群,所需逆律在整个ZN成立:模p或q若为0,幂运算仍为0;若非零,Fermat指数周期给出med=m;两分量经CRT合起来得到原m。这一步补足从旧单位群RSA接口到所有编码整数的正确性条件。

编码的执行顺序 ​

令hLen=32、mHash=SHA256(M),要求emLen≥hLen+sLen+2。选择32字节盐salt,计算

H=SHA256(008‖mHash‖salt),DB=00emLen−sLen−hLen−2‖01‖salt.

MGF1把种子H扩展到emLen−hLen−1字节:依次计算SHA256(H‖I2OSP(i,4)),从i=0开始拼接并截取需要的长度。计数器固定为四字节大端数。令maskedDB=DB⊕MGF1(H),把它最左8emLen−emBits位清零,输出

EM=maskedDB‖H‖bc.

签名者把EM按大端转成m,计算s=mdmodN,最后输出恰好k字节大端S。这里的H是编码内部摘要,和消息摘要mHash有不同输入。

验证不能只比较末尾摘要 ​

先检查S恰为k字节、整数s<N;计算m=semodN,尝试将m编码成恰好emLen字节。装不下即拒绝。接着检查以下各项:

  1. EM长度满足本参数组,尾字节为bc
  2. maskedDB的最高保留位已经为零;这一步发生在任何清除操作之前
  3. 重新生成掩码并异或恢复DB,然后清除DB的同一组高位
  4. DB前面的PS恰为规定个数的零字节,后面分隔字节恰为01
  5. 取精确长度的salt,重新计算八个零字节、mHash、salt的SHA-256,与H比较

任一失败都返回无效签名。编码使用密码哈希的具体SHA-256算法,但编码正确性与计算不可伪造性是不同结论;PSS的安全分析还需要RSA反演及相应随机预言机模型。

直觉

盐让同一消息可以形成不同编码;掩码把盐所在的数据块与摘要H绑定,固定零前缀、分隔符和尾标则让验证者确认自己解析的是同一种结构。每一层都需要准确的长度和位置,不能从“RSA模幂相等”直接跳到“消息格式合法”。

最高位清零是为了保证EM代表整数小于N。验证时若先把收到的最高位清掉再检查,就会把不合法编码悄悄改成另一个合法候选;规范检查的任务是拒绝输入,而不是修复输入。

例子与边界

1024位与1025位模数 ​

在1024位教学模数下,k=128,emBits=1023,emLen=128。PS长128−32−32−2=62字节,DB长95字节,MGF1需要三次SHA-256并取前95字节。maskedDB首字节最高一位必须为零;最后是32字节H及1字节bc。

改用1025位教学模数后,k=129,emBits=1024,emLen=128。DB、H、盐长度不变,但此时没有需要清除的高位,签名却必须是129字节。验证者不能把129字节S直接当成129字节EM;RSA公开运算后的m还须通过128字节表示检查。

下载器的消息是ASCII Theoryroad offline PSS lesson,盐为依次递增的字节00到1f。这组输入在两种模数下恰好得到相同EM,因为其首字节本来就没有最高位;两把密钥的RSA签名不同。完整EM和S由下载输出逐字给出,这种偶合不意味着两套最高位合同可以合并。

把坏编码真的签出来 ​

单纯翻转S的一个位,通常只得到一个无法解释的RSA像,不能单独说明哪个编码检查救了验证者。更有区分力的实验是:解出合法DB,把01分隔符改为02,保留盐与H,重新掩码;再用公开教学私钥对这份坏EM执行RSA私钥运算。公开模幂会精确还原坏EM,但PSS验证仍因分隔符错误拒绝。

同样可以分别构造非零PS、错误尾字节和设置了保留位的EM。在设置高位的外层签名实验中还须先确认整数小于N;若已经越界,拒绝来自RSA输入范围,不应误记为PSS最高位门禁的功劳。下载器另在EM层翻转每一个位,直接核对编码验证,避免混淆两层责任。

盐长也是验证政策。32字节盐的签名不能按20字节盐合同接受。显式选择sLen=0是另一个参数组;空盐时不能在程序中使用会把整个DB取出的DB[-0:],应明确得到空字节串。SHA-256空盐的最小emLen是34字节,即允许的最小emBits为265,PS可以恰为空。

推论与应用

主例用Go项目保留的RSA Laboratories公开1024/1025位测试密钥数值;旧资料的原签名向量使用SHA-1及20字节盐,本页SHA-256结果是重新计算的教学输出。固定公开私钥和递增盐只用于离线复算,不是安全密钥生成或生产随机盐策略。

设消息长m字节、EM长n字节,SHA-256和MGF1编码需要O(m+n+1)字节工作及O(n)额外缓冲;生成掩码采用一次扩展缓冲,不反复复制增长中的不可变字节串。MGF1允许的掩码长度至多232hLen,否则四字节计数器不够。RSA签名和验证另计各自模幂;公开指数短可以减少乘法次数,但这不消除解析与哈希工作。

验证结果不包含具体失败原因时,更容易保持统一接口;下载器的测试定位则分层进行。实际部署还需经过审计的恒定时间运算、私钥保护和规范协议参数协商,不能直接把教学Python大整数代码接到真实签名服务。

签名执行实验的结构迁移从1024位换成1025位模数,并要求分别列S、EM、DB、PS长度及保留位数。再保持消息与密钥不变、把盐长设为0,重新推导边界和分隔位置,而不是只替换一个数字后沿用旧解析器。

参考资料
  • Kathleen Moriarty等,RFC8017: PKCS #1 v2.2,2016年11月,§§8.1.1–8.1.2、9.1.1–9.1.2、B.2.1:RSA-PSS、EMSA-PSS及MGF1
  • Go项目保留的RSA Laboratories公开PSS测试资料,Example1与Example2的1024/1025位RSA参数;原资料采用SHA-1,本页只复用公开密钥数值并另外计算SHA-256教学结果
关系图谱9 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系