十年老IT知识分享 – 非对称密钥沉思系列(2):聊聊RSA与数字签名

先简单回顾下MAC

在前面的文章《消息验证码MAC入门指南》中,我们围绕消息验证码的工作原理进行了一些分析和实验。

在对消息进行MAC计算时,无论是使用HMAC亦或是CBC-MAC,它们都是基于“Encrypt-Then-MAC”的机制,其工程上的含义为:对明文加密生成密文,然后对密文进行MAC计算。

在现有的许多工程实践上,其实还存在另外两种MAC生成方式:

  • MAC-Then-Encrypt
    这种方式的使用,是先对明文进行MAC生成,然后将明文和MAC值一起进行加密,这种方式在早期的TLS中应用比较多。
  • Encrypt-And-MAC
    这种方式,也是首先对明文计算MAC值,只不过,在发送数据时,MAC值一直是保持明文的,明文的MAC值和对明文加密后的密文将会一起发送。早期的Secure Shell中就使用了这种方式。

这里多说一句,在针对消息不可篡改的使用目的上,工程学上其实更推荐“Encrypt-Then-MAC”的方式,本文不过多讨论关于这种方式安全性的算法论证,但是有一点是比较值得强调的,那就是,密码学领域的许多大佬专家都更倾向于认为,“Encrypt-Then-MAC”在避免直接修改密文的攻击手法上,效果会更好。

当然,在兼具不可篡改与保密性的加密选择上,AEAD(Authenticated Encryption With Additional Data)的方式是更值得推荐的,这一块后面有时间我们展开细聊,这篇文章先不过多探讨。

但是,无论MAC在算法实现上多么的优雅,MAC始终有一个很致命的问题,就是它需要共享密钥!

使用共享密钥意味着,一旦密钥泄露,数据的安全性将会极大的降低。

从MAC过渡到数字签名

相同的目的

与MAC的目的一样,数字签名的目的,其实也是为了验证消息来源真实性与消息不可篡改性。

消息来源真实性,在MAC中指的是,只有具有这把共享密钥的人,才可以验证通过。

消息不可篡改性,在MAC中指的是,一旦这个消息被篡改过,那么即使使用的是同一把共享密钥,最后计算出来的结果也一定具有可显式分辨的差异性。

回顾下非对称密钥的特性

在前面的文章《非对称密钥沉思系列(1):RSA专题之PKCSv1.5填充模式下的选择性密文攻击概述》中,我们探讨了非对称秘钥的一些特性,这里总结几个比较重要的性质:

  • 非对称加密总是以密钥对的形式出现,而在对称加密中总是共享一般密钥。
  • 公钥和私钥,总是一个加密,另一个解密,互为对立面。
  • 在RSA中,公钥可以从私钥派生出来,而反过来不行。
  • 私钥应该总是保持为私有,永远不能公开。
  • 公钥应该允许广泛传播,允许被任何人持有。

总的来说,任何人都可以使用密钥对中的公钥进行消息加密,同时密文总是可以被密钥对中的私钥进行解密。

也就是说,生成密文消息的人,总是知道,只有拥有私钥的人才可以解密。

如果使用私钥加密呢?

私钥是可以加密的,也就是说,加密的方向,是可以反过来的。

并且,使用使用私钥加密的消息,也只有公钥能够解密,算法上这是没有问题的。

但是,这种加密方式,在工程上有什么意义呢???

前面我们提到了,公钥其实可以被任何持有,也就是说,任何持有公钥的人,都能解密由私钥加密的数据,这样对数据来说,其实其保密性相当于为零!!!

但是,想想对称密钥场景下,密文能被解密,则说明,解密者必定是持有共享密钥的那个人;

同样的道理,如果持有公钥的人可以解密被私钥加密的数据,那么说明,发送私钥加密密文的人,一定是持有私钥的人!!

也就是说:

如果你得到一条可以用你的公钥解密的消息,那么你一定能确定这条消息来自于对应的私钥持有者,因为其他任何人都不能加密它。

非对称加密的效率问题

这里其实就是要强调,非对称加解密是一个很慢的过程。

相比较于对称加密解密,非对称加解密的过程是一种相当低效的过程。

也就是说,在使用非对称加解密能力时,最好不要在数据量比较大的场景下使用。

诶???

这个时候有没有想到什么???

既然不能对原始大数据做加解密,那么,能否直接怼数据的哈希做加解密呢??

要记住,此时我们做加解密的目的,已经不是保密性,而是为了证明来源的真实性!!

RSA数字签名的基本思想

RSA数字签名,基本可以概括为以下几个步骤:

  • 首先对数据进行哈希计算,得到原始数据的哈希值。
  • 使用私钥对哈希值加密,此时得到的密文就是原始数据的签名。
  • 将哈希密文与原始数据一起发送。
  • 接收方接收到原始明文与哈希密文后,对原始明文同样计算哈希值,并使用公钥对哈希密文解密,对比两个哈希值是否一致,这个过程也叫做验签。

这里有必要再次强调,RSA的公钥加密与私钥加密,适用于不同的用途:

  • 公钥加密,可以对消息保密,只有私钥所有者才能解密它
  • 私钥加密,可以验证消息来源真实性,因为只有私钥持有者才能生成这个消息

在RSA工程化时间上,一般都建议:

  • 使用RSA进行加密时,推荐使用OAEP的填充方式。
  • 使用RSA进行签名时,推荐使用PSS的填充方式。
  • PSS填充时,其掩码生成函数,有且仅有一个,那就是MGF1。

数字签名实践的决策点:先加密再签名 还是 先签名在加密?

在MAC的场景下,我们强调过,建议使用“Encrypt-Then-MAC”的方式,那么在RSA的签名场景下,我们是否也应该推荐先加密再签名的方式呢??

这里笔者的结论是,不建议使用先对称加密再签名的方式,而是应该先对明文签名,再对明文和签名做对称加密

在做数字签名时,消息的完整性已经不仅仅是其目的,更重要的是,我们需要验证消息来源的真实性,也就是验证发送方的身份。

MAC场景下,其共享密钥,理论上只会被两方共享,持有第三方密钥的人无法替换由真实共享密钥生成的MAC值;

而在RSA数字签名的场景下,用于创建数字签名的私钥是不被共享的,而公钥确实公开且可以被任何人持有的;

公钥只能验签,但是不能伪造签名,先签名,后加密,可以保护签名人,因为在签名之后又做了一层加密,即使第三方截获了这段消息,也没办法知道是谁发送的。

而如果先加密,后签名,则这段消息如果被第三方拦截后,其可以修改这段密文并重新生成签名,此时虽然签名用的私钥变换了,但如果第三方的公钥同样也被接收者合法采用,则接收者在验签时是有概率认为签名成功的,且此时,接收者很可能会误以为发送者来自于第三方。

正文完