在 RSASSA-PSS 和 RSASSA-PKCS1-v1_5 之间切换是不是应该注意其他参数?

Posted

技术标签:

【中文标题】在 RSASSA-PSS 和 RSASSA-PKCS1-v1_5 之间切换是不是应该注意其他参数?【英文标题】:Should switching between RSASSA-PSS and RSASSA-PKCS1-v1_5 be mindful of other parameters?在 RSASSA-PSS 和 RSASSA-PKCS1-v1_5 之间切换是否应该注意其他参数? 【发布时间】:2021-09-18 20:46:28 【问题描述】:

我不确定我应该在这里还是在 Security Stackexchange 中问这个问题。

无论如何,我最近在使用 TPM 处理 RSA 签名时遇到了一个问题,我将填充方案从 RSASSA-PKCS1-v1_5 切换到了 RSASSA-PSS。我认为这应该没什么区别,但我注意到 TSS.MSR(.NET TPM 库)中的一个示例不再起作用。我在https://github.com/microsoft/TSS.MSR/issues/109 开始了一个关于它的问题。

但我想检查一下,是否有人可以分享意见,是否需要做或注意除了更改填充方案之外的一些明显的事情?

我认为不是,这也隐含在 .NET RSA 库等参数中,例如https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rsasignaturepadding 以及如何使用它

using(var rsaKey = RSA.Create(keySizeInBits: 2048))

   byte[] message = /* Random data. */
   var sig = rsaKey.SignData(message, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);

我从https://security.stackexchange.com/questions/183179/what-is-rsa-oaep-rsa-pss-in-simple-terms、https://crypto.stackexchange.com/questions/77881/are-rsa-pss-parameters-standardized 和其他地方的问题中看到填充实际上是如何发生的更复杂。但假设它是库的一个实现细节,并且签名检查似乎不匹配或不起作用,一个结论是可能需要检查此 TSS.NET 库中的各种内部参数,例如填充。所以,因此我想确保自己这个结论是正确的,并且可能没有非常明显的东西。举个例子:不要使用 SHA-256 或将 salt size 明确设置为 nn(好吧,这可能是一个通常不应该关心的实现细节)。

附录:

这是在接受Maarten Bodewes的优秀笔记之后写的。

将散列从 SHA-256 切换到 SHA-1 并没有消除链接示例中验证签名的失败。不过,正如预期的那样,“nameSize”或摘要更改为 20 个字节。因此,如果在示例或某处的库中没有正确处理一些“挥之不去的默认值”,仅此一项(可能是部分解决方案)并不是切换到 RSASSA-PSS 填充方案失败的原因。

任务继续。 :)

【问题讨论】:

【参考方案1】:

其实padding有一些配置选项,在使用该功能时确实需要提前设置。

奇怪的是,标准中没有针对 PSS 功能描述这些“选项”。但是,它们为 PSS 填充机制列出:

Options:

  Hash     hash function (hLen denotes the length in octets of the hash
           function output)
  MGF      mask generation function
  sLen     intended length in octets of the salt

但是,这仍然没有完全配置 PSS,因为 MGF 本身就是一种算法,并且该算法也有参数。

所以最好看一下参数的 ASN.1 结构以获得一个好主意:

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

幸好只有一个Mask Generation Function:MGF1。也只指定了一个尾部字段:trailerFieldBC,所以这主要是为将来的更改指定的。

如您所见,其中有两个哈希函数,一个用于消息/输入数据本身,另一个用于掩码生成函数 (MGF)。所以散列又是 MGF1 的配置参数。该标准表明最好对消息散列和 MGF1 散列使用相同的散列函数。但是,算法可能会使用默认值,如您在结构中看到的 SHA-1。 AFAIK,Java 始终对 MGF1 使用 SHA-1,但 .NET 使用与消息哈希相同的哈希。

同样,盐长度通常设置为hLen,即哈希的输出大小。它默认为 20,但那是因为这是 SHA-1 的输出大小。零值也是一种选择,但我觉得一般留到20。

是的,很遗憾,您确实需要检查是否使用了相同的参数。一个好的库应该清楚地指定使用什么,或者至少可以选择明确地配置它们。但是,如果这是一个好的库的要求,那么存在许多不好的库。此外,您绝对不应该尝试从签名本身获取此类信息或在验证过程中猜测多种算法,因为这会将安全性降低到最不安全的算法。

最后,当您找到安全且兼容的 PSS 方案时,我建议您在代码中明确指定使用哪组参数。这可以使用显式参数来完成(即使默认值用于特定库)。如果前者不可能,您也可以在评论中指出参数。单独记录您的方案并在 cmets 中指出它不会有什么坏处。

【讨论】:

请不要向信使开枪。我是最小化配置选项的坚定支持者,这里只需一个配置选项(哈希)就足够了。 时间不够,稍后会添加对 PKCS#1 v2.2 RFC 的引用。 非常彻底,像这样的东西我希望/害怕用我粗略的知识阅读。我只是在调试github.com/microsoft/TSS.MSR/blob/master/TSS.NET/TSS.Net/… 使用 SHA-256 提供 32 字节长的“nameSize”。这反过来又被用来创建这么长的种子。我试图查看传递给 TPM 的盐值是多少,但还没有找到。现在你写了,需要检查 SHA-1 而不是 SHA-256。但首先要照顾好孩子。我稍后会回来,请接受这个。 :) 呃!我将在这里分享groups.google.com/a/chromium.org/g/chromium-reviews/c/…,其他人可以使用“tpm,RSA PSS”进行搜索。在 TPM 世界中似乎是一个陷入困境的计划。 我不完全知道“最大盐量”是什么意思。我认为这意味着它是 PKCS#1 v2.2 标准中emLen 的最大长度。但是,我完全同意“Gerrit”的评论:“PSS 确实是为什么过度参数化你的算法是一个糟糕的想法的典型代表!”

以上是关于在 RSASSA-PSS 和 RSASSA-PKCS1-v1_5 之间切换是不是应该注意其他参数?的主要内容,如果未能解决你的问题,请参考以下文章

Bouncycastle和PKCS#1 v2.1,使用RSASSA-PSS进行签名并使用带有RSAES-OAEP的AES CBC进行加密

window和 linux 在一起 ios和 android在一起 net和js在一起

当@objc和@nonobjc在swift中写在方法和变量之前?

当@objc和@nonobjc在swift中写在方法和变量之前?

and和or的用法和区别

在javafx中设置舞台和场景的高度和宽度