前端传输的数据咱们应该用什么算法加密,如何组织整个加密过程呢? 通常有几种作法:前端
• JavaScript 加密后传输算法
• 浏览器插件内进行加密传输数据库
• Https 传输后端
严格意义来讲第一种手段并不是加密,而是一种信息摘要的应用,为了阐述方便下文通通使用加密一词。在进行下文以前,须要简单的介绍几个概念:浏览器
上图中咱们能够明显看到哈希和加密是两个不一样的东西,主要有两点不一样:安全
哈希算法一般用于数据摘要,生成相同长度的文本。而加密算法生成的密文长度与明文长度有关。
哈希算法是不可逆的,而加密算法是可逆的。服务器
在加密算法中又分为对称加密(symmetric encryption)和非对称加密(asymmetric encryption)。非对称加密算法中,加密密钥和解密密钥是不一样的,分为私钥和公钥,咱们熟知的 RSA 就是一种非对称加密算法。而对称加密中,加密和解密都是用同一个密钥,如 AES / DES。从性能上来讲,非对称加密相对于对称加密要慢不少。网络
在 HTTPS 中,认证过程使用了非对称加密算法,非认证过程当中使用了对称加密算法。性能
在 HTTP 协议下,数据是明文传输,传输过程当中网络嗅探可直接获取其中的数据。 如用户的密码和信用卡相关的资料,一旦被中间人获取,会给用户带来极大的安全隐患。网站
另外一方面,在非加密的传输过程当中,攻击者可更改数据或插入恶意的代码等。HTTPS 的诞生就是为了解决中间人攻击的问题,但现在 HTTPS 的使用状况在国内并不乐观,基本是由于成本或者性能的考量。
那么问题来了,
若是仍然使用 HTTP 协议,
怎么样必定程度保证用户的数据安全?
前端加密,
即在数据发送前,
将数据进行哈希或使用公钥加密。
若是数据被中间人获取,
拿到的则再也不是明文。
设想在现在公共 WIFI 流行的今天,一旦某一个 AP 的流量被攻击者劫持,若是密码和用户名都是明文,那么攻击者将垂手可得的使用这些资料进行 Replay 登陆。更糟糕的是不少用户在不一样的网站使用相同的帐号信息,用户的隐私荡然无存。
做为网站服务提供者,网站设计和开发人员应该为用户提供相对安全的服务,这是一种责任也是一种情怀。
另外,若是前端使用哈希算法,不只能够帮助后端分担部分计算压力,还能够增长撞库成本。具体的讨论将在下文继续。
前面说过使用 JavaScript 加密有两种方式,一是使用哈希进行信息摘要,一种是使用非对称加密。在国内的知名站点中,这两种方式都有人使用。接下来咱们分别来深刻了解加密过程,探讨下如何应对不一样的场景。
为了不传输过程当中的明文风险,前端能够在发送敏感数据前对其加密,如密码。因为哈希算法的不可逆性,中间人没法从截取的数据中得知用户的密码信息。
可是这里有一个问题,攻击者仍然可使用拿到的哈希值进行直接登陆。使用前端加密如何避免中间人重放攻击?带着这个问题,咱们回顾下后台如何验证用户。
不少站点后台对于用户密码处理也是用哈希算法,一方面由于不须要将密文解密成明文来比对密码,另外一方面是一旦加密算法和密钥泄露,那么整个用户资料库就至关于明文存储了。若是前端传过来的是明文,那么在注册时将其哈希,存入数据库。登陆时,将密码哈希和数据库对应的数据比对,若一致则说明密码正确。
若是咱们使用 Salt 是否能够解决问题?若是前端传过来的是加了 salt 的哈希值,咱们须要后端存有同一份 salt ,用其和数据库的加密密码哈希,而后与前端传过来的哈希值比对。两个过程的对比见下图:
很容易知道,若是 Salt 不是每次登录不一样,那么攻击者仍可使用加密后的密码进行直接登录,因此必须使用动态 Salt。动态 Salt 有不少方法,能够是动态的 Token,也能够直接使用现成的验证码。 这当中使用验证码是对后台系统改动较小且效果不错的,咱们来看看怎么样结合验证码进行前端加密。
前端先将密码哈希,而后和用户输入的验证码进行哈希,获得的结果做为密码字段发送给服务器。服务器先确认验证码正确,而后再进行密码验证,不然直接返回验证码错误信息。
这种实践保证了密码在传输过程当中的资料安全,即便攻击者拿到了数据也没法重放。图形化验证码更是增长了难度。另外一方面该实践大大增长了撞库的成本。
前端加密必定程度保障了传输过程当中的资料安全,那么会不会有对两端(客户端和服务器)有安全帮助呢?
有帮助,使用一些前端加密手段,能够增长拖库后的数据破解难度。可是以前介绍的验证码方法不具备这样的功能,由于数据库存的还是明文密码哈希后的结果,那么攻击者能够绕过前端加密,能够直接暴力破解。
使用怎么样的前端加密方法能够增长拖库后的数据破解难度?从两个方面分别去思考,一是下降破解速度,二是须要前端加密结果影响数据库的数据存储。数据被暴力破解出来的时间与哈希算法速度负相关。
咱们知道暴力破解便是使用相同的算法把经常使用的字符组跑一遍,若是结果相同那么就猜中明文了。若是算法越快,便能更快的破解。例如 MD5 加密一次耗费1微秒,那么攻击者一秒钟就能够猜大约 100万个词组。
因此为了减慢破解速度,咱们须要增长破解的时间,一个直接的方法就是使用更慢的算法,咱们能够把经常使用的MD5算法替换为 bcrypt,PBKDF2 等慢算法。
对于须要前端加密结果影响数据库的数据存储,即为后端加密把前端加密结果当作明文密码,那么存在库里的密码即是前端哈希加上后端加密的结果。
因为慢的算法会增长服务器计算压力,当咱们把一部分哈希工做拿到前端,即减慢了加密速度,减轻了服务器压力,也顺带完成了前端加密的工做。
加密速度减慢必定程度会下降用户体验,这也是一部分站点未启用 https 的缘由之一。可是由于咱们的前端加密只会用在不常使用的登陆和注册上,因此不会影响网站总体的体验。
综上,咱们可使用更慢的算法,加之视前端哈希结果为明文密码,即可增长拖库破解的成本。既然增长了破解的成本,撞库的成本也一样增长了。为了不攻击者先前使用先后端加密生成的新字典,咱们须要加盐,并不按期更新盐值。下图文是使用过时 Salt 的方法描述:
前端加密使用按期刷新的 Salt,哈希后生成密文,再通过后端加密后即为用于比对的密文。数据库中的密码哈希值跟着 Salt 进行变化,先后端须要有一套salt的更新机制。
回顾前端哈希的方法,解决了中间人攻击重放、加大了拖库破解的难度。虽然这些方法都不能彻底保证用户安全,可是做为站点服务者,应该视用户为上帝嘛。这些方法也不过就是几行代码的事,可是却能必定程度的避免了用户帐号被盗等风险。
上文中咱们讨论了前端的哈希加密以及应用的场景。对于十足的安全控来讲,这样的措施对于有心的攻击者基本没有用。那么咱们能够采用更强的措施保障传输中的敏感数据安全。
以前有说过加密算法分为对称加密和非对称加密,由于前端的透明性,使用JavaScript来进行对称加密是不可能的了,那么只剩下了非对称加密这个选择。
通过笔者几天的调研发现,某鹅某浪的部分登陆页面采用非对称加密对密码加密。这些站点目前都仍是使用 http 协议,这样的安全措施必定程度保证了用户的密码安全。
前端使用非对称加密原理很简单,先后端共用一套加密解密算法,前端使用公钥对数据加密,后端使用私钥将数据解密为明文。中间攻击人拿到密文,若是没有私钥的话是没办法破解的。
可能有人会指出加密算法一旦被破解,这一套安全措施就没用了。何况 JavaScript 的生成安全随机数仍是个问题,因此其实这是用不了 https 的权衡之计。在没有 https 的状况下,使用 JavaScript 非对称加密或者 插件加密通信是比较好的替代方法,后者优于前者。