在前面的文章《消息验证码MAC入门指南》中,我们围绕消息验证码的工作原理进行了一些分析和实验。
在对消息进行MAC计算时,无论是使用HMAC亦或是CBC-MAC,它们都是基于"Encrypt-Then-MAC"的机制,其工程上的含义为:对明文加密生成密文,然后对密文进行MAC计算。
在现有的许多工程实践上,其实还存在另外两种MAC生成方式:
这里多说一句,在针对消息不可篡改的使用目的上,工程学上其实更推荐"Encrypt-Then-MAC"的方式,本文不过多讨论关于这种方式安全性的算法论证,但是有一点是比较值得强调的,那就是,密码学领域的许多大佬专家都更倾向于认为,"Encrypt-Then-MAC"在避免直接修改密文的攻击手法上,效果会更好。
当然,在兼具不可篡改与保密性的加密选择上,AEAD(Authenticated Encryption With Additional Data)的方式是更值得推荐的,这一块后面有时间我们展开细聊,这篇文章先不过多探讨。
但是,无论MAC在算法实现上多么的优雅,MAC始终有一个很致命的问题,就是它需要共享密钥!
使用共享密钥意味着,一旦密钥泄露,数据的安全性将会极大的降低。
与MAC的目的一样,数字签名的目的,其实也是为了验证消息来源真实性与消息不可篡改性。
消息来源真实性,在MAC中指的是,只有具有这把共享密钥的人,才可以验证通过。
消息不可篡改性,在MAC中指的是,一旦这个消息被篡改过,那么即使使用的是同一把共享密钥,最后计算出来的结果也一定具有可显式分辨的差异性。
在前面的文章《非对称密钥沉思系列(1):RSA专题之PKCSv1.5填充模式下的选择性密文攻击概述》中,我们探讨了非对称秘钥的一些特性,这里总结几个比较重要的性质:
总的来说,任何人都可以使用密钥对中的公钥进行消息加密,同时密文总是可以被密钥对中的私钥进行解密。
也就是说,生成密文消息的人,总是知道,只有拥有私钥的人才可以解密。
私钥是可以加密的,也就是说,加密的方向,是可以反过来的。
并且,使用使用私钥加密的消息,也只有公钥能够解密,算法上这是没有问题的。
但是,这种加密方式,在工程上有什么意义呢???
前面我们提到了,公钥其实可以被任何持有,也就是说,任何持有公钥的人,都能解密由私钥加密的数据,这样对数据来说,其实其保密性相当于为零!!!
但是,想想对称密钥场景下,密文能被解密,则说明,解密者必定是持有共享密钥的那个人;
同样的道理,如果持有公钥的人可以解密被私钥加密的数据,那么说明,发送私钥加密密文的人,一定是持有私钥的人!!
也就是说:
如果你得到一条可以用你的公钥解密的消息,那么你一定能确定这条消息来自于对应的私钥持有者,因为其他任何人都不能加密它。
这里其实就是要强调,非对称加解密是一个很慢的过程。
相比较于对称加密解密,非对称加解密的过程是一种相当低效的过程。
也就是说,在使用非对称加解密能力时,最好不要在数据量比较大的场景下使用。
诶???
这个时候有没有想到什么???
既然不能对原始大数据做加解密,那么,能否直接怼数据的哈希做加解密呢??
要记住,此时我们做加解密的目的,已经不是保密性,而是为了证明来源的真实性!!
RSA数字签名,基本可以概括为以下几个步骤:
这里有必要再次强调,RSA的公钥加密与私钥加密,适用于不同的用途:
在RSA工程化时间上,一般都建议:
在MAC的场景下,我们强调过,建议使用"Encrypt-Then-MAC"的方式,那么在RSA的签名场景下,我们是否也应该推荐先加密再签名的方式呢??
这里笔者的结论是,不建议使用先对称加密再签名的方式,而是应该先对明文签名,再对明文和签名做对称加密。
在做数字签名时,消息的完整性已经不仅仅是其目的,更重要的是,我们需要验证消息来源的真实性,也就是验证发送方的身份。
MAC场景下,其共享密钥,理论上只会被两方共享,持有第三方密钥的人无法替换由真实共享密钥生成的MAC值;
而在RSA数字签名的场景下,用于创建数字签名的私钥是不被共享的,而公钥确实公开且可以被任何人持有的;
公钥只能验签,但是不能伪造签名,先签名,后加密,可以保护签名人,因为在签名之后又做了一层加密,即使第三方截获了这段消息,也没办法知道是谁发送的。
而如果先加密,后签名,则这段消息如果被第三方拦截后,其可以修改这段密文并重新生成签名,此时虽然签名用的私钥变换了,但如果第三方的公钥同样也被接收者合法采用,则接收者在验签时是有概率认为签名成功的,且此时,接收者很可能会误以为发送者来自于第三方。