原文网址:加密和签名的区别及应用场景_IT利刃出鞘的博客-CSDN博客
简介
本文介绍加密和签名的区别及应用场景。
RSA是一种非对称加密算法, 可生成一对密钥(私钥和公钥)。(RSA可以同时支持加密和签名)。
加密和签名的区别
加密
用公钥对明文加密,用对应的私钥才能解密,防止明文被人看到。
签名
用私钥对明文签名,用对应的公钥验签(验证签名),防止数据被篡改。
加密流程
(友情提醒,以下场景仅为说明基本的加密流程,不符合真实应用)。
自从潘金莲放窗帘打到西门庆的头之后,他们就开始秘密交往,潘金莲的丈夫武大郎总是怀疑他们俩在偷情,苦于没有证据,在暗地里观察。
一天,潘金莲想写情书撩西门庆,但是情书内容不想被武大郎知道,于是潘金莲就告诉西门庆,采用 RSA 加密的方式来传递书信。
于是,西门庆就用 RSA 生成了一对密钥(一个公钥,一个私钥),将公钥的内容写成一封信,然后寄出去送给潘金莲。
武大郎观察到了西门庆发出的信件,偷偷地将这封信件拦截了下来并复制了一份自己藏着,然后又将信件原路寄给潘金莲,以免打草惊蛇,以为这样就可以神不知鬼不觉地拿到他们之间偷情的证据。武大郎打开信封,发现里面写的只是公钥内容。
信封(公钥)传达到潘金莲手上后,潘金莲就开始写情书了:“巴拉巴拉各种虎狼之词”(明文)。写好后装入信封想直接寄回给西门庆,但是马上停住了,心想,这封信如果这样直接寄出去,中途被武大郎拦截的话,不就什么都被看到了吗?于是潘金莲用西门庆发过来的公钥对自己写的情书进行加密,生成了一份完全看不懂的信息“eSYJztu3RqGZBcRPvINyg2Hpmu…”(密文)。然后这封信可以放心的寄给西门庆了。
果然,武大郎偷偷观察到了潘金莲发出的信件,又进行同样的操作:拦截,复制,原路寄回给西门庆。当武大郎打开复制回来的信件(密文)后,发现又是一堆看不懂的信息,然后尝试用之前从西门庆那封信复制下来的公钥进行各种 RSA 操作(用公钥加密,解密),结果发现无论怎么操作,得到的都是看不懂的信息。单凭这封全是乱码的信件并不能坐实潘金莲与西门庆偷情。
信封(密文)最终传达到西门庆手上,西门庆拿着自己的密钥(密钥只有自己知道,其他人都不知道),对信封进行解密,于是看到了信封原来的内容:“巴拉巴拉各种虎狼之词,…”西门庆被撩得心花怒放。
结论
以上是使用 RSA 进行加密解密的一个虚拟场景。可见,加密后消息的传递是单向的,只有潘金莲发加密消息给西门庆,西门庆没法直接发有效的加密消息给潘金莲(因为潘金莲没有私钥)。除非双方都各自生成自己得 RSA 公钥私钥,并且互相发送各自的公钥给对方,这样双方就可以加密通讯了。
整个通讯流程(单向)
- A 明文告诉 B,我现在要发送消息给你,请使用 RSA 进行加解密(这条消息会被 C 截获,C 知道了 AB 之间要通讯并使用 RSA 加密)。
- B 生成一对密钥(公钥,私钥),然后将公钥发送给 A(这个公钥会被 C 截获,但是 C 拿不到私钥)。
- A 把要发送的消息用公钥进行 RSA 加密,得到密文,然后发送给 B(这个密文被 C 截获,但 C 无法知道密文所对应的明文的内容,因为 C 只截获到公钥,没有私钥,用公钥对密文怎么操作都得不到明文)。
- B 拿到密文后,使用自己的私钥解密,得到明文。
B如果想发加密的消息给A,则将以上流程反着来走一遍就行了,只不过就需要由A来生成密钥(公钥,私钥)。
也就是说:
- A想给B发加密消息,由B来生成密钥对(公钥B,私钥B),对外公布公钥B。
- B想给A发加密消息,由A来生成密钥对(公钥A,私钥A),对外公布公钥A。
签名流程
西门庆想给潘金莲写信,告诉她"午时去王婆家做衣服"。潘金莲要如何才能确信这条消息真的是西门庆发给她的呢?万一这条消息是哪个泼皮乱发的,那潘金莲岂不是白跑一趟?
RSA 算法有一组对称操作:用公钥加密的密文,用私钥解密可以得到明文;反过来,用私钥加密的密文,用公钥解密也可以得到明文。
潘金莲手上是有西门庆的公钥的(延续上一场景的公钥),如果西门庆用私钥对消息进行加密,潘金莲用公钥进行解密,如果解密后能得到明文,那就能说明:发送者确实是西门庆本人。因为除了西门庆外,没有人拥有私钥,能用这个公钥解密的密文一定是密钥的持有者(即西门庆)所发出的。
于是,西门庆写了一条消息“午时去王婆家做衣服”(明文),然后用私钥将这条消息加密生成了“PvINeSYJuZBcRygztu3Gpm2HRq…”(密文)一共两条消息(一条明文一条密文)合并写在一封信里寄给了潘金莲。
潘金莲收到信后,用公钥对信件的密文部分“PvINeSYJuZBcRygztu3Gpm2HRq…”进行 RSA 解密,得到“午时去王婆家做衣服”。然后和信件前面部分里对比,发现内容一模一样,这就确认了消息确实是西门庆发的。
说明
西门庆用私钥对前面明文内容加密,然后追加到明文后面的这种做法,就是签名。
潘金莲用公钥对签名解密,并与前面明文部分进行比对,这个做法就叫做验签。
为什么可以这么做?不怕被武大郎中途截获修改吗?不怕。因为如果武大郎中途截获了这封信,并修改成“申时去王婆家喝茶”但由于武大郎没有私钥,无法对明文加密,因此无法修改后面的签名部分。当潘金莲收到信件后,用公钥解密签名部分得到的内容,跟被篡改的明文内容一对比,发现不一致,就说明消息被篡改了,发送者并不是西门庆。
又或者武大郎用自己的私钥对篡改后的明文进行加密签名,再发送给潘金莲,潘金莲用手上西门庆的公钥根本无法解密武大郎篡改后的加密部分,这种情况也可以确定发送者不是西门庆。
从这里可以看出,加密和签名,这两种场景是不一样的。
- 加密,是为了确保通讯内容不被第三方知道。
- 签名,是为了确保发送者确实是本人,并且消息没有被篡改过。
在加密场景下,并不关心消息是否被篡改过。可能武大郎第一次截获西门庆公钥时,偷偷换成了自己生成的公钥,并发给潘金莲。潘金莲用公钥加密后发出的情书被武大郎截获之后,武大郎用自己的私钥也是可以解密出来那些虎狼之词的(中间人攻击),但是加密场景并没有解决这些问题,加密仅是为了不让私钥持有者以外的第三方知道消息的内容。
在签名场景下,只关心消息没有被篡改,并不关心内容是否保密。比如“午时去王婆家做衣服”就是明文传输,任何人都知道这个信息。签名场景并不负责保密内容,仅仅是为了说明这条消息是西门庆本人发出的,并且没有被篡改过。
项目场景
公钥之所以叫公钥,意思是可以公开给任何人。任何人拿到一把锁都是没有意义,所以对锁的定义就是不能打开钥匙,即不能用私钥加密,公钥解密(切记,我说的是加密场景不能用私钥加密,公钥解密,加签的场景正好相反,恰恰是私钥加密,公钥解密,不过我们通常会说成私钥加签,公钥验签)。
验签
实际项目中,一般使用明文的哈希值来进行验签。
数字签名属于非对称加密,非对称加密依赖于复杂的数学运算,包括大数乘法、大数模等等,如果数据量大,那么计算数字签名将会比较耗时。所以先将原数据进行 Hash 运算,得到的 Hash 值就叫做摘要,然后对摘要计算签名。不同的内容计算出的摘要是不同的。
摘要最好是不可逆转的,这样即使第三方使用公钥解签出摘要,也无法根据摘要反推出原本的数据。一般使用 MD5 作为 Hash 函数,MD5 输出的结果固定为 128 位。
流程
发送者A用私钥对摘要计算签名,将明文和摘要的签名发给B。接受者 B 收到后,拿签名部分,用 B 的公钥解密,可以解密成功(得到摘要1),就能证明确实是 B 发的。再对邮件内容(明文)使用相同的散列函数计算出摘要2,与之前得到的摘要1进行对比,两者一致就说明信息未被篡改。
Java和Python不同
java的小伙伴可能会这么说:服务端保存私钥,客户端保存公钥:
- 客户端请求接口时,用公钥加密,服务端收到信息用私钥解密
- 服务端返回的内容用私钥加密,客户端收到后,用公钥解密
这样用一对非对称密钥就可以完成整个交互的加密过程了,并不像你说的公钥可以公开给任何人,我们的公钥也是保密的,只给到指定的人或客户端。这里的第2步,其实是把公钥当私钥用了,来个了公私钥角色互换。也没有人说这么做不可以,反正只要保证“私钥”不泄漏就可以。
为了保证灵活性,所以java允许这么做,而python就要严格一点。
项目应用
电子邮件
这里不是指的落款,而是对电子邮件进行数字签名,以保证电子邮件传输中的机密性、完整性和不可否认性,确保电子邮件通信各方身份的真实性。
软件下载
在网络上下载软件,我们如何判断所下载的为原软件,而不是被篡改后的软件呢?这里就可以利用到数字签名,软件作者可以对软件加上数字签名,用户在软件下载之后验证数字签名,看签名是否一致,就可以识别出软件是否遭到篡改。
SSL/TLS
SSL/TLS:客户端在认证服务器身份是否合法时,会使用服务器证书,它就是加上了数字签名的服务器公钥。相对地,服务器为了对客户端(用户)进行认证也会使用客户端证书。