我目前正在使用pyPkcs11来签名文件。
以下调用适用于使用RSA和sha256
对公共文件进行签名session.sign(privKey, toSign, Mechanism(CKM_SHA256_RSA_PKCS, None)
但是我的一些文件已经被散列(sha256),并且签名需要提供与此openSSL命令相同的输出:
openssl pkeyutl -sign -pkeyopt digest:sha256 -in <inFilePath> -inkey <keyPath> -out <outFilePath>
我尝试过以下调用,它不会在签名之前生成文件的哈希值,
session.sign(privKey, toSign, Mechanism(CKM_RSA_PKCS, None)
但结果不是我预期的结果,并且根据这篇文章的第一个答案CKM_RSA_PKCS vs CKM_RSA_X_509 mechanisms in PKCS#11,
另一方面,CKM_RSA_PKCS也执行PKCS#1标准中定义的填充。此填充在EMSA-PKCS1-v1_5中定义,步骤3,4和5.这意味着此机制应仅接受比模数大小短11个字节的消息。要创建有效的RSASSA-PKCS1-v1_5签名,您需要自己执行EMSA-PKCS1-v1_5的步骤1和步骤。
经过一些研究后,我的文件似乎包含RFC 3447描述的签名的第一步,因此缺少的部分是第二步,其中生成了ASN.1值。
我可以使用pkcs11强制执行此操作吗?
PKCS#11 documentation似乎不包含任何有关它的信息。
答案 0 :(得分:7)
我看到两种方法可以做到这一点;适当的一个取决于令牌(并非所有令牌/包装器都执行所有机制)。
正如本other answer中所述,您可以将您开始的32位八位字节SHA-256装饰成一个完整的填充消息代表。基本上,如PKCS#1中所述,如果RSA密钥是 k 八位字节(我假设 k ≥51+ 11 = 62个八位字节,那就是公共模数至少8⋅62-7= 489位,这是安全必须的),你
30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20产生一个51个八位字节的字符串,它实际上是散列类型和值的ASN.1 DER编码
DigestInfo ::= SEQUENCE { digestAlgorithm DigestAlgorithm, digest OCTET STRING }
FF
)
00 01 FF FF FF FF..FF FF FF FF 00产生 k -octet字符串
或者,或者:按[1.]执行;跳过[2.];并在[3.]中使用机制 CKM_RSA_PKCS (长度为51个八位字节)。
免责声明:我没有检查,最近没有使用PKCS#11设备。
注意:虽然没有针对其正确实现的已知攻击,但使用PKCS#1 v1.5签名填充越来越不满意了;例如French authorities recommend
RecomSignAsym-1。 Ilestcomndmandéd'considedesmécanismesdesignatureasymétriquedisposdd'une preuvedesécurité。
或者,用英语:
建议使用具有安全性证明的非对称签名机制
他们提到了RSA-SSA-PSS( sic )。作为奖励,PKCS#11实现的机制是 CKM_RSA_PKCS_PSS ,它接受哈希,而不是要签名的数据,这使得所要求的内容变得微不足道。
答案 1 :(得分:2)
我担心,没有PKCS#11功能,它可以做你想要的。
我所知道的唯一解决方案是,手动将PKCS#1 v1.5填充应用于哈希,然后使用 CKM_RSA_X_509 (原始或教科书RSA)机制对块进行签名