问题引入
每个系统都有自己的账户系统,有账户系统,那就必然面临登录的概念,登录就要在互联网中传输密码,在互联网中传输密码就存在被人攻击和窃取的可能,如何做到密码传输安全可靠呢?
解决方案1
Https就已经保证了传输安全,不需要再进行加密
问题所在
有些大厂,为了能监控员工的网络,防止重要数据外泄,会在你的电脑上面安装企业证书,到了企业网关时,都会被拦截下来,由于电脑上面安装了企业证书,浏览器就信任了企业的“非法”证书,那网关就可以把所有请求数据明文解析出来,如果说我们的重要账号密码(比如银行)被解密了,那是非常严重的。
解决方案2
客户端上传请求之前,采用非对称加密,做一次公钥加密。
问题所在
加密公钥放在哪里?如果是写死在代码里面,确实没有私钥无法解密,但是你无法保证私钥永远不可能泄露,万一发生泄露,那所有的客户端都需要升级(网页端还好,App端那就天方夜谭了)
解决方案3
登录之前,先请求下载一个动态的公钥,利用这个公钥来进行加密密码,并且这个公钥是一次性的,用完就不能再用。每次登录之前都先动态生成一次公钥。
问题所在
对于通用的gateway拦截来说并不能破解,但是针对"有心人"就不一定了,因为gateway可以拿到所有传输的明文数据,那就意味着,他可以拦截掉服务端下发的公钥,然后再生成一个新的公钥给客户端,这样,又可以再次拿到密码明文。
解决方案4
动态下载的秘钥不是用来加密,而是用来计算hash值,因为我们知道,计算hash值是一种不可逆运算。既然已经到了这层,我们也就没有必要再用非对称秘钥了(因为非对称秘钥是比较烧机器性能的),直接采用Hmac就好了。就算gateway拦截下来,客户端是计算hash的方式上传,那也就不存在破解的问题。服务端匹配秘钥时,也需要对Key进行一次一样的hash计算,利用结果进行对比。
这种方案,网络传输的值实际根本就不是密码,而是密码的一个hash值,这种不可逆运算就是非常安全了。(这种方式存在极低的概率会存在输错密码,但是计算的Hash相同的情况,这种概率,我们可以忽略不计,比起其他方案来说,风险小太多)