接口安全:谈谈加密与签名的区别

非对称加密算法(如RSA)正确的使用方法是:

  1. 1. 公钥加密,私钥解密。
  2. 2. 私钥签名,公钥验签。

最近与三方合作伙伴对接接口安全方案,遇到一个开发同事跟我说,我们的实现方式是我方存储私钥,数据用私钥加密,公钥给三方,三方用公钥解密。我说不对,从安的角度来说,应该是公钥加密,私钥解密。他给我看示例代码,里面明明是私钥加签,公钥验签

这种的误解,不仅造成了沟通上的困难,而且可能会导致接口设计并没有达到预设的安全目的。

所以这里想专门讲一下加密与签名的区别

  • 加密:对一段明文进加密,只有用指定的密钥才能解密,防止数据被窃取,泄漏
  • 签名:对一段明文进行签名,通过指定的密钥来验证签名,防止数据被篡改

加密很容易理解,基本上不会出现误解。

通常误解出现在对签名的理解上,有很多人把签名也理解成加密(虽然本质上仍然是加密,但签名的目的不同,技术实现也有所不同),认为只要签名了,数据就不出被泄漏了,这是很大的一个误解。

划重点:签名的作用不是防泄密,而是防篡改

如何理解防篡改?给大家举个例子:

你经常给你的女朋友写信,里面有绵绵情话,有个快递员很坏,喜欢偷拆看别人的信,看完后再放回去。有一天,你发现你给女朋友写信的内容被曝光了,你意识到肯定是有人偷看了你写的信,于是你决定:

对信件内容进行加密

你采取了一套加密算法,如明文I love you,会被转化为密文:324678967702

你把解密的密钥给了女友,这样只有她能解密信件内容,这样快递员即使偷看了信,也不知道里面写的是啥。哈哈,你的目的达到了。

但是这个快递员真的很坏,他心怀不满,他说你不是不让我看你的信的内容吗?那么我就把你的信件给改了,比如,把I love you的密文:324678967702给改成1234567890,你女朋友收到信后,解密出1234567890的结果可能是:你欠我的一万块钱什么时候还。你女朋友很生气的问你,你信里都写的啥呀,莫名其妙的。你意识到,信件的内容肯定是被篡改了。你要防止别人篡改,你又有了新的想法。

对信息内容追加签名

你每次写完信,除了对信件内容进行加密外,还会用一套算法,针对信件明文生成一个签名(一般不会对明文直接签名,先会用哈希算法对明文进行摘要,然后对摘要进行加密,这个密文就叫签名),这套算法会保证:只要信件明文有任何改动,生成的签名都是不一样的。这样就做到了防篡改吗?是的,回到故事中,你的女友收到信件其实包含两个密文,一个是明文加密后的内容,我们称之为密文,一个是明文摘要加密后的内容,我们称之为签名。她收到你的信后,先要进行验签操作。即先用私钥解密密文,得到解密后的明文。那这个明文与原来的明文一致吗?他用同样的算法对收到明文做摘要,我为记为摘要2,然后再用公钥解密签名,得到摘要1,如果摘要2与摘要1相同,那么就说明信件明文或密文没有被篡改。如果两个摘要不同,那么她马上明白,密文不可信,被篡改过。即验签不通过。

这里用到的就是签名算法,这使得:

  1. 第一,任何人不能篡改内容,只要篡改了,签名就会不同,验签就会失败。
  2. 第二,不能伪造签名(中间人在篡改内容后,用自己私钥伪造一个签名),因为同样会验签失败。

而且用来做签名的密钥是一对非对称密钥,公私钥是成对的,用私钥生成的签名,只有用对应的公钥才能验签通过。(思考,为什么非要使用非对称密钥呢?用对称密钥签名不可以吗?)

这下任何人拿你的信件都没有办法了,即不能知道你信件的内容,也不能通过篡改信件来行骗或破坏你们的关系,从此你和女朋友过上了幸福美好的生活。

但是,故事就这么结束了吗?回到我们在前面提到的思考题,为什么非要使用非对称密钥来做签名呢?用对称密钥来做签名不可以吗?

先回答,再解释:可以,用对称密钥来做签名也是可以的,但是安全性不够,不方便传输关键点在于上面提到的第二点,如果中间人不仅篡改内容,而且还拿到了你的签名密钥,伪造签名怎么办?

继续讲故事,假设你和女朋友用的是对称密钥对信件进行签名(签名过程是一样的,只不过用的对称密钥),你总要把这个对称密钥告诉你的女朋友吧,或者这个密钥生成时一式两份,你和女友各执行一份。这个快递员不仅很坏,而且智商很高,他又窃听了你和你女朋友的电话,或入室盗窃,总之偷走了密钥,(唉,这个快递员确实不简单,简直TMD就是一特工),他不仅篡改了你的信,而且也篡改了你的签名,即用篡改后的内容,再生成一个签名,替换掉你原来的签名,这样篡改后的内容摘要和签名不就对应上了吗?(真是道高一尺,魔高一丈)那么我就认怂了吗?当然不能,关键在于如何保证密钥不被泄露我决定定期更换密钥,每次我都用不同的密钥与女友通信,但是你怎么将更新的密钥与女友同步呢?要知道这个快递员可是即坏又厉害呢!他可以窃听一切你和女友的通信噢。

解决方法就是非对称密钥,我可以每次都生成一个密钥对,但是我只传输公钥给女友,不传输私钥。女友也是一样,每次都生成一个密钥对,只传输公钥给我,私钥自己保留。这样我就可以:用女友给我的公钥加密信件内容,再用我自己的私钥对信件内容做签名,女友可以:用自己的私钥解密信件内容,再用我的公钥对信件内容做验签,这样即使这个坏快递员拿到了公钥,也没有什么用,他可以用公钥随意加密任何内容,发送给任何人,但因为他拿不到私钥,就无法对内容进行签名,在安全等级高的通信中,没有签名的内容是不可信的。至于非对称密钥为什么会有这种特性,涉及高等数字知识,我也说不清,有兴趣的可以自行深入研究。

至此,我们理解了:签名与加密完全是两个概念,也不是必须一起都实现才安全,要根据需求而定。例如,我传输了一个下单信息:买一杯奶茶,这个信息并不是什么机密,但是要防止被人篡改改成:买2杯可乐,所以只需要对内容做签名防篡改就可以了,并不需要加密。

为什么在使用非对称加密算法(如RSA)时,正确的使用方法是公钥加密,私钥解密。

理解了加密和签名的区别,我们再来说说非对称加密中加密的实现为什么必须是公钥加密,私钥解密才是安全的。而签名却是私钥签名,公钥验签。

在python中的rsa加密实现中,根本就不支持公钥解密。(好多java小伙伴也许会说,我们在项目中私钥加密,公钥解密,用的好好的,难道说java没考虑到安全?从存在即合理的角度看,java支持这么做一定是有应用场景的)。难道是python太low了?为什么不允许私钥加密呢?

私钥和公钥的关系,相当于钥匙和锁的关系。

私钥=钥匙,公钥=锁,私钥只有一把自己保存,而公钥锁可以复制很多把。

当要传输隐私数据时,就给对方一把锁,让对方把重要的隐私数据锁起来,传给你,然后你用私钥解锁。因为私钥在你手上,所以只有你能解锁。

而公钥之所以叫公钥,意思是可以公开给任何人。任何人拿到一把锁都是没有意义,所以对锁的定义就是不能打开钥匙,即不能用私钥加密,公钥解密(切记,我说的是加密场景下,不能用私钥加密,公钥解密,加签的场景正好相反,恰恰是私钥加密,公钥解密,不过我们通常会说成私钥加签,公钥验签)

java的小伙伴可能会这么说,我们的接口安全是这么实现的,服务端保存私钥,客户端保存公钥:

  1. 客户端请求接口时,用公钥加密,服务端收到信息用私钥解密
  2. 服务端返回的内容用私钥加密,客户端收到后,用公钥解密

这样用一对非对称密钥就可以完成整个交互的加密过程了,并不像你说的公钥可以公开给任何人,我们的公钥也是保密的,只给到指定的人或客户端。这里的第2步,其实是把公钥当私钥用了,来个了公私钥角色互换。也没有人说这么做不可以,反正只要保证“私钥”不泄漏就可以。

为了保证灵活性,所以java允许这么做,而python就要严格一点。

无论如何,我们永远要记住,私钥代表着你身份和权力,请保护好你的私钥。

说到这里,签名就好理解了,一定是私钥签名,公钥验签。毕竟私钥才能代表你的身份,你签名的文件,可以分发给任何人,也就是说任何人都需要拿到公钥来验证签名。如果反过来就不行了,任何拿到公钥的人都可以冒充你进行签名,那可是不行的。

  • 61
    点赞
  • 127
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值