近期,Github被爆出,在内部日志中记录了明文密码。html
虽然听说影响面很小,可是网络和数据安全问题又一次被放到台面上。大多数用户的经常使用密码就那么几个,一旦被黑客拿到,去其余网站“撞库”,可能会形成用户的财产损失。git
本篇文章主要介绍如何加密传输和存储用户密码,并讲解相关原理。github
加密主要有两种方式:对称加密和非对称加密。算法
对称加密:在加密和解密时使用的是同一个秘钥。数据库
对称加密的模式是:安全
客户端和服务端进行通讯,采用对称加密,若是只使用一个秘钥,很容易破解;若是每次用不一样的秘钥,海量秘钥的管理和传输成本又会比较高。网络
非对称加密:须要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。函数
非对称加密的模式则是:网站
即便黑客拿到了公钥,没有私钥也是没有办法解密,不考虑彩虹表的状况,彻底能够长期使用一对秘钥。加密
最经典的非对称加密算法是RSA算法。
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一块儿提出的。公钥私钥成对出现,用其中一个加密只能用另外一个解密,一般用公钥加密私钥解密。
为何RSA可以作到非对称加密呢?
互质关系:若是两个正整数,除了1之外,没有其余公因子,咱们就称这两个数是互质关系
简单来讲,RSA利用的原理是,若是两个互质关系的正整数的乘积足够大,是极难进行因式分解的(目前被破解的最长RSA密钥是768个二进制位,而正常使用的至少是1024位的密钥)。
经过必定的运算,把某计算结果和乘积做为公钥,另外一个计算结果和乘积做为私钥,便可以实现,利用公钥进行加密,并利用私钥进行解密。具体的数学公式推导和证实能够参考RSA算法原理。
传输层面的加密解密原理讲的差很少了,咱们来看看github是如何传输帐号密码的。
抓包看一下登陆请求的request,赫然发现,密码是经过明文传输的……
那么,这种传输方式安全嘛?还能够,由于使用了https,但还不够安全。
常规的http请求,全部信息明文传播,只要中间人在链路中的任意阶段进行劫持,就会带来三大风险:
怎么解决这些问题?用https。
https 能够认为是 http + TLS TLS 是传输层加密协议,它的前身是 SSL 协议,若是没有特别说明,SSL 和 TLS 说的都是同一个协议。
SSL/TLS协议是为了解决http的三大风险而设计的,但愿达到:
说了这么多,https作了什么?结合如下流程图,讲解一次https请求都发生了什么:
客户端发起https请求
服务端的配置
通常须要向权威机构申请一个证书(也能够本身制做,这个会在以后的中间人攻击中讲到,区别就是本身颁发的证书须要客户端验证经过,才能够继续访问,而使用受信任的公司申请的证书则不会提示),证书会生成RSA加密使用的一对公钥A和私钥B。
这个证书主要内容是公钥A,也包含了其余信息,如证书的颁发机构,过时时间等等。
由客户端的TLS来完成的,主要是验证公钥A是否有效,好比颁发机构,过时时间等等,若是发现异常,则会弹出一个警告框,提示证书存在问题。若是证书没有问题,那么就生成一个随机值。以后就进入了不对称加密的过程,首先用证书对该随机值进行加密。
这部分传送的是用证书加密后的随机值,目的就是让服务端获得这个随机值,后续全部的数据均可以用这个随机值(即私钥C),进行对称加密和解密。
服务端用私钥B解密后,获得了客户端传过来的私钥C,到此RSA非对称加密的过程结束了。
服务端用私钥C加密信息。
客户端用以前生成的私钥C解密服务端传过来的信息,因而获取了解密后的内容。整个过程第三方即便监听到了数据,也一筹莫展。
上面的过程,看起来彷佛无懈可击?并非,由于“人”才是安全系统中最脆弱的环节。
https信息的安全,彻底创建在证书可信的基础上,若是中间人伪造证书怎么办?
黑客本身伪造的证书须要客户端验证经过,才能够继续访问,只要客户端验证经过,那么公钥A,私钥B和私钥C对黑客来讲都是透明的,也有没有数据安全可言了,因此黑客只要诱导用户安装本身伪造的证书便可,例如使用各类钓鱼的不可描述网站。
因此即便使用https传输明文密码,也不是绝对安全的。那怎么样才能保证密码安全呢?
抓包看一下百度的登陆请求发现,密码是加密过的:
怎么加密的?咱们发现,有这么一个关键请求:
意味着,密码使用RSA进行加密和解密处理的。那么流程是什么样的呢?
查了一下github中,关键词RSA,star数最多的JavaScript库jsencrypt,惊喜的发现,百度登陆的加密方式和使用的函数名都和这个库一致,那咱们是否是能够大胆假设百度整套登陆请求时的流程和这个开源库基本一致呢,那jsencrypt的流程又是什么样的呢:
到这里,加密传输的过程已经完结了,如今服务端已经收到了用户真实的密码(解密后的),那怎么存储这个密码呢?
若是用明文存储密码(无论是存在数据库仍是日志中),一旦数据泄露,全部用户的密码就毫无保留地暴露在黑客的面前,开头提到的风险就可能发生,那咱们费半天劲加密传输密码也失去了意义。
单向加密算法:只能从明文生成一个对应的哈希值,不能反过来根据哈希值获得对应的明文。
经常使用的给密码加密的算法是几种单向的哈希算法。
常常被你们用来加密的算法有MD5和SHA系列(如SHA一、SHA25六、SHA38四、SHA512等)。
虽然用哈希算法能提升密码存储的安全性,但仍是不够安全。
一般黑客在侵入保存密码的数据库以后,他会随机猜想一个密码,生成一个哈希值。若是该哈希值在数据库中存在,那么他就猜对了一个用户的密码。若是没有猜中也没有关系,他能够再次随机猜想下一个密码进行尝试。
事实上黑客为了提升破解密码的效率,他们会事先计算大量密码对应的各类哈希算法的哈希值,并把密码及对应的哈希值存入一个表格中(这种表格一般被称为彩虹表),在破解密码时只须要到事先准备的彩虹表里匹配便可。所以如今黑客们破解仅仅只用哈希算法加密过的密码事实上已经是不费吹灰之力。
盐:一个随机的字符串,往明文密码里加盐就是把明文密码和一个随机的字符串拼接在一块儿。
为了应对黑客们用彩虹表破解密码,咱们能够先往明文密码加盐,而后再对加盐以后的密码用哈希算法加密。因为盐在密码校验的时候还要用到,所以一般盐和密码的哈希值是存储在一块儿的。
采用加盐的哈希算法对密码加密,要确保要往每一个密码里添加随机的惟一的盐,而不是让全部密码共享同样的盐。
虽然加盐的算法能有效应对彩虹表的破解法,但它的安全级别并不高,由于计算哈希值耗时极短,黑客仍然能够用穷举法来破解,只是增长了一些耗时。
为了应对暴力破解法,咱们须要很是耗时的而不是很是高效的哈希算法。BCrypt和PBKDF2算法应运而生。
这两个算法最大的特色是咱们能够经过参数设置重复计算的次数,重复计算的次数越多耗时越长。若是计算一个哈希值须要耗时1秒甚至更多,那么黑客们采用暴利法破解密码将几乎再也不可能。破解一个6位纯数字密码须要耗时11.5天,更不要说高安全级别的密码了。
若是咱们想要尽量保证用户的信息安全,咱们须要作如下的工做
以上。