加密?签名?傻傻分不清楚

697 阅读5分钟

最近跟别人讨论Tls1.3的时候,突然发现自己对于网络安全方面的知识还是有些贫瘠,所以特地去恶补了一把,然后整理出了这篇文章。

首先我们要先明确一些原则

  1. 公钥加密,私钥解密
  2. 签名的意义在于保证数据不被篡改
  3. 加密的意义在于数据传输过程中,不会被第三方获取到报文具体内容。

一般对接过开放api接口的都知道,常见的我们都会需要使用参数签名sign来进行相关的验证。那这究竟是为了什么呢?我们先提出一下问题,然后结合案例进行分析:

  • 如何校验请求参数在传输过程中是否已被篡改?
  • 如何校验请求来源的合法性?

案例,我们需要提供下单接口给分销商使用。以下是不进行验证时正常运行的流程:

  1. 分销商:调用下单接口提交参数
{
    "产品类型":"玻璃杯",
    "数量":30,
    "地址": "南京路10086号",
    "分销商编号": "****"
}
  1. 后台:接受到下单请求,受理订单同时扣除分销商余额

不过这会有问题

  1. 无法保证分销商的编号不会被盗用
  2. 当分销商的请求被劫持时候(常见的dns劫持),虚假服务器将参数内容修改成了
{
    "产品类型":"黄金杯",
    "数量":300,
    "地址": "黑心路10086号",
    "分销商编号": "****"
}
  1. 服务端接受请求,受理订单。然后......

于是就有了新的方式。

  1. 在开发之初,我们会给分销商派发一个私钥key。
  2. 当分销商提交请求时,需要先对参数名进行排序,然后在最后拼接key,获得一个加密前的beforeSign。最后对beforeSign进行一次签名(常见的有md5)后得到一个sign。放在报文里一起提交到服务端。
  3. 服务端接收到请求后,先进行参数校验,将参数去除sign后使用与分销商同样的算法进行签名。如果签名后的结果与分销商传过来的sign不一致,则表示参数在传输过程中被修改过,服务端返回”验签失败,订单不予以受理“。

不过订单提交的问题解决掉了,用户的信息安全性怎么保证呢?虽然通过签名验证,虚假服务器已经无法修改参数内容,可是订单提交的信息依然被虚假服务器获取。而且在一般的情况下,订单内的信息除了订单的相关参数,还包含着很多用户的敏感信息。

然后我们就需要对于报文的内容进行加密。在这里,我们不免会想起我们平时经常会看见的名词,什么https啊,RSA啊(我没有,我不是,你别乱。。)

RSA算法是一种在如今的商业用途中被广泛运用的加密算法。整体有公钥,私钥。其中公钥是公开的所有客户端都能获取,私钥只有服务端知道。公钥和私钥都能进行加密和解密。当使用私钥加密时,使用公钥解密。当使用公钥加密时,使用私钥解密。

于是分销商和服务器之间就有了如下交互:

  1. 分销商获取公钥,同时对报文进行加密。
  2. 我方服务器接收到请求,然后使用私钥解密,然后受理订单(这里虚假服务器由于不持有密钥,所以无法破译报文内容)。同时返回成功。
  3. 分销商系统提交查询订单详情(密文)
  4. 我方服务器返回订单数据(使用私钥加密)
  5. 分销商系统获得订单详情(使用公钥解密)

但是问题就来了,在4,5流程之间由服务端发送至客户端的报文是使用私钥加密的,所以只要是持有公钥(无论是中间的虚假服务器,还是客户端)都可以解密,然后取得明文。

怎么解决呢? 在这里,我们会引入一个对称加密的算法。

  1. 分销商获取公钥,同时对报文进行加密。
  2. 我方服务器接收到请求,然后使用私钥解密,然后受理订单(这里虚假服务器由于不持有密钥,所以无法破译报文内容)。同时返回成功。
  3. 分销商系统提交查询订单详情请求,同时附带一个对称加密算法,及其密钥。(由于查询订单详情请求是使用公钥加密,所以只有我方服务器能解密,黑客及其他方无法获取到对称算法内容)
  4. 我方服务器返回订单数据(使用分销商提交的对称加密算法及密钥加密)
  5. 分销商系统获得订单详情(使用堆成算法及密钥解密)

当然这种算法也有其问题。其根源在于所有人都可以生成自己的私钥和公钥,而服务器的公钥大家都可以获取到。当分销商的请求被劫持住时,由虚假服务器返回了一个它自己生成的公钥。而虚假服务器则可以获取到我方服务器的公钥。于是由客户端提交的请求,虚假服务器可以使用自己的私钥去解密,而我方服务器返回的密文,又可以使用公钥解密。整个服务的安全性也就不存在了。

那还有进一步的解决方式么?(有有有!,放开我,我还能说!)

有兴趣的大伙们可以期待我下一期的主题 《ssl?tsl?有关于网络安全》

本期的内容就讲到这里了,我是 IHAP亚楠小萌新,更多精彩内容,尽在 ihap 技术黑洞。