base64报文怎么解密_接口通讯加解密设计小白文

647b3d912f10512863cb33ae8a00b25d.png

对于一套标准化的接口通讯加解密流程,开发测试结束、线上运行正常以后便无人问津,这实在可惜。

本文的目的是让初级开发、产品同学更快的了解一下应用接口层的安全设计是如何做的,带领大家领略一下其中所蕴含的巧妙思想。所以这只是一片入门级别的小白文,也就是:相当基础。

0. 常用加密算法扫盲

非对称性加密算法常用的有:RSA等。有两个密钥,一个加密,另一个解密。

对称性加密算法:DES,3DES,AES等。一个密钥,用同一个密钥来加解密。

摘要算法:MD5,SHA-256等。摘要算法是单向加密,无法解密,一般用于确认消息的完整性。

1. 非对称性算法的特征

最初印象

最初印象就两个

  1. 有公钥、私钥,两个秘钥(偶尔听到开发同学提起过);
  2. 更安全(别问我为什么,问我就说公认的,大家都知道);

总之,大家都在用它!

特征

看过道听途说的印象以后,再来看看它的特征。

不用过于纠结为什么,当做数学定律先记住就行(不看也行,直接跳到场景一)。

  1. 公钥和私钥是成对出现的,一个用来加密,另外一个用来解密;
  2. 公钥私钥都能够用来加密或者解密。比如,可以公钥加密,私钥解密;也可以私钥加密,公钥解密;
  3. 我们通常把一个秘钥提供给对方,自己保管一个。然后各自用自己保管的秘钥做加密或者解密;
  4. 公钥和私钥的地位是不对等的,私钥包含了更多的信息(暂时这么理解就行了),通过私钥甚至可以推导出公钥。所以一般都是把公钥提供给对方。
  5. 只要通过网络发送信息,都有可能被人截取;

根据上述“定理”,我们肯定会有一个疑惑(假设你有疑惑)。

问题一: 密钥对由谁生成?

这个问题我们暂时先不做回答,先通过我们的第一个场景:单向通信,来观察一下它是怎么运作的。

2. 场景一:单向通信

假设现在存在这样的一个场景:

场景有A/B两个角色,现在B要给A发消息。

先假设密钥对由B生成,结合私钥必须是由自己保管这个“定律”,那么大致通讯的流程会如下图所示:

cb06cb077178059863dc5f4b3bac69b3.png

我们发现,给公钥给B的时候,这个过程是不可靠的,因为公钥B可能会被人截获。

那么当B发送报文的时候,用私钥B加密,那么此时任何拥有公钥B的人都能解密报文了。这样的加密是没有效果的!

所以,如果反过来,密钥对由A生成,结合私钥必须是由自己保管这个“定律”,那么大致通讯的流程会如下图所示:

ba0d2b5046a6e5475d714170eb15a41f.png

因为私钥牢牢握在A自己手里所以可以保证不会泄露。那么B用公钥A加密的报文,就算在发送过程中被人截取去了也没用,因为只有A的私钥能解密,对于截取报文的人来说,此时的报文相当于一串乱码。

这也就回答了“密钥对由谁生成的问题”。很显然,秘钥对由要接受消息的人去生成。

现在我们得到一个结论。

  • 发送方使用接收方的公钥加密报文。

3. 场景二:双向通信

问题一的场景中,我们只解决了单向问题,也就是解决了B给A发送消息的问题,但是如果A也要给B发送消息呢?

有了场景一的铺垫,问题很好解决。还记得在场景一得出的结论嘛?

发送方使用接收方的公钥加密报文

由此推测,A也要使用B的公钥,所以,在双向通讯的场景下。我们的结论是:

  • 通信双方都要生成一对秘钥,并且交换公钥。

整个过程如下图所示:

65c528cc85f34e8984925ffe95efd653.png

4. 场景三:确保消息是由对方发出的

还是围绕着场景一来展开

场景:A/B两个角色,B要给A发数据。A生成密钥对并公钥A暴露给B。

我们发现,在场景一里面,已经能确保只有A能解密B发送的数据了。但是我们是不是忽略了一点:

既然公钥A是暴露出来的,那是不是所有拥有公钥A的人都可以随意篡改B给A发的数据呢? 这种情况如下图所示:

7c4a1a31274afa94cf3aa04ae4bcdae9.png

一般来说,坏叔叔篡改消息的步骤是:

1. 窃取公钥A;

2. 拦截B发送给A的报文;

3. 使用公钥A伪造报文,传递虚假消息给A;

无论是用一对秘钥还是两对秘钥。都只能保证发送方发送的数据不会暴露给第三方,但是却无法保证接收方收到的数据就是发送方发送的!

不安全!!!

所有我们得使用其他的手段去判断我们收到的消息是否是真实的、是否是完整的!

这种手段就是“签名”。

5. 什么是签名

这可不是手写一封信,签个名哈!

这里所谓的签名,指的是生成一串“符号”,唯一表示源报文数据。如果源报文数据变了,那么这串“符号”也得按照一定规则发生变化。二者的须是一一对应、唯一对应的关系。

简单来说,能且只能够通过源报文数据 推导出 签名串。

常用的签名方式大致有三种:

  1. 采用非对称性算法进行签名,如MD5,SHA;
  2. 采用对称性算法进行签名,如RSA;
  3. 综合对称性算法和非对称性算法一起进行签名;

签名的时候要特别注意的是,要加上一些能代表自己的元素。比如,使用MD、SHA算法签名的时候,只是简单的对传输报文提取摘要,但是传输的报文相当于是公开的,所以要加入一个只有双方才知道的appSecret来一起签名;RSA算法用于签名的话,因为私钥本身就是独特的,所以无须添加appSecret。

先让我们先来看一下怎么使用MD5来做签名~

6. 场景四:RSA加解密+MD5签名

场景:A/B,交互公钥,使用RSA加解密,使用MD5做数据签名。

还记得之前提过:加签时需要加上能表示自己的元素嘛?

md5用作加签的时候,双方需要约定一个appSecret作为加签使用的参数。这个参数是不跟随报文传递的,可以理解为他是加签的密钥。这个密钥就是这个能表示自己的元素。

直接来看图吧!

83bcf6c68f443a37aba63bda2ecc2098.png

步骤:

1. A使用公钥B加密报文 -> 得到密文:encrypted;

2. A对密文进行加签,即MD5(encrypted+appSecret) -> 得到签名串:signature;

3. A把encrypted、signature一起发送给B;

4. B分别取出encrypted、signature;

5. B也来一次签名MD5(encrypted+appSecret) -> 得到签名串:signature2;

6. B用signature和signature2做比较,如果二者相同,证明报文未被修改;

7. 若未被修改,则B用私钥B解密密文encrypted -> 得到明文payload;

问题一:为什么A的签名操作是对 加密后的密文encrypted来进行的呢?

因为这部分就是A想要发送给B的数据,加签的目的就是为了要证明这部分数据没有被修改过。

问题二:为什么B要重新进行一次加签?

在B这边重新加签和比对结果的过程称之为验签。A发送过来的报文有两部分,encrypted、signature。如果encrypted被篡改了,那么对encrypted签名以后必定得不到signature;如果signature被篡改了,无论encrypted是否被篡改,encrypted就肯定推导不出来signature了。

问题三:appSecret既然是一个密钥,那必定也是一方颁发给另外一方,也存在泄露的风险吧?

要承认的是,的确有丢失风险。但是要从两个角度上看。首先,密钥只传输一次,丢失的概率不大,如果有必要甚至你可以用rsa加密后传给对方。

md5用作加签的时候,双方需要约定一个appSecret作为加签使用的参数。这个参数是不跟随报文传递的,可以理解为加签的密钥。这个密钥就是这个能表示自己的元素。

7. 场景五:RSA加解密+RSA签名

嗯哼?RSA不是用来加解密的嘛?为啥也能用来签名。讨厌~

咳咳,谁说不是呢。那就来看下RSA到底要怎么签名吧!

还是直接上图:

a2f710e3a42d237fbd0bd56cc4b729cc.png

步骤:

1. A使用公钥B加密报文 -> 得到密文:encrypted;

2. A用私钥A对密文进行加签,即私钥A(encrypted) -> 得到签名串:signature;

3. A把encrypted、signature一起发送给B;

4. B分别取出encrypted、signature;

5. B使用公钥A来验签,即公钥A(encrypted)-> 得到签名串:signature2;

6. B用signature和signature2做比较,如果二者相同,证明报文未被修改;

7. 若未被修改,则B用私钥B解密密文encrypted -> 得到明文payload;

和场景四不同的地方是第2和第5点。

问题一: 为什么A要使用私钥A来做签名呢?为什么不是公钥?

同学,还记得嘛,我们现在的场景是为了让消息接收方B能确保消息是由消息发送方A发送的。交互了公钥以后,消息发送方A这边现在有的秘钥分别为公钥B、私钥A,公钥是暴露出来的(所有人都有这货!),所以只能用私钥A来加签,并且私钥A只有消息发送方A拥有,只要B能用公钥A解密,那当前数据必然是A发送过来的完整数据。

问题二:为什么非对称性加密算法也可以用来加签验签?

还记得吗?签名的核心操作指的是 能且只能够通过 源报文数据 推导出 签名串。而RSA加密后的密文也必然是唯一的。所以,RSA用来作为签名无可挑剔。

问题三:RSA验签和MD5验签有何差别?

首先要知道,rsa有两把钥匙,用私钥加签,这里指的实际上的对数据加密,加签只是一对这过程的概括。反过来也一样,用公钥验签,指的其实是用公钥解密。能解密,就说明验签通过了。

而md5加签和验签是一样的。让发送端与接收端做相同的操作,即都对报文数据求一次哈希值,验签只是比较二者的结果是否相同。

8. 非对称性算法的缺点

非对称性算法好处多多,总结来说就是对秘钥的管理上可以让人安心。

但是就如同男人一样,你不能光想着他的好,他有时也很气人哦

直白的说,那就是

非对称性算法就是太慢了!

没错,非对称性算法加解密的效率会对称性算法加解密的效率低很多。加密相对较慢,解密会更慢。并且加密后的报文会变长,长度甚至直接翻倍。

所以,少量报文的加解密、签名,都是没问题的。对长报文就无能为力了,除非你愿意接受他的速度。

9. 解决方案

那么对于通讯的报文结构来说,哪一部分比较长?

必须是加密前的原始数据了,我们称之为payload。所以对payload而言,我们使用对称性加密最好。

但是对称性加密的秘钥一旦传输就可能会暴露出去,怎么办呢?

那我们就对把这个秘钥用非对称性算法加密好啦~

所以,让我们来到场景六~

10. 场景六:AES加密消息+RSA加密随机密钥+MD5加签

先明确我们的目标场景

场景:双向通信;要确保只有消息接收方才能解密报文;消息接收方要能判断报文是否是消息发送方发送的;加解密速度要快;

依然直接上图:

3868cff3c95c9ac8936f720dadf05fdb.png

步骤:

1. A生成一个随机秘钥randomKey;

2. A使用秘钥randomKey,加密payload -> 得到密文:encrypted;

3. A使用公钥B加密randomKey, -> 得到加密秘钥串:keyEncrypted;

4. A对报文进行加签,即MD5(encrypted+ keyEncrypted+appSecret) -> 得到签名串:signature;

5. A把encrypted、signature、keyEncrypted一起发送给B;

6. B分别取出encrypted、signature、keyEncrypted;

7. B也来一次签名MD5(encrypted+ keyEncrypted+appSecret) -> 得到签名串:signature2;

8. B用signature和signature2做比较,如果二者相同,证明报文未被修改;

9. B用私钥B解密keyEncrypted -> 得到 randomKey;

10. 若未被修改,则B用randomKey 解密 encrypted,即AES(randomKey, encrypted) -> 得到明文payload;

问题一:为什么A要用公钥B来加密随机秘钥randomKey?

因为randomKey很重要,要确保只有消息接收方B能解密,那自然就是用公钥B来加密啦~

问题二:回到场景4的问题,appSecret丢失怎么办?

就算丢失了,对方攻破了你的验签过程,要篡改数据,那必然是encrypted,keyEncrypted中的一个。此时后续解密keyEncrypted,或解密encrypted的时候便会失败。此时,你可能会有疑问 “appSecret如果泄露了就相当于不加签了,那为啥不直接放弃加签?”。要知道网络攻防不可能凭借一道防线就解决所有问题。验签能阻挡99.99%的非法请求了就已经是发挥了重要作用了。

11. 场景七:AES加密报文+RSA加密密钥+RSA加签

场景:双向通信;要确保只有消息接收方才能解密报文;消息接收方要能判断报文是否是消息发送方发送的;加解密速度要快;但是不想要appsScret了,觉得不安全。

也是直接上图:

47800e9dc41326b8e468b1cbe05b3cee.png

总的来说,无非就是将MD5加签,改成对encrypted和keyEncrypted 一起MD5后的值进行RSA签名。

步骤如下:

1. A生成一个随机秘钥randomKey;

2. A使用秘钥randomKey,加密payload -> 得到密文:encrypted;

3. A使用公钥B加密randomKey, -> 得到加密秘钥串:keyEncrypted;

4. A对encrypted/encrypted提取摘要,MD5(encrypted+keyEncrypted), -> 得到hash;

5. A对报文进行加签,即私钥A(hash) -> 得到签名串:signature;

6. A把encrypted、signature、keyEncrypted一起发送给B;

7. B分别取出encrypted、signature、keyEncrypted;

8. B用公钥A(encrypted+ keyEncrypted) -> 得到签名串:signature2;

9. B对encrypted/encrypted提取摘要,MD5(encrypted+keyEncrypted), -> 得到hash;

10. B用hash和signature2做比较,如果二者相同,证明报文未被修改;

11. B用私钥B解密keyEncrypted -> 得到 randomKey;

12. 若未被修改,则B用randomKey 解密 encrypted,即AES(randomKey, encrypted) -> 得到明文payload;

但如何每次都要自己去MD5、RSA操作挺麻烦的,现在部分平台已经存在SHAwithRSA、MD5withRSA算法,直接把这两步操作一起做了。

12. 结语

没啥好说的啦,就简单总结一下我们上述场景下的结论吧。

  1. 公钥给别人,私钥自己用;
  2. 使用对方的公钥加密报文;
  3. 公钥加密,私钥解密;
  4. 私钥加签,公钥验签;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值