本文从一个输入密码登录场景说起,详细介绍了密码传输过程的改进和思路,最后展现出一个相对安全的传输和存储方案。
场景
在互联网项目中,我们经常会遇到以下场景:
在上述场景中都涉及到了密码的传输和存储。这就产生了一个问题,密码作为用户的敏感数据,我们该采取怎样的方案才能保证这个过程中的数据安全。
存在的问题
这里我们以登录场景说起。你可能会说,这多简单,这不就是前端输入密码,然后保存到后端密码,或者直接从MySQL中查询出密码对比一下不就好了吗?
先说说,如果没有特殊处理关于密码的传输和存储会有哪些问题。
因为大多数用户的常用密码是固定的,如果拿到用户的明文数据,影响范围不只是我们的系统。他们会去其他网站尝试“撞库”,很可能会造成用户的财产损失。作为一个合规的负责任的企业,我们在设计系统时应该考虑这些问题。
为什么会被劫持?
首先说第一个劫持的问题如何解决。
HTTP(超文本传输协议)是用于在网络上传输数据的一种协议。虽然HTTP是广泛使用的协议之一,但它也存在着一些安全风险,例如:
HTTP 存在如此多的安全问题,那么可以替换为 HTTPS 协议来解决。
HTTPS 降低劫持风险
HTTPS(安全套接字层超文本传输协议)是HTTP协议的安全版本,通过在传输过程中使用加密协议(如SSL或TLS)加密传输的数据,避免了明文传输的风险,并且使用数字证书验证服务器的身份,防止冒充攻击,为Web通信提供了安全保障。HTTPS的主要目的是解决HTTP在传输过程中存在的明文传输和窃听风险。
SSL/TLS协议的主要作用是:
那么HTTPS请求的完整流程如何,具体是如何保证数据安全的?
以上是HTTPS请求加密的基本过程,其核心是通过数字证书和加密技术来保证数据在传输过程中的安全性。整个过程第三方即使监听到了数据,因为没有私钥所以无法解密,如果篡改数据服务器将无法解密。
中间人攻击
看起来HTTPS似乎解决了网络传输过程中的安全问题,但是HTTPS的安全完全建立在证书可信的基础上,如果中间人伪造证书怎么办?
中间人攻击(Man-in-the-middle attack, MITM攻击)是指攻击者在通信双方之间进行了非法的拦截、篡改和注入操作,从而能够窃取双方之间的信息和敏感数据。只要黑客诱导用户安装非法证书,他就可以模拟服务器,获取到用户传输的信息。那么如何解决呢?
加密算法
既然黑客可能获取到明文数据,那我们加密不就好了嘛。所以,在使用加密算法前我们先简单了解下加密算法。
加密主要有两种方式:对称加密和非对称加密。
对称加密
对称加密是指加密和解密过程使用相同的密钥,也称为共享密钥加密。
常见的对称加密算法有DES、3DES、AES等,其加密速度快、加密效率高,但密钥的安全性是一个问题,因为加密和解密使用相同的密钥,如果密钥被泄露,那么整个通信过程的安全性就会被破坏。
客户端和服务端进行通信,采用对称加密,如果只使用一个密钥,很容易破解;如果每次用不同的秘钥,海量秘钥的管理和传输成本又会比较高。
算法热点DES(Data Encryption Standard)数据加密标准,速度较快,适用于加密大量数据的场合,目前已证实不安全,可用3DES替换3DES(Triple DES是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高AES(Advanced Encryption Standard)高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密。是目前最常见的对称加密算法
非对称加密
非对称加密则使用两个密钥:公钥和私钥。公钥可以向任何人公开,用于加密数据,而私钥只有密钥的持有者才能使用,用于解密数据。
常见的非对称加密算法有RSA、DSA、ECC等。非对称加密算法的安全性很高,因为密钥是成对出现的,只有私钥的持有者才能解密数据,而私钥通常保存在计算机的安全存储区中,不易泄露。
一般情况下,对称加密和非对称加密会结合使用,例如HTTPS协议就同时使用了对称加密和非对称加密算法。HTTPS建立连接时使用非对称加密算法对密钥进行传输,然后使用对称加密算法来加密数据传输,这样既保证了安全性,又不会影响通信速度。
RSA
RSA加密算法是一种非对称加密算法,它由Ron Rivest、Adi Shamir和Leonard Adleman三位密学家于1977年共同提出。RSA加密算法的安全性基于数学难题,目前是公认的一种较为安全的加密算法。公钥私钥成对出现,用其中一个加密只能用另一个解密,通常用公钥加密私钥解密。
为什么RSA能够做到非对称加密呢?
互质关系:如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系
简单来说,RSA利用的原理是,如果两个互质关系的正整数的乘积足够大,是极难进行因式分解的(目前被破解的最长RSA密钥是768个二进制位,而正常使用的至少是1024位的密钥)。
通过一定的运算,把某计算结果和乘积作为公钥,另一个计算结果和乘积作为私钥,即可以实现,利用公钥进行加密,并利用私钥进行解密。具体的数学公式推导和证明可以参考RSA算法原理。
继续改进流程
知道了加密算法的分类,我们果断采取使用RSA来加密我们的密码。那么我们将密码传输流程改进为下面这个样子,将传输过程分为获取公钥和用公钥加密两步,这样即使有人拦截请求,他也无法解密数据。
存储加密
现在第一个传输密码的问题已经解决了,那么我们如何存储密码呢?
如果用明文存储密码(不管是存在数据库还是日志中),一旦数据泄露,所有用户的密码就毫无保留地暴露在黑客的面前,开头提到的风险就可能发生,那我们费半天劲加密传输密码也失去了意义。
单向加密
单向加密算法指的是只能从明文生成一个对应的哈希值,不能反过来根据哈希值得到对应的明文。经常被大家用来加密的算法有MD5和SHA系列(如SHA1、SHA256、SHA384、SHA512等)。
这样即使是我们开发人员,拿到数据都不知道用户的真实密码,安全性提高了很多,但是还不够。
通常黑客在侵入保存密码的数据库之后,他会随机猜测一个密码,生成一个哈希值。如果该哈希值在数据库中存在,那么他就猜对了一个用户的密码。如果没有猜中也没有关系,他可以再次随机猜测下一个密码进行尝试。
事实上黑客为了提高破解密码的效率,他们会事先计算大量密码对应的各种哈希算法的哈希值,并把密码及对应的哈希值存入一个表格中(这种表格通常被称为彩虹表),在破解密码时只需要到事先准备的彩虹表里匹配即可。因此现在黑客们破解仅仅只用哈希算法加密过的密码事实上已是不费吹灰之力。
加点“盐”
盐salt:一个随机的字符串,往明文密码里加盐就是把明文密码和一个随机的字符串拼接在一起。
为了应对黑客们用彩虹表破解密码,我们可以先往明文密码加盐,然后再对加盐之后的密码用哈希算法加密。由于盐在密码校验的时候还要用到,因此通常盐和密码的哈希值是存储在一起的,我们需要在数据库中为其增加对应的字段。这样我们的密码就安全多了。
继续改进我们的流程,如下。
拿到密文密码并且在服务器解密之后,我们用数据库中的盐(每个用户不同)来拼接明文密码,然后和数据库中的密码做对比,如果相同则登陆成功。
最后,欢迎大家提问和交流。