2011-04-07 135 views
3

为RSA_sign的手册页()NID_sha和NID_sha1之间的区别说,有关的类型参数:请告诉我OpenSSL中

type denotes the message digest algorithm that was used to generate m. It usually is one of NID_sha1, NID_ripemd160 and NID_md5; see objects(3) for details. 

但我可以看到另一种类型是NID_sha在OpenSSL源代码。 有人可以帮我解决这两者之间的区别吗?

我打算使用RSA_Sign函数来签署一个SHA-256,SHA-512的摘要,但我没有看到SHA-256和SHA-512的相应类型参数,所以我应该输入什么类型参数这些情况。

现在我使用的类型为NID_sha并尝试签署SHA-256,SHA-512的散列,并且它为它成功运行提供了一个合适的签名,后来的签名验证也是正确的,但我只是想知道什么是NID_sha?

任何帮助将不胜感激。 谢谢!

回答

11

NID_sha指定SHA-0,SHA-1的直接祖先。 SHA-0最初被称为“SHA”,但很快发布了一个名为SHA-1的修改版本;之前的“SHA”被宣布已经过时,现在传统上被称为“SHA-0”。这种改变的真正原因并不是官方的,但人们普遍认为SHA-0有某种弱点 - 这在几年后由独立研究人员发现,并用于产生碰撞。因此,SHA-0是“破碎的”(远远超过SHA-1),你不应该使用它。

对于使用SHA-256进行RSA签名,您应该使用NID_sha256(对于SHA-512,NID_sha512)。如果您使用NID_sha,那么您将得到一个错误的签名。在内部,签名过程包括一个变换,其中散列值(m/m_len参数到RSA_sign())填充了标识散列函数的标头(这就是为什么RSA_sign()必须有权访问此信息,通过它的type参数)。如果你使用NID_sha那么这个头就会说“这是一个长度为32字节的SHA-0散列值”,这是双重错误的:SHA-0散列值的长度是20字节,而不是32;这不是SHA-0散列值,而是SHA-256散列值。

因此,您的签名者基本上会生成一个与官方RSA签名标准(PKCS#1)不同的签名。所以你的签名将不能用兼容的验证器验证。但是,验证者也是也与标准不同,方法相同:使用NID_sha作为RSA_verify()的参数,指示验证者期望“SHA-0”标头(以及32字节散列值)。这就解释了为什么事情似乎与你的代码一起工作:你的验证者与你的签名者完全相同的错误,并且这两个错误被取消。

换句话说,你并没有签署真正的RSA,而是一个变种,乍看起来,它不是真正的安全,但仍然不同,因此不能互操作。也许在你的具体情况下这不是问题,但是一般来说,对于加密操作,你应该坚持标准的字母(因为安全弱点是微妙的事情)。如果您在签署SHA-256哈希值时使用NID_sha256,那么您将获得符合标准的PKCS#1 v1.5 RSA签名,这会更好。

综上所述:忘记NID_sha,使用NID_sha256如果散列值来自SHA-256(NID_sha512为SHA-512),两者都为RSA_sign()RSA_verify()

+0

非常感谢!非常牛眼的答案。 – sunnyX 2011-04-08 09:41:41

+2

你已经忘了打牛眼接受按钮,sunnyX ... – 2013-11-22 10:48:17