用户注册密码加密和后端校验的权衡

背景

  1. 对于一个系统来说,显然把用户的密码明文存储是大忌,那么必然要加盐加密存储。
  2. 在登录注册过程中,密码显然不能明文传输,那么必然会用https来做登录注册接口。
  3. 但是 https 并不是绝对安全的,经常用抓包工具调试软件的就会明白,虽然条件苛刻,但是也能实现中间人攻击,那么为了安全,应该在浏览器或者客户端把密码先做加密处理(MD5),即使被中间人攻击了,也不会泄露密码。Link
  4. 那么问题来了,对于后端开发人员来说,客户端是不能被信任的,如果采用MD5或其他摘要算法,后端是无法对密码强度进行检验的,如何解决这个问题?

实验环节

为了解决这个问题,我首先对几个知名网站的注册进行抓包,看看他们是怎么处理这个问题的 (截图丢失这里暂时只放结论)
  1. 阿里云账户: https + 明文密码
  2. 微软账户: https + 明文密码
  3. 百度个人中心: https + 某种未知加密
  4. 微信公众平台: https + MD5
  5. 谷歌账户:https + 明文密码

分析思考

  1. 上述5个网站中百度的最有意思,从密文上没看出来是何种加密方法,密文长度和密码长度趋势相反,引起了我的好奇,于是提取js观察,原来用了RSA算法,这种非对称加密传输密码,确实能保证密码被可靠的传输到后端,这个过程和https传输对称加密密码过程是一样的,除非这个黑客黑到极致,不仅成功做了中间人攻击,还顺手把百度的那个js给改成了他自己的一套,用户注册的密码被中间人解密后再用真正的百度的那个js加密请求给百度后端(从这个角度考虑,只要中间人存在,就不存在绝对的安全,就算用了Hash加密密码,中间人捕获到你的md5密文,来伪造请求登录,登陆成功过后还不是可以为所欲为,如果杠精说阿里、微软谷歌的都不安全,微信公众平台和百度才叫真正的安全,那么大可怼回去,这只不过是五十步笑百步,在中间人面前,皆是蝼蚁)。
  2. https 的可靠性还是被认可的,毕竟对https进行中间人攻击,条件是很苛刻的,如果是浏览器,会给你提示证书错误,阻止你的访问,如下图。如果是自己开发的客户端,ssl证书的认证过程也是可控的。
    用户注册密码加密和后端校验的权衡_第1张图片
  3. 回到题目,如果使用https + 密码明文进行注册,服务端自然可以检验密码强度,除了担心安全,没什么好纠结的。
  4. 如果使用https + md5进行注册,服务端无法检验密码强度,那么能自己绕过前端验证的,必然都是搞技术的开发者或者黑客(正经人谁 TM 使 Postman 注册),黑客注册一个脆弱的账户自己用的话,其意义跟注册一个密码强度高的账户没区别,系统安全的要求都是防止恶意用户越权访问。如果黑客注册一堆脆弱的账户给别人用,其依然没意义,既然是黑客注册的,密码简单和复杂没区别,因为黑客完全掌握。因此也没什么好纠结的。
  5. 如果使用RSA非对称加密进行注册,服务端可以解密得到密码明文,从而检验密码强度,密码没有在https加密下明文传输(这话说着别扭),心理好受,又担心非对称加密代价比较大,其实注册不是一个高并发的场景,在网关层面做好防护,防止流量攻击即可。因此也没什么好纠结的。

总结起来,为了屁事少,前端做个密码强度校验,然后https请求到服务端,服务端对密码加盐增加密码长度,以sha或者md5的形式存储到数据库即可。如果你作为不受信任的服务提供商,为了充分保护用户隐私(避嫌),大可在https请求之前,做个MD5哈希,服务端不接触用户用户的明文密码,就不会有因为日志等因素泄露用户隐私的风险!

其实我有考虑能否使用同态加密,但是没研究过其可行性,只是设想客户端传输了服务端不可解的密文,服务端又能判断密码强度,然后服务端存储这个不可解的密文,这样就能做到md5形式的避嫌,又能做到不传输明文,还可以在服务端校验密码强度,全部痛点都解决了(除了开发者肝疼)

你可能感兴趣的:(职业,项目经验,测试,golang,https,密码学,安全)