HTTP如何“自加S“来安全传输数据?


尽管如今HTTPS已经成了业界标配,前后端之间更常使用api进行数据传输,但穷逼中小型项目中,怎么保证数据在HTTP传输下保证安全?虽然本文所讲的安全通信实践并不完善,但也好过裸奔,有兴趣的话就来看看吧~

可用场景:n个客户端对某些固定服务端的HTTP安全通信


下面实现方案都有以下前提:

  • 已知公私钥对P是 服务端或站点 提供的,而不是黑客假冒(可为线下约定,公钥P1不担心泄漏,但私钥P2绝不能泄漏)
  • 客户端中已经保存公钥P1,减少请求连接次数

一、如何保证安全登录

在聊怎么保证安全前,需要先知道:什么情境下不安全?下面先来看看大佬总结的“黑客定理”

黑客定理:

  1. 网络上传递的数据是不安全的,网络属于黑客公共场所,能被截取。
  2. 客户端是不安全的,属于黑客本地范畴,能被逆向工程。
  3. 用户客户端内存是安全的,属于黑客远端范畴,认为是安全的。

通过对这些定理的分析,可以得出:

  1. 网络上传递的数据,要先加密,再传输
  2. 任何客户端与服务端提前约定好的算法与密钥都是不安全的,不能固定密钥
  3. 密钥不能在网络上直接传输

那么,只要做到以上几点,数据在网络上的传输就有了一定的安全性

(ps:要是遇到黑客大佬,当我没说)


以登录为例进行安全的数据传输,示例时序图如下:

客户端 服务端 默认已有公私钥对P (客户端拥有`公钥P1`;服务端拥有`私钥P2`) 获取用户输入的账号、密码 随机生成公私钥对T(`公钥T1`、`私钥T2`) 使用`公钥P1`加密(账号+密码+`公钥T1`),发起请求 黑客没有`公钥T1`、`私钥T2` 使用`私钥P2`解密,获得账号+密码和`公钥T1` 账密验证成功,生成"用户标识token"和"对称秘钥M" 使用`公钥T1`加密("token"+"对称秘钥M"),响应请求 黑客没有`私钥T2`解密 使用`私钥T2`解密,获得"对称秘钥M"和"token" 黑客没有"对称秘钥M",不能伪造、解密数据 使用"对称秘钥M"加解密数据,保证数据不被阅读/篡改 请求时header头中携带"token",来作为通信时用户的身份标识 客户端 服务端

Q:为什么要随机生成公私钥对T?像事先约定公私钥对P一样,让服务端事先保存公钥T1,客户端事先保存私钥T2,不行吗?

A:如果客户端事先保存私钥T2,那么通过反编译,黑客就能够从客户端中拿到私钥T2,服务端通过公钥T1加密的数据,就能够被黑客解密,不再安全;即使黑客拥有公钥P1,也可以自己生成公私钥对T(伪),但是没有正确账密的他,并不能得到服务端的响应,无处着手。



登录是否搞复杂了?如果客户端不生成公私钥对T,直接生成对称密钥M,是否可行?
是可以的,这么做也能减少服务器生成对称密钥的步骤,提高服务器响应速度和处理效率。话不多说,直接看下图:

客户端 服务端 默认已有公私钥对P (客户端拥有`公钥P1`;服务端拥有`私钥P2`) 获取用户输入的账号、密码 随机生成"对称秘钥M" 使用`公钥P1`加密(账号+密码+"对称秘钥M"),发起请求 黑客无法得到"对称秘钥M" 使用`私钥P1`解密,获得账号+密码和"对称秘钥M" 账密验证成功,生成"用户标识token" 使用`私钥P2`签名("token"),响应请求 黑客没有`私钥P2`篡改数据 使用`公钥P1`验签,并获得"token" 黑客没有"对称秘钥M",不能伪造、解密数据 使用"对称秘钥M"加解密数据,保证数据不被阅读/篡改 请求时header头中携带"token",来作为通信时用户的身份标识 客户端 服务端



其实不管是生成公私钥对,还是生成对称密钥,或者使用其他密钥交换算法,都是借助“公钥加密的数据,仅拥有私钥的服务端能够解密阅读”这一特点,从而保证了密钥交换时的安全性。



二、如何防止重放攻击

Q:假设重新登录,token就重新生成,而黑客截取到了客户端发起的"使用公钥P1加密(账号+密码+公钥T1)"请求,即便他无法解析数据,但只要重新请求服务端,就导致已登录的用户可能出现登录过期/异常的情况,怎么处理?

A:需要对黑客的重放攻击进行防范,绝不能让其影响到实际业务,可以采用下面这种做法:

  1. 在真正登录之前,先进行一次"预登录"(携带一个自己要进行的登录标识,比如IP、用户名等进行请求),获取服务端颁发的"一次性准许登录凭证voucher"
  2. 获取用户输入的账密,并携带voucher,请求服务端
  3. 服务端接收到voucher,需要对其进行检验:如果voucher可用,则进入正常流程,并销毁该voucher,防止该voucher再次使用产生数据重放问题;如果voucher已经被销毁,那便是数据重放,直接终止流程

再将上述的安全登录流程加上,整合后的时序图如下:

客户端 服务端 默认已有公私钥对P (客户端拥有`公钥P1`;服务端拥有`私钥P2`) 获取用户输入的账号、密码 传参 用户账号 ,发起"预登录"请求 随机生成voucher(唯一不重复的字符串即可), 并保存该voucher到缓存中 返回"一次性准许登录凭证"voucher字符串 随机生成"对称秘钥M" 使用`公钥P1`加密(账号+密码+"voucher"+"对称秘钥M"),发起请求 黑客无法得到"对称秘钥M" 使用`私钥P2`解密,获得账号+密码和"对称秘钥M"、"voucher" 检查缓存中是否存在"voucher",不是的话终止下面流程; 是的话清掉缓存中该"voucher" 重放攻击时,"voucher"已失效,终止流程 账密验证成功,生成"用户标识token" 使用`私钥P2`签名("token"),响应请求 黑客没有`私钥P2`篡改数据 使用`公钥P1`验签,并获得"token" 黑客没有"对称秘钥M",不能伪造、解密数据 使用"对称秘钥M"加解密数据,保证数据不被阅读/篡改 请求时header头中携带"token",来作为通信时用户的身份标识 客户端 服务端



三、不登录,如何建立安全连接

上面是基于特定场景——登录才实现之后的安全通信,那能不能做到:不登录,一样能够安全通信呢?当然是可以的

还是那个前提:已知公私钥对P是 服务端或站点 提供的,而不是黑客假冒(可为线下约定,公钥P1不担心泄漏,但私钥P2绝不能泄漏)

客户端 服务端 默认已有公私钥对P (客户端拥有`公钥P1`;服务端拥有`私钥P2`) 随机生成"对称秘钥M"和其对应会话标识"session_id" 使用`公钥P1`加密("对称秘钥M"), 并携带"session_id"发起请求 黑客没有`私钥P2`,无法阅读 使用`私钥P2`解密,获得"对称秘钥M" 使用`私钥P2`签名("session_id"),响应请求 黑客可以使用`公钥P1`,但无法篡改 使用`公钥P1`验签,确保是服务端的响应,则可以安全通信 黑客没有"对称秘钥M",不能伪造、解密数据 使用"对称秘钥M"加解密数据,保证数据不被阅读/篡改 请求/响应时携带"session_id",来作为会话标识 客户端 服务端

上面直接由客户端直接生成对称秘钥,是一种最为简单的算法,实际应用上,秘钥的交换算法多种多样,如ECDHE 秘钥交换算法(目前大部分网站的做法)、DHE 算法等。

只要能够借助公钥加密的数据,仅拥有私钥的服务端能够解密阅读”这一特点,并保证客户端是随机生成密钥/公私钥对(防止反编译),那么就能够有无数种花样玩法了



四、参考文章

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值