PKCS#1 v2.1: RSA密码学规范

RSA实验室
2002年6月14日
--翻译:CaesarZou (zoudeqiang1979@tsinghua.org.cn)

1.介绍

这个文档提供了基于RSA算法的公钥密码学的建议实现,包含如下的方面:
> 密码学单元
> 加密方案
> 带填充的签名方案
> 以ASN.1语法展现的密钥和方案
参考建议基于计算机的通用需求和通讯系统,并且引入了合适数量的灵活性。建议基于这个规范的应用标准可以包含额外的限制。参考建议尝试与IEEE-1353-2000和当前ANSI X9F1开发的讨论版本规范以及IEEE P1363[27]工作组兼容。

这个文档取代PKCS#1 版本2.0。 但是包含兼容的技术。

这个文档的组织结构如下:
> 第一章是一个介绍。
> 第二章定义了这个文档中使用的一些符号。
> 第三章定义了RSA公钥和四要类型。
> 第四章和第五章定义了一些单元或者数学操作的基本单位。
> 第六章第七章和第八章解决了这个文档中加密和签名的方案。第六章给出了一个综述,沿着PKCS$1 v1.5定义的方法,第七章定义了OAEP基础的加密算法,第八章定义了PSS基础的填充签名算法。
> 第九章定义了第八章定义的签名算法的编码方法。

附录A定义了第三章定义的密钥以及第七章第八章定义的算法的ASN.1语法标识。
附录B定义了这个文档中使用的哈希函数和掩码生成算法。包含算法的ASN.1语法标识。
附录C给出了一个ASN.1模块
附录D,E,F和G包含了一些常见问题,PKCS#1的版本历史,给出到其它出版物和规范的引用,并提供关于公钥算法规范的基本信息。

2 符号
c      密文标识,是一个0到n-1大小的整数。
C     密文标识,一个字符串
d     RSA私有指数
di    ri的CRT指数的附加因子,一个正整数满足 e *  di ≡ 1 (mod(ri-1)), i=3,....,u
dP  p的CRT指数,一个正整数满足e*dP≡1(mod(p-1))
dQ  q的CRT指数,一个正整数满足e*dQ≡1(mod(q-1))
e    RSA公有指数
EM  编码消息,一个字节串
emBits 一个编码消息EM的比特长度
emLen  一个编码消息EM的字节长度
GCD       两个正整数的最大公约数
Hash     哈希函数
hLen     哈希函数Hash输出的字节长度
k           RSA模数n的字节长度
K          RSA私钥
L          可选的RSAES-OAEP标签,一个字节串
LCM      一系列正整数的最小公倍数
m         消息标识,一个0到n-1的整数
M         消息,一个字节串
mask    MGF的输出,一个字节串
mgfSeed mask生成的种子,一个字节串
mLen   消息M的字节长度
n           RSA模数,n=r1*r2*....ru, u>=2
(n,e)      RSA公钥
p,q        RSA模数n的第一分解因子
qinv      CRT西数,一个小于p的正整数,满足q.qinv≡1(mod p)
ri           RSA模数的主因子,包含r1=p, r2=q,如果有的话也包含额外的因子。
s            签名标志,一个0到n-1整数
S          签名,一个字节串
sLen     EMSA-PSS的字节长度
ti           ri的CRT系数的附加质数,一个小于ri的正整数,满足r1*ri*....*ri-1*ti ≡ 1(mod ri), i=3,.....u
u           RSA模数的主因子个数,u大于等于2
x           一个正整数
X          x的字节串
xLen     X的字节串长度
0x         一个字节或者一个字节串的十六进制标识;"0x48"意味着十六进制的值48;"(0x)48 09 0e"意味着由3个连续的十六进制值48,09,03组成的字节串
λ (n)     r1-1,r2-1,ru-1的最小公倍数
⊕         两个字节串异或
[.]          上限函数,一个大于等于实数x的最小整数
||           连接符
≡         全等符号;a≡b(mod n)意思是n可以被整数a-b整除

注释。CRT可以使用回调或者非回调的方式提供,本文参照了加纳算法使用的回调算法。参见3.2章的注释1.

3 密钥类型
这个文档的算法和单元提供了两种密钥类型:RSA公钥和RSA私钥。RSA公钥和RSA私钥合在一起称为RSA密钥对。
这个规范支持号称“多质数”的可以有两个以上质数因子的RSA模数。多模数的RSA的好处是使用CRT(中国余数算法)的时候是解密和签名运算具有更低的计算代价。
在单处理器平台就可以获得很好的表现,并且在多处理器平台上面会有很大的提升,因为可以并行的调用模幂运算。
关于多个质数对RSA算法安全的影响的讨论,参见注释[49]

3.1 RSA公钥
基于这个文档的目标,一个RSA公钥由两个组件组成:
n RSA模数,一个正整数
e RSA公共指数,一个正整数

在一个有效的RSA公钥中,RSA模数n是由u个独立的质数ri,i=1,2....,u(u>=2)的乘积,RSA公共指数e是一个介于3到n-1的整数,满足GCD ( e,  λ (n)) = 1
其中λ (n) = LCM (r1 – 1, …,  ru– 1)。按惯例,前两个质数r1和r2也可以被分别的定义为p和q。

在不同实现之间交换的公钥建议语法参见附录A.1.1;实现内部的表现可以是不同的。

3.2 RSA私钥
基于这个文档的目标,一个RSA私钥可以有如下两种标识方式:
1.第一种标识方式由(n, d)对组成,其中组件意义如下:
n RSA模数,一个正整数
d RSA私有指数,一个正整数

2.第二种标识方式由一个五元组(p,q,dP,dQ,qInv)和一个(可能为空)的三元组(ri,di,ti)组成,i=3,...,u,对应于不在五元组的每个指数。其中组件意义如下:
p 第一因子,一个正整数
q 第二因子,一个正整数
dP 第一因子的CRT指数,一个正整数
dQ 第二因子的CRT指数,一个正整数
qInv第一CRT系数,一个正整数
ri 第i因子,一个正整数
di 第i因子的CRT指数,一个正整数
ti 第i因子的CRT系数,一个正整数

在一个第一种方式描述的有效的RSA私钥内,RSA模数和对应的RSA公钥中的模数一致,由u个独立的质数ri,i=1,2....,u(u>=2)的乘积,RSA私有指数d是一个小于n的正整数
满足e ·  d ≡  1 (mod  λ (n)) ,其中e是公钥指数,λ (n)参照第3.1章的定义。

在一个第二种方式描述的有效的RSA私钥内,因子p和q是RSA模数n的前两个质数因子(r1 和 r2),CRT指数dP和dQ是小于p和q的正整数满足
e ·  dP ≡  1 (mod  (p – 1))   e ·  dQ ≡  1 (mod  (q – 1)) ,并且CRT系数qInv是一个小于p的正整数,满足q ·  qInv  ≡  1 (mod  p)。
如果u>2,描述还需要包含一个或者多个的三元组(ri,di,ti),i=3,...,u.ri因子是RSA模数n的附加质数因子,每个CRT指数di(i=3,...,u)
满足e ·  di ≡  1 (mod ( ri – 1)) .
每个CRT系数ti(i=3,...,u)是一个小于ri的正整数Ri·ti ≡  1 (mod  ri) , 其中Ri  =  r1 · r2  · …·  ri –1

在不同实现之间交换的私钥建议语法参见附录A.1.2;实现内部的表现可以是不同的。

注释:
1.此处CRT系数的定义遵从和使用了第五章描述的加纳算法。然而为了和PKCS#1 v.20以及以前版本的描述兼容,p和q的规则相对于其它的质数是颠倒的。因此
CRT系数qInv被定义为q模p的倒数,而不是R1模r2或者说是p模q的倒数。
2.Quisquater and Couvreur算法符合了中国余数算法带给RSA操作的好处。

4.数据转化单元
这个文档定义了两个数据转化单元
> I2OSP 整数到字节串单元
> OS2IP 字节串到整数单元
基于本文的目标,考虑到ASN.1的语法,一个字节串是一个有序的八比特字节组成的。顺序从左到右,从到整数的转化考虑,在接着的转化单元中,第一个字节为最高有效字节。

4.1 I2OSP(整数到字节串单元)
I2OSP转化一个非负整数为一个指定长度的字节串。
I2OSP(x,xLen)
输入: x 待转化的非负整数
xLen 预订的结果字节串的长度
输出: X 对应的长度为xLen的字节串
错误: 整数太大了

步骤:
1.如果x >= 256^xLen, 输出错误信息“整数太大”并结束
2.将整数x写为基于256的唯一的xLen长度数字表示:
x = x(xLen-1)256^(xLen-1) + x(xLen-2)256^(xLen-2)+...+x0, 其中0=<xi<=256(注意如果x小于256^(xLen-1),将会有一个或者多个的引导数为零)。
3.设字节Xi为X(xLen-i)的值。i从1到xLen,输出字节串: X=X1X2...X(xLen)

4.2 OS2IP(字节串到整数单元)
OS2IP转化一个字节串到一个非负整数。
OS2IP(X)
输入: X 待转化的字节串
输出: x 对应的正整数

步骤:
1.使得X的字节X1X2...X(xLen)从左到右,并使得整数值作为x(xLen-i) 1<=i<=xLen。
2.使得x=x(xLen-1)256^(xLen-1)+x(xLen-2)256^(xLen-2)+...+x0
3.输出x。

5.算法单元
算法单元是在具体加密算法使用的基础数学操作。它被假定为通过硬件或者软件模块实现,而不提供算法安全无关的逻辑。
本文中定义了四种类型的单元,成对的方式组织为:加密和解密;签名和验签。
单元的规范假定输入条件满足特定规定,并且RSA的公钥和私钥是有效的。

5.1 加密和解密单元
一个加密单元在公钥的控制下从输入消息产生一个密文,并且解密单元在对应私钥的控制下将密文恢复为明文。
在本文中定义的:RSAEP/RSADP中使用了一对加密和解密单元。RSAEP和RSADP使用了不同密钥输入下的相同的数学操作。
此处定义的单元和IEEE规范中的IFEP-RSA/IFDP-RSA是相同的,并且兼容PKCS#1 v1.5
单元中用到的主要数学操作是模幂。

5.1.1 RSAEP
RSAEP((n,e),m)
输入: (n,e) RSA公钥
m 消息标识,一个介于0到n-1的整数
输出: c 密文标识,一个介于0到n-1的整数
错误: 消息标识越界
假定: RSA公钥(n,e)是有效的

步骤:
1.如果消息标识m不在0到n-1,输出“消息越界”并停止。
2.使得c=m^e mod n
3.输出c

5.1.2 RSADP
RSADP(K,c)
输入: K RSA私钥,K有如下的格式:
--一个对(n,d)
--一个五元组(p,q,dP,dQ,qInv)和一个可能为空的三元组(ri,di,ti),i=3,...,u
c 密文,一个介于0到n-1之间的整数
输出: m 消息标识,一个介于0到n-1的整数
错误: 密文数据越界
假定: RSA私钥K是有效的

步骤:
1.如果密文标识c不在0到n-1之间,输出“密文消息越界”并停止
2.消息标识m采用如下方式产生。
a.如果K使用第一种方式(n,d),使得m=c^d mod n
b.如果K使用第二种方式(p,q,dP,dQ,qInv)和(ri,di,ti),流程如下:
1. 使得m1=c^dP mod p, m2=c^dQ mod q
2. 如果u>2,使得mi=c^di mod ri, i=3,...,u
3. 使得h=(m1-m2)*qInv mod p
4. 使得m=m2 + q*h
5. 如果u>2,使得R=r1并且从i=3到u开始做
1.使得R=R*ri-1
2.使得h=(mi-m)*ti mod ri
3.使得m=m + R*h
3.输出m

注释:2.a步骤可以重写为一个单循环,由p和q的顺序反转。参见PKCS#1 V2.0,所以前两个质数p和q和其它扩展指数是区别对待的。

5.2 签名和验签操作
签名单元提供了在私钥控制下从消息产生一个签名的过程,一个验签单元在对应的公钥的控制下,将消息从对应的签名中产生出来。
本文定义的一对签名和验签操作为:RSASP1/RSAVP1.
本单元和IEEE1363-2000中的IFSP-RSA1/IFSP-RSA1相同并且兼容PKCS#1 v1.5
RSASP1和RSAVP1除了名字和参数和RSADP和RSAEP不一致外,单元中用到的主要数学操作和加密解密一样为模幂;他们是由不同的目标区分的。

5.2.1 RSASP1 
RSASP1(K,m)
输入输出流程等同于RSADP

5.2.2 RSAVP1
RSAVP1((n,e),s)
输入输出流程等同于RSAEP

6 方案综述
方案联合了算法单元和其它的技术来实现特定的安全目标。本文规定了两种类型的设计:加密方案和带填充的签名方案。
本文中的设计定义仅包含操作方案中的RSA公钥或私钥的处理数据的步骤,不包含获得和验证密钥的过程。然而除了算法方案外,应用的典型操作还应该包含为RSA算法过程选择公私钥的密钥管理过程。这部分附加的操作和细节不在本文范围内。
因为是作为一个数学单元,算法操作假设输入的特定条件是满足的,特别是RSA的公钥和私钥的有效性。因此,一个实现在密钥无效的情况下的操作是未定义的。
这种未定义属性的处理由应用决定。
解决密钥验证的可能手段,包含应用明确的密钥验证;公共密钥基础框架的密钥验证;以及追究产生无效密钥的操作的分配责任。
一个总体上比较好的加密的做法是在一个过程中使用一个给定的RSA密钥对。这就避免了一个设计的漏洞影响到其它部分安全的风险,对保证安全至关重要。
虽然RSAES-PKCS1-v1_5(7.2章)和RSASSA-PKCS1-v1_5(8.2章)传统上被遗弃使用并且没有任何已知的坏的作用,但在新的应用中,这种类型的组合是不推荐的。
举例来说明在多个过程中使用一个RSA密钥对的风险,假设一个RSA密钥对在RSAES-OAEP(7.1)和RSAES-PKCS1-v1_5同时使用。尽管RSAES-OAEP是抗攻击的,但攻击者可以在RSAES-PKCS1-v1_5中找到弱点来把加密的消息恢复出来。
另外一个例子,假设一个RSA密钥对同时被RSASSA-PSS和RSASSA-PKCS1-v1_5使用。然后RSASSA-PSS的安全验证将不再是足够的,因为验证不考虑被第二个过程产生签名的可能性。基于类似的考虑,同一组密钥在此处定义的过程和其它地方定义的过程共享的时候,也有同样的问题。

7 加密方案
基于本文的目的,一个加密过程由一个加密操作和一个解密操作,加密操作使用接受到的公钥从一个消息产生一个密文,解密操作使用给定的RSA私钥将密文恢复为明文。
加密过程可以在多种应用中使用,一个典型的应用是建立协议,消息包含着密钥数据秘密的从一方发给另外一方。具体的实例,PKCS#7使用这样的协议从发送者提交内容-加密密钥到接收者;次数定义的加密过程将会符合那个场景下的密钥-加密算法。
本文定义了两个加密过程:RSAES-OAEP和RSAES-PKCS1-v1_5。RSAES-OAEP建议在新的应用中使用;RSAES-PKCS1-v1_5的包含仅仅是为了和现有的应用兼容,在新应用中不建议使用。
此处定义的加密过程遵从类似IEEE Std 1363-2000 的通用模型,包含在加密算法内的加密和解密单元。加密操作提供对消息提供编码操作其产生一个整数形式的编码消息。加密单元操作消息编码产生密文。相对于此,解密操作将密文恢复为转化为字节串的编码消息。消息解码操作将编码的消息恢复为原始消息并且校验解密的正确性。
为了避免实现在解码操作中的方式错误带来的实现弱点,RSAES-OAEP和RSAES-PKCS1-v1_5的解码操作嵌入在各自的规范里,而不是定义在其它规范中。两个加密过程都和PKCS#1 v2.0对应的过程兼容。

7.1 RSAES-OAEP
RSAES-OAEP包含了RSAEP和RSADP单元(第5.11和5.12章)以及EME-OAEP编码方法(7.1.1 step 1.b和7.1.2 step 3)。EME-OAEP基于Bellare和Rogaway的最佳非对称加密方案。它和IEEE Std 1363-2000中的IFES对应的加密和解密单元是IFEP-RSA和IFDP-RSA,消息编码算法是EME-OAEP方案兼容。
RSAES-OAEP可以操作长度最大为k-2hLen-2个字节,hLen是潜在的哈希输出的长度,k是RSA模数的容器字节数。
假设计算e的th次方模n是不可行的,并且RSAES-OAEP的掩码生成函数也有相应的属性,RSA理论上对抵抗指定密文攻击是安全的。这个保证是可证实的,攻破RSA-OAEP的难度直接依赖于反推RSA函数的难度,提供的掩码函数可以被看作黑盒子或者随机数,见[21]有进一步的讨论。
RSAES-OAEP的加密和解密操作都使用一个标签L的值作为输入。在这个PKCS#1的版本中,L是一个空串;其它标签的使用不在本文范围内。参照附录A.2.1相对的ASN.1语法。
RSAES-OAEP通过选择哈希函数和掩码生成函数来参数化。对于一个给定的RSA密钥,这个选择是固定的。建议的哈希和掩码生成函数见附录B。

7.1.1 加密操作
RSAES-OAEP-ENCRYPT  (( n,  e),  M, L )
可选: Hash 哈希函数(hLen代表哈希函数的输出字节数)
MGF 掩码生成函数
输入:
(n,e) 输入的RSA公钥(k代表RSA模数n的字节长度)
M 待加密的数据, 一个长度为mLen的字节串,并且mLen<=k-2hLen-2
L 可选的和消息关联的标签;如果L没有提供,默认的值是空串
输出:
C 加密输出,长度为k的字节串
错误: “消息太长”;“标签太长”
假设: RSA公钥(n,e)是有效的。
操作:
1.长度检查
a.如果L的长度超过了哈希函数的输入限制(SHA-1是2^61-1字节),输出"标签太长“并中止。
b.如果mLen>k-2hLen-2,输出“消息太长”并中止。
2.EME-OAEP编码
a.如果标签L没有提供,使得L为空串。使得lHash=Hash(L),一个长度为hLen的字节串。
b.生成一个字节串PS,由k-mLen-2hLen-2个字节零组成,PS的长度有可能是0。
c.连接lHash,PS,一个单字节值为0x01和消息M,形成一个长度为k-hLen-1的字节串: DB = lHash || PS || 0x01 || M
d.生成一个长度为hLen的随机字节串种子seed。
e.使得 dbMask = MGF(seed, k-hLen-1)
f.使得 maskedDB = DB ⊕ dbMask.
g.使得 seedMask = MGF(maskedDB, hLen)
h.使得 maskedSeed = seed ⊕ seedMask
i.级联值为0x00的单字节,maskedSeed,和maskedDB形成长度为k的消息EM: EM = 0x00 || maskedSeed || maskedDB
3.RSA加密:
a.转化消息EM为一个整数m(参见4.2章) 
m = OS2IP(EM).
b.使用RSA公钥(n,e)和消息m产生一个加密结果整数c。  
c = RSAEP((n,e),m).
c.转化加密结果c为长度为k的加密数据C。
C = I2OSP(c,k)
d.输出密文C

7.1.2 解密操作
RSAES-OAEP-DECRYPT (K ,  C, L )
可选: Hash 哈希函数(hLen代表哈希函数的输出字节数)
MGF 掩码生成函数
输入: K 输入的RSA私钥(k代表RSA模数n的字节数)
C 待解密的密文,长度为k的字节串,k>=2hLen+2
L 可选的关联到验证的消息的标签,L没提供的话,使用默认值空串。
输出: M 消息,一个长度为mLen的字节串,并且mLen <= k-2hLen-2
错误: “解密错误”
步骤:
1.长度检查
a.如果L的长度大于哈希函数的输入限制,输出“解密错误”并停止。
b.如果密文C的长度不是k个字节,输出“解密错误”并停止。
c.如果k<2hLen+2,输出“解密错误”并停止。
2.RSA解密
a.转化密文C为整数形式c(参见第4.2章)
c = OS2IP(C)
b.使用RSADP解密单元使用私钥K将密文c产生整数消息m:
m = RSADP(K,c)
如果RSADP输出“解密数据越界”(c>=n),输出"解密错误“并停止。
c.转化消息m为k字节长度的字节串EM
EM = I2OSP(m,k)
3.EME-OAEP解码
a.如果标签L没有提供,使得L作为空串。使得 lHash = Hash(L), 一个长度为hLen的字节串。
b.将编码消息EM切分为一个字节Y,一个长度为hLen的字节串maskedSeed,和一个长度为k-hLen-1的字节串maskedDB
EM = Y || maskedSeed || maskedDB
c.使得 seedMask = MGF(maskedDB, hLen)
d.使得 seed = maskedSeed ⊕  seedMask
e.使得 dbMask = MGF(seed, k-h-1)
f.使得 DB = maskedDB  ⊕  dbMask
g.将DB分成长度为lHash的字节串,一个由0组成的填充串,和消息M
DB = lHash' || PS || 0x01 || M
如果没有值为0x01的数据将PS和M分隔开,如果lHash不等于lHash',或者如果Y非零,输出“解密错误“并停止。
4.输出消息M。

7.2 RSAES-PKCS1-v1_5
RSAES-PKCS1-v1_5包含RSAEP和RSAEP单元和EME-PKCS1-v1_5编码方法.它算术上等于PKCS#1 v1.5的加密算法。RSAES-PKCS1-v11+5可以操作长度最大为k-11字节(k是RSA模数n的字节长度)。
但应小心在长数据加密过程中基于 Coppersmith, Franklin, Patarin, 和 Reiter的小指数RSA攻击。作为一般规则,此方案用于加密普通的消息,而不建议用于加密随机生成的密钥。
它有一定概率成功的在不知道对应的明文的前提下产生有效的RSAES-PKCS-v1_5的密文。这个能力可能被密文选择性攻击利用。因此如果采用RSAES-PKCS1_v1_5,应采取一些容易实施的对策阻扰攻击。
典型的例子是在数据中加入附加结构,在解密的消息中严格检查PKCS#1 v1.5的一致性(和其它冗余)。并巩固在基于PKCS#1 v1.5的客户-服务协议中的错误消息。这些都可以是不涉及改动PKCS#1 v1.5基础协议的有效的对策。
这个问题的进一步讨论请参照[7]。最近展现出来的SSL/TLS的握手协议,就是使用RSAES-PKCS1-v1_5和若干对策解决RSA问题的一个变种。

7.2.1 加密操作
RSAES-PKCS1- V1_5-ENCRYPT   ((n,  e),  M)
输入: (n,e) 输入的RSA公钥(k代表RSA模数n的字节长度)
M 待加密的数据, 一个长度为mLen的字节串,并且mLen<=k-11
输出: C 密文,长度为k的字节串
错误: “消息太长”
步骤:
1.长度检查: 如果mLen > k-11,输出“消息太长”并停止。
2.EME-PKCS1-v1_5编码:
a.生成长度为k-mLen-3的字节串PS包含随机生成的非零的伪随机数。PS的长度最小为8个字节。
b.级联PS,消息M和其它的填充组成长度为k的消息EM
EM = 0x00 || 0x02 || PS || 0x00 || M
3.RSA加密:
a.转化消息EM为整数消息m(参照4.2章)
m = OS2IP(EM)
b.使用RSAEP加密单元使用RSA公钥(n,e)和消息m生成整数密文c。
c.转化整数c为长度为k的密文字节串。
C = I2OSP(c,k)
4.输出密文C。
7.2.2 解密操作
RSAES-PKCS1- V1_5-D ECRYPT (K ,  C )
输入: K 输入的私钥
C 待解密的密文,一个长度为k的字节串,k是RSA模数n的字节长度。
输出: M 消息,一个长度最多为k-11的字节串
错误: "解密错误“
步骤:
1.长度检查:如果C的长度不是k个字节,(或者k<11),输出“解密错误”并停止。
2.RSA解密:
a.将密文C转化为整数形式c。
c = OSIP(C)
b.使用RSADP使用RSA私钥(n,d)和密文c产生整数消息m。
m = RSADP((n,d),c)
c.将消息m编码为长度为k的字节码串EM。
EM = I2OSP(m,k)
3.EME-PKCS-v1_5解码:将EM编码为由非零字节组成的PS和消息M:
EM = 0x00 || 0x02 || PS || 0x00 || M。

如果EM的第一个字节不是0x00,如果第二个字节不是0x02,如果没有0x00来分割PS和M,或者如果PS的长度小于8字节,输出“解密失败”并停止。
4.输出M。

8 带填充的签名方案
基于这个文档的目的,一个带填充的签名方案由一个签名操作和一个验签的操作组成,签名操作使用RSA私钥对消息产生签名,验签操作使用RSA公钥对签名进行验证。
使用这个方案来验签必须有消息本身。在这种方式下,带填充的签名方案有别于本人中不支持的消息回复的签名方案。
带填充的签名算法可以在各种应用中使用。举个例子,此处定义的带填充的签名算法将适合X.509证书的签名算法。相关的签名算法将在PKCS#7中使用,尽管出于技术原因,当前版本的PKCS#7是从签名方案分离出的与此处不同的哈希函数;参见附录A2.3进一步的讨论。
本文档定义了两个带填充的签名算法:RSASSA-PSS和RSSSA-PKCS1-v1_5。尽管没有已知的针对RSASSA-PKCS1-v1_5的攻击,基于对健壮性增强的兴趣,建议新的应用最终使用RSASSA-PSS。RSASSA-PKCS1-v1_5包含以兼容已经存在的应用,不过仍然鼓励新的应用平滑的过度到RSASSA-PSS上。
此处给出的带填充签名算法和IEEE Std 1363-2000中一样尊崇一个通用的模型,签名和验签单元和一个签名编码方法。签名操作对消息编码操作产生一个编码数据,然后转为整型消息数据。签名过程对消息产生签名。与此相反,验签操作提供签名验证单元将签名恢复为消息,并转化为字节编码的消息。验签操作对消息和编码后的消息操作,判断他们是否是一致的。
如果编码方法是确定的,验签操作将对消息产生编码操作,并比较编码结果和提供的消息。如果匹配,签名被认为是有效的。如果方法是不确定的,验签操作显然更复杂。例如,EMSA-PSS的验证操作提取随机数成分和一个编码消息的哈希值,并检查是否哈希输出和成分是否匹配。在特定的消息和成分组里面哈希函数是确定的。
对本文定义的两种签名方案来说,如果签名被放置在消息后边,签名和验签操作很容易实现“单通”操作。参阅PKCS#7的基于RSASSA-PKCS1-v1_5的例子。

8.1 RSASSA-PSS
RSASSA-PSS由RSASP1和RSAVP1模块和EMSA-PSS编码方法组成。和IEEE P1363a讨论规范中修订的IFSSA方案中定义的IEEE Std 1363-2000 IFSP-RSA1和IFVP-RSA1操作以及EMSA4的编码兼容。EMSA4比EMSA-PSS稍微通用一点,因为它基于比特串而不是字符串。EMSA-PSS等同于EMSA4操作字节串的哈希和成分的限制版。
RSASSA-PSS可以操作的消息长度既不是无限制也不是限制为非常大的数目,取决于EMSA-PSS编码方法使用的哈希函数。
考虑到计算 e^th MOD(n)是不可实行的,并且EMSA-PSS中的哈希和掩码生成函数也有适当的特性,RSASSA-PSS提供安全的签名。在这个意义上,这个保证是可以证实的因为伪造签名的难度和RSA反响运算的难度直接等同,并由哈希和掩码生成函数作为黑盒子或随机引入。安全性被证明是很高,意味着成功对RSASSA-PSS进行伪造的速度和概率与RSA反演类似。见[4][13][31]进一步的讨论。
对比RSASSA-PKCS1-v1_5签名方案,哈希函数标识不签入EMSA-PSS编码消息,所以,理论上,对手有可能选择和签名者不一样的哈希算法。因此,建议EMSA-PSS掩码生成函数基于相同的哈希函数。
基于这种方式,整个编码的消息都将依赖于哈希函数,对手使用其它哈希函数替换签名的函数将很困难。这种哈希函数匹配仅用于防治哈希函数替换的目的,不是必要的。如果哈希函数通过其它方式替代(列入,验证只接受指定的哈希函数)。进一步讨论参见[34]。RSASSA-PSS的可证明安全性不依赖于用户掩码的哈希函数相同。
RSASSA-PSS和其它的基于RSA的签名方案不同的是它的引入随机生成的salt带来的非确定性。salt值通过提供一个更严格的安全证明比确定性的替代品(例如全域哈希)更多的安全提升。然而,随机性不是安全的关键。在随机数生成无法实现的情况下,一个固定的值或者序列数字也可以替代,并且产生可证明相似于FDH的安全性。

8.1.1 签名操作
RSASSA-PSS-S IGN  ( K ,  M)
输入: K 签名的私钥
M 待签名的消息,一个字节串。
输出: S 签名,一个长度为k的字节串,k是RSA模数n的字节数。
错误: "消息太长“,“编码错误”
步骤:
1.EMSA-PSS编码:使用EMSA-PSS编码操作(第9.1.1章)使用消息M产生一个长度为[(modBits-1)/8]的字节串EM,或者说OS2IP的比特长度最多为 modBits-1,modBits是RSA模数n的比特长度。
EM = EMSA-PSS-ENCODE(M,modBits-1)
注意,如果modBits-1可以被8除尽,EM的字节将比k小1,否则等于k。如果编码操作输出“消息太长”,输出“消息太长”并停止。如果编码操作输出“编码错误”,输出“编码错误”并停止。
2.RSA签名:
a.转化编码消息EM为整数消息m
m = OSIP(EM).
b.使用RSASP1签名单元用RSA私钥K和消息m产生一个整数结果s
s = RSASP1(K,m).
c.转化签名值s为长度为k的字节串S。
S = I2OSP(s,k).
3.输出签名S

8.1.2 验签操作
RSASSA-PSS-V ERIFY   ((n,  e),  M, S)
输入: (n,e) 验签的公钥
M 将验签的消息,一个字节串
S 待验证的签名,长度为k的字节串,k为RSA模数n的字节长度。
输出: “有效签名” 或 “无效签名”
步骤:
1.长度检查:如果S的长度不是k个字节,输出“无效签名”并停止。
2.RSA校验:
a.将S转化为整数表示s
s = OS2IP(S).
b.使用RSAVP1验签单元用RSA公钥(n,e)和签名数据产生一个整数消息m
m = RSAVP1((n,e),s)
如果RSAVP1输出“签名越界”输出“无效的签名”并停止。
c.将消息m转化为长度为emLen=[(modBits-1)/8]字节,modBits是RSA模数n的比特长度:
EM = I2OSP(m,emLen)
注意,如果modBits-1被8整除,emLen为k-1,否则为k。如果I2OSP输出“整数太大”,输出“无效的签名”并停止。
3.EMSA-PSS验证:使用EMSA-PSS验证操作(第9.1.2章)对消息M和编码消息EM来判断他们是否相同。
Result = EMSA-PSS-VERIFY(M,EM,modBits-1).
4.如果结果为相等,输出“有效签名”,否则输出“无效签名”。

8.2 RSASSA-PKCS1-v1_5
RSASSA-PKCS1-v1_5包含了RSASP1和RSAVP1单元和EMSA-PKCS1-v1_5编码方法。它与定义在IEEE Std 1363-2000中的IFSSA规范中对应的IFSP-RSA1和IFVP-RSA1以及消息编码EMSA-PKCS1-v1_5是兼容的。
RSASSA-PKCS1-v1_5可以处理的消息长度既不是无限制也不是强迫为很大的数,取决于EMSA-PKCS1-v1_5使用的哈希函数。
假设计算e^th mod(n)是不可行,并且EMSA-PKCS-v1_5中的哈希函数有适当的属性,RSASSA-PKCS1-v1_5推测可以提供安全的数字签名。更确切的说,在不知道私钥的前提下打造签名是不可能的。另外,在EMSA-PKCS1-v1_5的编码方法中,签入了一个哈希函数标识。因为这个特点,试图发现之前签名消息的相同的签名值的攻击者必须寻找使用哈希函数的碰撞对。攻击与签名选择的哈希不同的函数是没有用的。

8.2.1 签名操作
RSASSA-PKCS1-V1_5-SIGN  ( K ,  M)
输入: K 签名用的私钥
M 待签名的消息,一个字节串
输出: S 签名,一个长度为k的字节串,k是RSA模数n的字节个数。

错误: “消息太长”;“RSA模数太短”
步骤:
1.EMSA-PKCS1-v1_5 编码:使用EMSA-PKCS1-v1_5 编码操作将消息M产生编码消息EM,长度为k字节。
EM = EMSA-PKCS1-v1_5-ENCODE(M,k)
如果编码操作输出“消息太长”,输出“消息太长”并中止。如果编码操作输入“参与编码消息长度太短”,输出“RSA模数太短”并停止。
2.RSA签名:
a.将EM转化为整数m。
m = OS2IP(EM)
b.使用RSASP1签名单元用RSA私钥K和消息m来产生整数签名s
s = RSASP1(K,m)
c.转化签名s为长度为k个字节的字节串S
S = I2OSP(s,k).
3.输出签名S。

8.2.2 验签操作
RSASSA-PKCS1-V1_5-V ERIFY   ((n,  e),  M, S)
输入: (n,e) 签名的RSA公钥
M 待验证签名的消息,一个字节串
S 待验证的签名,长度为k的字节串,k是RSA模数n的长度。
输出: “有效签名”,“无效签名”
错误: “消息太长”,“RSA模数太短”
步骤:
1.长度检查:如果S的长度不是k字节,输出“无效签名”并停止。
2.RSA验证:
a.转化签名S为整数形式表示s.
s = OS2IP(S).
b.使用RSAVP1验签单元用公钥(n,e)和签名消息s产生一个消息标识m:
m = RSAVP1((n,e),s).
如果RSAVP1输出“签名越界”,输出“无效的签名”并停止。
c.转化消息m为长度为k的字节串编码消息EM':
EM = I2OSP(m,k).
如果I2OSP输出“整数太大”,输出“无效签名”并停止。
3.EMSA-PKCS1-v1_5编码:使用EMSA-PKCS-v1_5编码操作将消息M产生另一个长度为k字节的编码消息EM'。
EM' = EMSA-PKCS1-v1_5-ENCODE(M,k).
如果编码操作输出“消息太长“,输出”消息太长“并停止。如果编码操作输出”参与编码的消息太短“,输出”RSA模数太短“并停止。
4.比较编码消息EM和第二编码消息EM‘。如果他们是相同的,输出”有效签名”;否则输出“无效签名”。

9 带填充的编码方法
编码方法由字节串消息和字节串编码消息直接的操作组成,都是和整数消息m互相转出来的。整数消息单元是在单元中使用的。编码方法因此提供了方案和消息之间的连接。
基于这文档的目标,一个带填充的签名算法由编码操作和可选的验证操作组成。编码操作将消息M转化为一个特定长度的编码消息EM。验证操作决定是否消息M和编码消息EM是相等的,或者说EM是不是消息M的有效编码。
编码操作可以引入一些随机性,所以不同的应用对相同消息的编码操作可能产生不同的编码消息,这有助于安全性的提升。对这种编码算法,如果验证算法不能复现随机数,那么编码和验证操作都是必要的。对确定性的编码方法,只需要编码操作。
在签名方案中使用了两个带签名的编码方法,定义如下:EMSA-PSS和EMSA-PKCS1-v1_5。

9.1 EMSA-PSS
这个编码方式可以通过选择哈希函数,掩码生成函数,salt长度来参数化。这些选择对一个给定的RSA密钥是固定的,除了salt长度是可变的。(参见[31]的讨论)。建议的哈希和掩码函数参见附录B。编码方法基于Bellare and Rogaway’s Probabilistic 签名算法(PSS)。是随机性的并有编码和解码操作。

9.1.1 编码操作
EMSA-PSS-ENCODE ( M,  emBits )
属性: Hash 哈希函数(hLen代表着哈希函数的输出)
MGF 掩码生成函数
sLen salt参与的字节数
输入: M 待编码的消息,一个字节串
emBits 整数OSIP(EM)的最大bit长度,最少 8hLen + 8sLen + 9
输出: EM 编码消息,长度为emLen=[emBits/8]的字节串
错误: “编码错误”,“消息太长”
步骤:
1.如果消息M的长度大于哈希函数的输入限制,输出“消息太长”并停止。
2.使得mHash = Hash(M),一个长度为hLen的字节串。
3.如果emLen < hLen + sLen + 2,输出“编码错误”并停止。
4.生成一个随机的字节串salt,长度为sLen;如果sLen = 0,那么salt是空串。
5.使得 M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
6.使得 H = Hash(M'),一个长度为hLen的字节串。
7.生成字节串PS,由 emLen - sLen - hLen - 2个零字节组成,PS的长度可以为0。
8.使得 DB = PS || 0x01 || salt; DB是一个长度为emLen - hLen - 1的字节串。
9.使得 dbMask = MGF(H, emLen - hLen - 1)
10.使得 maskedDB = DB ⊕  dbMask
11.将maskedDB的左边最高有效位的 8emLen - emBits的比特为0。
12.使得 EM = maskedDB || H || bc
13.输出EM
9.1.2 验证操作
EMSA-PSS-VERIFY  ( M,  EM,  emBits )
条件: Hash 哈希函数(hLen代表着哈希函数的输出)
MGF 掩码生成函数
sLen salt参与的字节数
输入: M 待验证的消息,一个字节串。
EM 编码的消息,一个长度为emLen=[emBits/8]的字节串
emBits 整数OSIP(EM)的整数最大bit长度,最小为 8hLen + 8sLen + 9
输出: "相同的“或者”不相同的“
步骤:
1.如果 M的长度超过哈希函数的最大输出限制,输出”不相同“并停止。
2.使得 mHash = Hash(M),一个长度为hLen的字节串
3.如果 emLen < hLen + sLen + 2,输出“不相同的”并停止。
4.如果 EM最右边如果不是十六进制0xbc,输出“不相同的”并停止。
5.使得 maskedDB为EM左边的 emLen - hLen - 1个字节,H为接下来的hLen个字节。
6.如果 maskedDB左边最高有效位的 8emLen - emBits个比特不全等于零,输出“不相同”并停止。
7.使得 dbMask = MGF(H, emLen - hLen - 1)。
8.使得 DB = maskedDB ⊕ dbMask。
9.使得 DB左边最高 8emLen - emBits的比特为0。
10.如果 DB左边最高 emLen - hLen - sLen - 2个字节不为零,或者 emLen - hLen - sLen - 1位置的字节不为0x01,输出“不相同”并停止。
11.使得 DB最后的sLen个字节为salt。
12.使得 M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt。M'是一个由8个零字节引导的长度为8 + hLen + sLen的字节串。
13.使得 H' = Hash(M'), 一个长度为hLen的字节串。
14.如果 H = H',输出“相等”,否则输出“不相等”

9.2 EMSA-PKCS1-v1_5
这个编码方法是确定性的,并只有一个编码操作。
EMSA-PKCS1-v1_5-ENCODE ( M,  emLen )
条件: Hash 哈希函数(hLen代表了哈希函数的输出字节数)
输入: M 待编码的消息
emLen 参与编码消息的长度,最小为tLen + 11,tLen是一个编码操作中确定的DER编码的字节长。
输出: EM 编码消息,一个长度为emLen的字节串。
错误: “消息太长”;“参与的编码消息长度太短”
步骤:
1.使用哈希函数对消息M产生哈希值H:
H = Hash(M)。
如果哈希函数输出“消息太长”,输出“消息太长”并中止。
2.将使用的哈希函数和哈希值以ASN.1描述的DigestInfo的DER编码方式编码,DigestInfo的语法:
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
第一部分表明了哈希函数,第二部分包含了哈希值。使得T作为DER编码的DigestInfo的值,并且tLen为T的字节长度。
3.如果 emLen < tLen + 11,输出“参与编码消息长度太短”并停止。
4.产生一个PS字节串,由长度 emLen - tLen - 3个字节的0xFF组成。PS的长度最小为8个字节。
5.级联PS,DER编码的T,和其它的填充信息,组成编码消息EM
EM = 0x00 || 0x01 || PS || 0x00 || T
6.输出EM

注意:
1.在附录 B.1中提到的六个哈希函数的DigestInfo的DER编码值T如下:
MD2:  (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10  ||  H .
MD5:  (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 ||  H .
SHA-1:  (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14  ||  H .
SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20  ||  H .
SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30  ||  H .
SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40  ||  H .
2.在此文档的1.5版本中,T被定义为DigestInfo的BER编码,而不是DER编码。挑剔的说,至少在理论上本文中的验证操作可能会拒绝在1.5版本中有效的签名。这么说是因为DER以外的编码有可能会产生其它长度的结果。然而在实践中,不需要去关心这个问题,一个谨慎的实现者将会选择实现基于PKCS#1 v1.5中的BER编码。

附录A ASN.1语法
A.1 RSA密钥表示
这张为RSA公钥和私钥定义了ASN.1的对象标识,并且定义了类型 RSAPublicKey 和 RSAPrivateKey。此处定义的应用被包含在 X.509证书,PKCS#8和PKCS#12。
对象标识 rsaEncryption 确定了在A.1.1和A.1.2中定义的公钥和私钥。 关联到这个OID上的类型为AlgorithmIdentifier的parameters域的值为NULL。
rsaEncryption    OBJECT IDENTIFIER ::= { pkcs-1 1 }
本章的定义将会被扩展来支持多质数RSA,但是兼容之前的版本。

A.1.1 RSA公钥表示
RSA公钥的ASN.1类型表示 RSAPublicKey:
RSAPublicKey ::= SEQUENCE {
   modulus           INTEGER,  -- n
   publicExponent    INTEGER   -- e
}
RSAPublic的属性有如下意义:
modulus是RSA的模数n。
publicExponent是RSA的公共指数e。

A.1.2 RSA私钥表示
RSA私钥的ASN.1类型表示 RSAPrivateKey:
RSAPrivateKey ::= SEQUENCE {
   version           Version,
   modulus           INTEGER,  -- n
   publicExponent    INTEGER,  -- e
   privateExponent   INTEGER,  -- d
   prime1            INTEGER,  -- p
   prime2            INTEGER,  -- q
   exponent1         INTEGER,  -- d mod (p-1)
   exponent2         INTEGER,  -- d mod (q-1)
   coefficient       INTEGER,  -- (inverse of q) mod p
   otherPrimeInfos   OtherPrimeInfos OPTIONAL
}
RSAPrivateKey的属性有如下意义:
# version 为了兼容未来的修订提出的版本号。本文的版本,多质数为1,其它则为0.
Version ::= INTEGER { two-prime(0), multi(1) }
    (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
    # modulus 是RSA模数n
    # publicExponent 是RSA公有指数e
    # privateExponent 是RSA私有质数d
    # prime1 是n的质数因子p
    # prime2 是n的质数因子q
    # exponent1 是d mod(p-1)
    # exponent2 是d mod(q-1)
    # coefficient 是CRT系数 q-1 mod p
    # otherPrimeInfos 按顺序包含了附加的质数 r3----ru。它在版本0的时候不存在,将包含在版本1中最少一个实例。
   
    OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
OtherPrimeInfo ::= SEQUENCE {
   prime             INTEGER,  -- ri
   exponent          INTEGER,  -- di
   coefficient       INTEGER   -- ti
}

OtherPrimeInfo的属性有如下的含义:
# prime是n的质数因子ri,i>=3.
# exponent是 di = d mod(ri-1)
    # coefficient是CRT系数 ti = (r1*r2*...ri-1) mod ri
   
    注意:保护RSA私钥不被曝露和修改是非常重要的。这种保护的技术不在本文档的范围内。存储和派发私钥或其它密码数据的方法在PKCS#12和PKCS#15中讨论。
   
A.2 方案标识
这章定义了加密和签名的对象标识。方案兼容于PKCS#1 v1.5,和PKCS#1 v1.5有相同的定义。此处定义的应用在X.509证书和PKCS#7中包含。
此处是PKCS#1 OIDs的类型标识
PKCS1Algorithms    ALGORITHM-IDENTIFIER ::= {
    { OID rsaEncryption              PARAMETERS NULL } |
    { OID md2WithRSAEncryption       PARAMETERS NULL } |
    { OID md5WithRSAEncryption       PARAMETERS NULL } |
    { OID sha1WithRSAEncryption      PARAMETERS NULL } |
    { OID sha256WithRSAEncryption    PARAMETERS NULL } |
    { OID sha384WithRSAEncryption    PARAMETERS NULL } |
    { OID sha512WithRSAEncryption    PARAMETERS NULL } |
    { OID id-RSAES-OAEP PARAMETERS RSAES-OAEP-params } |
    PKCS1PSourceAlgorithms                             |
    { OID id-RSASSA-PSS PARAMETERS RSASSA-PSS-params } ,
    ...  -- Allows for future expansion --
}

A.2.1 RSAES-OAEP
对象标识 id-RSAES-OAEP标识了RSAES-OAEP加密方案。
id-RSAES-OAEP    OBJECT IDENTIFIER ::= { pkcs-1 7 }
与这个OID关联的parameters属性是一个类型为 RSAES-OAEP-params:
RSAES-OAEP-params ::= SEQUENCE {
    hashAlgorithm      [0] HashAlgorithm     DEFAULT sha1,
    maskGenAlgorithm   [1] MaskGenAlgorithm  DEFAULT mgf1SHA1,
    pSourceAlgorithm   [2] PSourceAlgorithm  DEFAULT pSpecifiedEmpty
}
RSAES-OAEP-params的属性有如下的意义:
# hashAlgorithm 标识了哈希函数。 它是一个OAEP-PSSDigestAlgorithms集合中的一个OID表示的算法ID。对支持的哈希函数的讨论,参见附录B.1。

HashAlgorithm ::= AlgorithmIdentifier { {OAEP-PSSDigestAlgorithms} }

OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
   { OID id-sha1 PARAMETERS NULL   }|
   { OID id-sha256 PARAMETERS NULL }|
   { OID id-sha384 PARAMETERS NULL }|
   { OID id-sha512 PARAMETERS NULL },
   ...  -- Allows for future expansion --
    }
    
    默认的哈希函数是SHA-1:
    sha1    HashAlgorithm ::= {
   algorithm   id-sha1,
   parameters  SHA1Parameters : NULL
}
SHA1Parameters ::= NULL

# maskGenAlgorithm标识了掩码生成程序。它是一个PKCS1MGFAlgorithm集合中一个OID表示的算法ID。版本等于id-mgf1的标识了MGF1掩码生成程序。(参见附录B.2.1)。和id-mgf1关联的parameters属性是OAEP-PSSDigestAlgorithms中的OID标识的算法ID,表明了MGF1基于的哈希函数。

MaskGenAlgorithm ::= AlgorithmIdentifier { {PKCS1MGFAlgorithms} }

PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
    { OID id-mgf1 PARAMETERS HashAlgorithm },
    ...  -- Allows for future expansion --
}

id-mgf1    OBJECT IDENTIFIER ::= { pkcs-1 8 }

默认的掩码生成函数是使用SHA-1的MGF1:
mgf1SHA1    MaskGenAlgorithm ::= {
    algorithm   id-mgf1,
    parameters  HashAlgorithm : sha1
}

# pSourceAlgorithm标明了标签L的来源。它将是集合PKCS1PSourceAlgorithms中一个OID表示的算法ID。这个版本将等于id-pSecified,表明标签被明确定义。与id-pSecified关联的参数将是一个类型为OCTET STRING包含标签的字节串。在这个规范的前一个版本,没有使用标签的说法,而是编码参数,今后类型的名字如下:

PSourceAlgorithm ::= AlgorithmIdentifier { {PKCS1PSourceAlgorithms} }

PKCS1PSourceAlgorithms    ALGORITHM-IDENTIFIER ::= {
    { OID id-pSpecified PARAMETERS EncodingParameters },
    ...  -- Allows for future expansion --
    }
    
id-pSpecified    OBJECT IDENTIFIER ::= { pkcs-1 9 }

EncodingParameters ::= OCTET STRING(SIZE(0..MAX))

默认的标签是一个空串(所以lHash将包含空串的哈希值)

pSpecifiedEmpty    PSourceAlgorithm ::= {
    algorithm   id-pSpecified,
    parameters  EncodingParameters : emptyString
}

emptyString    EncodingParameters ::= ’’H

如果RSAES-OAEP-params的属性都采用默认值,那么算法标识就有如下的值:

rSAES-OAEP-Default-Identifier    RSAES-AlgorithmIdentifier ::= {
    algorithm   id-RSAES-OAEP,
    parameters  RSAES-OAEP-params : {
       hashAlgorithm       sha1,
       maskGenAlgorithm    mgf1SHA1,
       pSourceAlgorithm    pSpecifiedEmpty
    }
}

RSAES-AlgorithmIdentifier ::= AlgorithmIdentifier { {PKCS1Algorithms} }

A.2.2 RSAES-PKCS1-v1_5
对象标识符 rsaEncryption (参见附录A.1)标明了RSAES-PKCS1-v1_5加密过程。 与类型为AlgorithmIdentifier的OID关联的parameters属性是一个NULL值。和PKCS#1 v1.5中一致。

rsaEncryption    OBJECT IDENTIFIER ::= { pkcs-1 1 }

A.2.3 RSASSA-PSS
对象标识 id-RSASSA-PSS 标明了RSASSA-PSS加密方案。

id-RSASSA-PSS    OBJECT IDENTIFIER ::= { pkcs-1 10 }
与AlgorithmIdentifier类型的OID对应的parameters属性将为类型为RSASSA-PSS-params的值:

RSASSA-PSS-params ::= SEQUENCE {
    hashAlgorithm      [0] HashAlgorithm      DEFAULT sha1,
    maskGenAlgorithm   [1] MaskGenAlgorithm   DEFAULT mgf1SHA1,
    saltLength         [2] INTEGER            DEFAULT 20,
    trailerField       [3] TrailerField       DEFAULT trailerFieldBC
}

类型RSASSA-PSS-params的属性有如下意义:
# hashAlgorithm 标识了哈希函数,它将是一个由集合 OAEP-PSSDigestAlgorithms中一个OID标识的算法ID。默认的哈希函数是SHA-1.
# maskGenAlgorithm 标识了掩码生成函数,它将是一个由集合PKCS1MGFAlgorithms中一个OID标识的算法ID。默认的掩码生成函数是基于SHA-1的MGF1.对MGF1而言,建议使用和hashAlgorithm相同的哈希函数。第9.1章有进一步讨论。
# saltLength 是salt的字节长度。它将是一个整数。对一个给定的hashAlgorithm,saltLength的默认值应该是哈希值的字节长度。和RSASSA-PSS-params的其它属性不一样,saltLength对一个给定的RSA密钥对,不必要确定。
# trailerField 是跟踪属性个数,为了兼容 IEEE P1363a讨论版。 对这个文档的版本,它的值为1。代表着跟踪属性为值0xbc。其它跟踪属性(比如IEEE支持的HashID || 0xcc)则在此文档中不支持。

TrailerField ::= INTEGER { trailerFieldBC(1) }

如果RSASSA-PSS-params的属性hashAlgorithm, maskGenAlgorithm,和 trailerFiled都采用默认值,那么算法标识有如下的值:

rSASSA-PSS-Default-Identifier    RSASSA-AlgorithmIdentifier ::= {
   algorithm   id-RSASSA-PSS,
   parameters  RSASSA-PSS-params : {
       hashAlgorithm       sha1,
       maskGenAlgorithm    mgf1SHA1,
       saltLength          20,
       trailerField        trailerFieldBC
   }
}

RSASSA-AlgorithmIdentifier ::= AlgorithmIdentifier { {PKCS1Algorithms} }

A.2.4 RSASSA-PKCS1-v1_5
RSASSA-PKCS1-v1_5的对象标识将是如下中的一个。OID的选择依赖于哈希算法的选择:MD2,MD5,SHA-1,SHA-256,SHA-384,或者SHA-512.注意如果使用MD2或者MD5,OID的定义在PKCS#1 v.15中。对每个OID,OID关联的AlgorithmIdentifier类型的parameters属性都是NULL。OID应该在下表中选择:
Hash algorithm OID
MD2 md2WithRSAEncryption    ::= {pkcs-1 2}
MD5 md5WithRSAEncryption    ::= {pkcs-1 4}
SHA-1 sha1WithRSAEncryption   ::= {pkcs-1 5}
SHA-256 sha256WithRSAEncryption ::= {pkcs-1 11}
SHA-384 sha384WithRSAEncryption ::= {pkcs-1 12}
SHA-512 sha512WithRSAEncryption ::= {pkcs-1 13}

EMSA-PKCS1-v1_5编码方法在ASN.1中的标识为 DigestInfo 类型的值,遵照如下格式:
DigestInfo ::= SEQUENCE {
   digestAlgorithm DigestAlgorithm,
   digest OCTET STRING
}

digestAlgorithm 表明了使用集合 PKCS1-v1-5DigestAlgorithms中一个OID标识了算法ID。对支持的哈希函数,参照附录B.1

DigestAlgorithm ::= AlgorithmIdentifier { {PKCS1-v1-5DigestAlgorithms} }

PKCS1-v1-5DigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
   { OID id-md2 PARAMETERS NULL    }|
   { OID id-md5 PARAMETERS NULL    }|
   { OID id-sha1 PARAMETERS NULL   }|
   { OID id-sha256 PARAMETERS NULL }|
   { OID id-sha384 PARAMETERS NULL }|
   { OID id-sha512 PARAMETERS NULL }
}

B 支持的技术
这章给出了第七章和第九章的一些潜在方法的例子。这段范围的技术支持是允许已经存在的应用更好的兼容到新技术。尽管这些支撑技术适合应用的实施,但不一定必须实现。值得期待的是PKCS#1 v2.1将会指定特定的配套技术。
这章也给出了支持的技术的对象标识符。

B.1 哈希函数
哈希函数在第七章和第九章使用。Hash函数是确定性的,这意味着输出完全由输入决定。哈希函数接受可变长度的字节数组,并产生固定长度的字节数组。第七章和第九章使用的哈希函数都是抗碰撞的。这意味着不可能找到两个不同的输入对应同样的输出。一个抗碰撞的哈希函数也有单向的可选属性,这意味着对给定的输出,也不可能找到对应的输入。在另外的需求中,哈希函数也可以作为伪输出的掩码生成函数。
这个文档的编码方法给出了六个哈希函数作为例子:MD2,MD5,SHA-1,以及过时的算法SHA-256, SHA-384,和SHA-512。对RSAES-OAEP加密方案和EMSA-PSS编码方法,新的应用只建议使用SHA-1和SHA-256/384/512。MD2和MD5只为了兼容基于PKCS#1 v1.5的旧应用。
对象标识符 id-md2, id-md5, id-sha1, id-sha256, id-sha384, 和 id-sha512 标识了对应的哈希函数;
id-md2      OBJECT IDENTIFIER ::= {
   iso (1) member-body (2) us (840) rsadsi (113549) digestAlgorithm (2) 2
}
id-md5      OBJECT IDENTIFIER ::= {
   iso (1) member-body (2) us (840) rsadsi (113549) digestAlgorithm (2) 5
}
id-sha1    OBJECT IDENTIFIER ::= {
   iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26
}
id-sha256    OBJECT IDENTIFIER ::= {
   joint-iso-itu-t (2) country (16) us (840) organization (1) gov (101)
   csor (3) nistalgorithm (4) hashalgs (2) 1
}
id-sha384    OBJECT IDENTIFIER ::= {
   joint-iso-itu-t (2) country (16) us (840) organization (1) gov (101)
   csor (3) nistalgorithm (4) hashalgs (2) 2
}
id-sha512    OBJECT IDENTIFIER ::= {
   joint-iso-itu-t (2) country (16) us (840) organization (1) gov (101)
   csor (3) nistalgorithm (4) hashalgs (2) 3
}

类型AlgorithmIdentifier中和OID对应的parameters属性的值为NULL。

B.2 掩码生成函数
一个掩码生成函数使用变长的字节串和一个指定的输出长度作为输入,并输出指定长度的字节串。有可能限制输入和输出的字节串的长度,但这种边界通常是非常大。掩码生成函数是确定性的;字节串的输出完全取决于输入。掩码生成函数应该是伪随机的:一部分的输出不能预测输出的另一部分。被证明为安全的RSAES-OAEP和RSASSA-PSS依赖于掩码生产函数输出的随机性质,反过来影响哈希函数的随机性质。
此处给出一个掩码生成函数:MGF1,基于哈希函数。MGF1和IEEE Std 1363中定义的ANSI X9.44中定义的一致。本文的未来版本会定义其它掩码生成函数。

B.2.1 MGF1
MGF1是一个基于哈希函数的掩码生成函数:
MGF1 (mgfSeed,  maskLen)
条件: Hash 哈希函数(hLen代表了哈希函数的输出字节长度)
输入: mgfSeed 生成掩码的种子,一个字节串。
maskLen 掩码的目标长度,长度最大为2^23 * hLen
输出: mask 掩码,一个长度为maskLen的字节串。
错误: “掩码太长”
步骤:
1.如果 maskLen > 2^23hLen,输出"掩码太长“并停止。
2.使得T为空字节串
3.计数器counter从0到[maskLen/hLen]-1,做如下:
a.转化计数器counter为一个长度为4的字节串C
C = I2OSP(counter, 4).
b.连接mgfSeed的哈希值和C到字节串T
T = T || Hash(mgfSeed) || C
4.输出T的前maskLen个前maskLen个字节作为mask。

对象标识符 id-mgf1 标识了MGF1 掩码生成函数:
id-mgf1    OBJECT IDENTIFIER ::= { pkcs-1 8 }

在类型AlgorithmIdentifier中与OID对应的parameters属性将是一个类型为hashAlgorithm的值,标明MGF1基于的哈希函数。

C ASN.1 模块
省略

D 知识产权问题
省略

E 修订历史
Versions 1.0 – 1.3
Version 1.4
Version 1.5
Version 2.0
Version 2.1

F 参考文献
省略

G 关于PKCS
省略

PKCS#1 v2.1 RSA Cryptography Standard (PKCS#1 RSA密码学规范,版本2.1)相关推荐

  1. 公钥密码学标准(Public Key Cryptography Standards, PKCS)

    PKCS 公钥加密标准(Public Key Cryptography Standards, PKCS),此一标准的设计与发布皆由RSA资讯安全公司( RSA Security LLC)所制定. RS ...

  2. RSA公钥格式PKCS#1,PKCS#8互转(微信获取RSA加密公钥)

    /把RSA公钥格式PKCS#1转换成PKCS#8org.bouncycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.bouncycastle.asn1 ...

  3. PHP rsa私钥pkcs8加密,Openssl rsa私钥的PKCS#1和PKCS#8格式以及加密和转化

    这里主要介绍: 私钥的PKCS#1格式,及PKCS#8格式 格式PKCS#1和PKCS#8之间的互相转化 私钥的加密,解密 PKCS#1 -> PKCS#8 生成PKCS#1私钥 $ opens ...

  4. 非对称加密算法之RSA介绍及OpenSSL中RSA常用函数使用举例

    RSA算法,在1977年由Ron Rivest.Adi Shamirh和LenAdleman,在美国的麻省理工学院开发完成.这个算法的名字,来源于三位开发者的名字.RSA已经成为公钥数据加密标准. R ...

  5. 配置 不使用rsa 密码_了解使用RSA的密码学

    配置 不使用rsa 密码 RSA is an asymmetric cryptographic algorithm that you are probably using right now to v ...

  6. RSA加密算法详解以及RSA在laravel中的应用

    最近做APP,由于刚开始开发,所以关于数据传输之间的加密部分还没做.在BOSS的要求下,准备给APP的接口加上RSA加密.先测试一个小demo. 一.使用场景 APP接口数据部分的加密.特别是设计到账 ...

  7. python实现rsa加密源代码_python实现RSA加密(解密)算法

    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. 今天只有短的RSA钥匙才可能被强力方式解破.到2008年为止,世界上还没有任何可靠 ...

  8. 基于java的rsa加密程序_RSA rsa加密程序,rsa java源码和 rsa的jsp Crypt_De algrithms 解密 238万源代码下载- www.pudn.com...

    文件名称: RSA下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 169 KB 上传时间: 2014-04-23 下载次数: 0 提 供 者: 姚双奇 详细说明: ...

  9. rsa/ecb/pkcs1padding php,PHPJAVA RSA/ECB/PKCS1Padding 加密解密

    PHP代码: $privateKeyFilePath = '-----BEGIN RSA PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwgg ...

最新文章

  1. windows 8 修改文件权限
  2. Permission denied: user=root, access=WRITE, inode=/:hadoopuser:supergroup:drwxr-xr-x
  3. swift为UIView添加extension扩展frame
  4. php study 直接显示代码_PHP获取文件大小的方法详解(附视频)
  5. Powerline专用字体安装_PowerFonts字体库安装_Meslo LG字体安装
  6. OC Swift中UITextFiled、UITextView限制输入字数
  7. [Deepin - Pycharm调试记录] Pyinstaller索引系统库问题
  8. JavaScriptCore.framework基本用法(一)
  9. Vue源码阅读一:说说vue.nextTick实现
  10. 微信公众号开发 包括服务器配置、java web项目搭建、tomcat手动发布web项目、微信开发所需的url和token验证 2017.12.2...
  11. C++::My Effective C++
  12. bug9-TypeError: ‘generator‘ object is not subscriptable
  13. 【优化算法】鲸鱼优化算法(WOA)【含Matlab源码 1243期】
  14. 软件测试的方法有哪些?
  15. (转)C#中 DirectoryEntry组件应用实例
  16. 微信小程序如何使用阿里巴巴矢量图标库彩色图标
  17. 谈谈RJ45线序的打法及口诀
  18. 计组作业【题目记录】
  19. LeetCode 21-30 题
  20. unity3d 禁用脚本

热门文章

  1. Box2D 物理引擎入门
  2. 使用 github pages, 部署静态网页
  3. PS2021要求计算机配置,原创 Photoshop 2021来了,配置要求变高,新功能升级
  4. js-xlsx实现文件导出、下载(excel)
  5. EasyUI中使用自定义的icon图标
  6. 【IT情感】社会求助,也许你也曾有过的矛盾
  7. Autojs--2019最新版蚂蚁森林能量自动收取QQ自动点赞
  8. .NetCore——基于OpenCV人脸检测
  9. Mac软件:15个提升办公效率的软件
  10. 房地产行业不良资产处置方式