我了解RSA算法如何用于加密和解密目的,但是我不了解签名的完成方式。 />
如果我有要签名的消息,则不对消息本身进行签名,而是创建一个哈希值,然后使用我的私钥对该哈希值进行签名。
签名得到附加到邮件上的邮件,都将被转移到收件人。
收件人重新计算邮件的哈希值,然后使用我的公共密钥来验证他收到的签名。

以下是问题:


为什么通常创建消息的哈希值并签名而不是直接对消息签名呢?头:如果公用密钥似乎足以重新创建签名,接收者如何验证我拥有私有密钥?


评论

私钥是唯一可以生成可以由相应公钥验证的签名的密钥。然后,问题就变成了如何信任公钥,即为私钥生成的公钥。答案就是密钥管理。最常用的密钥管理方案是使用X509证书的PKI。

我个人认为,在签名中使用散列是用户理解可能已经避免的方案的概念性负担。 (他必须了解有关散列的知识。)因此,我在不使用散列的情况下使用RSA编写了签名方案。见例s13.zetaboards.com/Crypto/topic/7234475/1/中的4。

用于调试RSA Sign验证的在线工具8gwifi.org/rsasignverifyfunctions.jsp

RSA应该使用RSA-FDH或OAEP来确保安全。

#1 楼


为什么通常创建消息的哈希值并签名而不是直接对消息签名呢?模量大小。这意味着,如果您具有2048位RSA密钥,则将无法直接对任何长度超过256个字节的消息进行签名(而且由于缺少填充,即使那样也会出现问题)。相比之下,加密哈希可以接收任意长的消息,然后将其“压缩”为短字符串,这样我们就无法找到两个哈希值相同的消息。因此,对散列进行签名与对原始消息进行签名一样好。没有长度限制,如果我们不使用散列,我们将拥有该长度。


是什么使您认为公钥足以重新创建签名?验证给定的签名就足够了,但是生成新的签名是不够的(或者,我们希望如此;如果不正确,则表示签名方案已损坏)。

如果正在使用RSA,签名验证过程将(有效)检查是否:

$ S ^ e = \ operatorname {Pad}(\ operatorname {Hash}(M))\ pmod N $

定义:$ S $是签名; $ M $是消息; $ e $和$ N $是公用指数和公用密钥的模数; $ \ pmod N $表示以$ N $取模。 $ \ operatorname {Pad} $是填充函数; $ \ operatorname {Hash} $是哈希函数。请注意,我说“有效”是因为有时填充方法是非确定性的。这会使检查稍有不同,但对于本次讨论而言并不重要。

现在,如果我们试图伪造消息$ M'$(仅使用公共密钥)的签名,我们当然可以计算出$ P'= \ operatorname {Pad}(\ operatorname {Hash}(M'))$ ;但是,我们需要找到一个值$ S'$,其值如下:

$ S'^ e = P'\ pmod N $

$是RSA模数,我们不知道该怎么做。

私钥持有者可以这样做,因为他的值$ d $具有以下属性:

$(x ^ e)^ d = x \ pmod N $

对于所有$ x $。这意味着:

$(P')^ d =(S'^ e)^ d = S'\ pmod N $

是签名。

现在,如果我们只有公共密钥,我们将不知道$ d $;获得该值等效于分解$ N $,而我们不能这样做。私钥的持有者知道$ d $,因为他知道$ N $的因式分解。

评论


$ \ begingroup $
@ rubo77:如果您知道$ N $的因式分解,则可以。如果您不这样做,那将是个难题(实际上,这被称为RSA问题)。
$ \ endgroup $
–雨披
2014年8月15日13:44

$ \ begingroup $
@ rubo77:这不仅是计算P的e的根,然后取N为模。相反,您正在尝试查找值X,使得$ X ^ e \ bmod N = P $。
$ \ endgroup $
–雨披
2014年8月16日下午3:19

$ \ begingroup $
啊,我很明白:您应该在解释中加上$(mod \ N)$和方括号,表示“原始根模N”。这并不意味着:“取模N”,取模或余数运算符(计算起来很简单)。那就是我不知道的,所以我的第一个问题是“什么应该如此困难?”来了
$ \ endgroup $
–rubo77
2014年8月16日在6:25



$ \ begingroup $
@ rubo77:我不知道RSA的原始根源是什么。首先,没有以$ N $为模的原始根;也就是说,没有值$ g $,其中$ g ^ i \ bmod N $具有相对于$ N $质数的所有值(假设$ N $是两个不同的奇质数的乘积)
$ \ endgroup $
–雨披
16 Jul 27 '15:06



$ \ begingroup $
@Krumelur用私钥加密的消息只能用公共密钥(用于身份验证)解密,而用公钥加密的消息只能用私钥(用于加密)解密。
$ \ endgroup $
–sdfqwerqaz1
16年11月24日在13:33

#2 楼


这是重要的部分,这就是我真正开始挠头的地方:如果公用密钥似乎足以重新创建签名,那么收件人如何验证我拥有私有密钥?
您可以使用public keysignature进行“加密”(或“解密”,与“教科书” RSA中的相同)并获得hashed message。如果hashed message等于散列的message,那么您验证了message是否正确签名。聚苯乙烯对于“教科书” RSA,我的意思是https://www.cs.cornell.edu/courses/cs5430/2015sp/notes/rsa_sign_vs_dec.php

#3 楼


RSA签名验证如何工作?

在A和B之间的未加密通信中,RSA签名(不使用散列函数)只是用发送者的私钥$ d $(而不是像通常的加密通信中那样$ e):$ c \ equiv m ^ d \ pmod n $使接收者可以通过使用公钥$ e $“解密”消息并将结果与​​未加密消息进行比较来验证消息m \ equiv c ^ e \ pmod n $。
此过程应确保通信的完整性,因为接收方(如果消息与“解密的”签名匹配)可以确保消息有效,因为只有发送方才可以能够使用加密指数$ e $计算“可解密”的签名。

为什么通常创建消息的哈希并签名
而不是直接对消息签名?
/>
在某些情况下可以伪造或欺骗RSA签名,如以下演示所示:

A和B是通配符在未加密的频道上发送信息,攻击者E便可以捕获他们的消息$ m $。但是,它们将RSA签名$ c $与每个软件包一起发送,因此将过滤E发送的伪造消息。假定A发送带有签名$ c_ {1,2}的消息$ m_1 $和$ m_2 $ equiv m_ {1,2} ^ d \ pmod n $并E捕获它们。
E现在能够为消息$ m_x $生成有效签名,其中$ m_x = m_1 \ cdot m_2 $必须为真。在没有私钥$ d $的情况下这是可行的,因为可以通过将$ m_1 $和$ m_2 $的签名相乘来计算$ m_x $的签名$ c_x $:
$$ m_1 ^ dm_2 ^ d \ equiv(m_1 \ cdot m_2)^ d \ equiv m_x ^ d \ equiv c_x \ pmod n $$。
由于RSA /模块的同构性,这是可能的:$$(m_1 \ cdot m_2)\ bmod n =(((m_1 \ bmod n \ cdot m_2 \ bmod n)\ bmod n)$$
简单地讲,同态意味着$ f(xy)= f(x)\ cdot f(y)$。
因此,E可以向B发送一条消息,该消息将通过完整性和真实性测试,可能会导致错误或引起混乱。但是,E无法更改$ m_x $的内容,因为$ m_x = c_x ^ e $必须保持为真。通常在数字签名生成中使用,另外@poncho的答案也很重要。 .org / wiki / Homomorphic_encryption
https://en.wikipedia.org/wiki/Module_homomorphism