加密算法中盐的作用

由来

         涉及身份验证的系统都需要存储用户的认证信息,常用的用户认证方式主要为用户名和密码的方式,为了安全起见,用户输入的密码需要保存为密文形式,可采用已公开的不可逆的hash加密算法,比如SHA256, SHA512, SHA3等,对于同一密码,同一加密算法会产生相同的hash值,这样,当用户进行身份验证时,也可对用户输入的明文密码应用相同的hash加密算法,得出一个hash值,然后使用该hash值和之前存储好的密文值进行对照,如果两个值相同,则密码认证成功,否则密码认证失败。

        由于密码是由用户设定的,在实际应用中,用户设置的密码复杂度可能不够高,同时不同的用户极有可能会使用相同的密码,那么这些用户对应的密文也会相同,这样,当存储用户密码的数据库泄露后,攻击者会很容易便能找到相同密码的用户,从而也降低了破解密码的难度,因此,在对用户密码进行加密时,需要考虑对密码进行掩饰,即使是相同的密码,也应该要保存为不同的密文,即使用户输入的是弱密码,也需要考虑进行增强,从而增加密码被攻破的难度,而使用带盐的加密hash值便能满足该需求

      其实这里所说的盐,简单的说,就是一组安全随机数。它会在特定的时候,加入到密码中(一般来说是加密后的密码

常用的密码攻击方式有字典攻击、暴力破解、查表法、反向查表法、彩虹表等。

常用的密码攻击方式

字典攻击暴力破解,攻击者均采用逐密码尝试的方式,目前没有很好的手段来阻止字典攻击和暴力破解攻击,只能是想办法让这两种攻击方式变得相对低效一些而相同的密码产生不同的hash值便能让攻击者针对每一个hash值都需要从头进行尝试,从而使攻击变得更加低效。

查表法反向查表法彩虹表攻击方式,攻击者需要提前准备好包含密码和密码hash值的密码表,然后根据该表和用户密码数据库进行批量匹配,从而达到攻破密码的目的;而如果我们在加密时,给每个密码附加了不同的随机值,这样每个密码对应的hash值也会不同,这样攻击者在准备密码表时,就必须要将最基本的密码和用户密码数据库中的值进行笛卡尔积后再计算hash值,盐值越多,用户需要准备的表量越大,这样对于攻击而言,就变得有些得不偿失了。

加盐的注意事项

1、盐值不能太短;如果盐值只有少数两三位甚至一两位的话,攻击者完全可以穷举所有可能的盐值;关于盐值长度的一个经验值是长度至少要和hash加密函数的返回值长度保持一致。

2、盐值不能固定;如果系统使用了固定的盐值,那么和不加盐相当于是一回事了,攻击者完全可以使用该固定的盐值提前准备密码表;另外,相同密码对应的hash值仍然是一样的,仍然无法对密码相同这一事实进行掩饰。

3、不要使用能提前预知的值作为盐值;如果盐值能提前得知或提前推断出,攻击者也完全可以根据提前预知的盐值准备密码表,从而对破解的难度也增加不了多少。

4、每一次修改密码重新计算hash值时,要重新生成新的盐值,不要使用上次密码对应的盐值;因为如果用户密码泄露之后,盐值相应的也就泄露了,用户修改密码时,如果还沿用原来的盐值,攻击者也仍然可以根据上次的盐值提前准备密码表,从而使攻破可能性变得更高了。

数据库泄露

      众所周知,用户名和密码是被保存在数据库中。可是一旦数据库发生了泄露,用户名和密码就都遭到了泄露。攻击者可以轻松的获取用户名和密码,进行操作。更大的危害是,由于现在需要注册的网站、app越来越多。用户名和密码很多时候都是相同的。一旦某处发生了泄露,则后果会慢慢的扩散。这些危害大家可以查询下近些年发生的一些安全事故,如Sony数据库泄露、网易数据库泄露、CSDN数据库泄露等。

解决这个问题的通用方法是:

1、对密码进行加密存储

      这样的好处是,即使数据库发生了泄露,攻击者也不会拿到明文密码,依然无法直接使用这些密码。但是这样的存储方式也存在缺点:很多用户在注册时都是使用的弱密码。攻击者可以通过大量的注册用户,这些用户使用扩散的使用各种弱密码。当拿到数据库密文后,根据已知的用户名密码,就可以获取到相关的彩虹表。然后依据彩虹表依次匹配数据库中的密码。这样就可以得到其中使用弱密码的用户了。同时app、web等软件由于用户体验等原因,也不可能让用户设置安全系数过高的密码。如8位以上、包含大小写、特殊字符、于最近三次的密码不能相同、于上次密码至少有三位不同、不能包含密码字典中涉及的简单密码等等。举个例子:如ATM、微信支付密码使用的是纯6位数字,这样就有了10^6种可能,攻击者只要拿到了全套的密码对应的彩虹表,就可以获取到所有用户的密码。这套彩虹表,攻击者可以通过使用大量的简单密码注册用户得到。然后从获取到的数据库中找到攻击者自己注册的这些用户数据,进而拿到彩虹表。那么该怎么解决呢?这就涉及到固定盐值加密。

2、对密码进行加密

如前文所说,这个盐是一个随机数。当用户注册一个简单密码时,系统会同时生成这样一个salt,于该用户对应,保存到数据库中。

这样当用户的密码是888888时,后台真实存储的密码时888888盐化以后的值

操作步骤如下:

(1)注册、修改密码时,前台将 888888加密后的pwd1,传入后台

(2)后台拿到pwd1以后,生成一个相应的随机数 salt。将pwd1与salt拼接并再次加密,生成pwd2

(3)后台将pwd2salt 一并存储到数据库中。

(4)当用户每次输入用户名密码后,将密码加密生成pwd1'后,传入后台。

(5)后台拿到pwd1'后,根据用户名id拿到对应的盐值。与盐值拼接加密后,生成pwd2‘。

(6)然后判断pwd2'与数据库中的pwd2是否一致即可。

这里有两点需要注意:

①密码在前后台的加密方式可以采用不同的形式

②盐值的拼接不一定非要拼接到最后,也可以放在前边、插在中间、甚至拆开或者倒序拼接。

③这样即使是简单密码也没关系。因为相同的密码在数据库中存储的值并不一样。攻击者无法构造有效的彩虹表进行破解。

重放攻击

  先抛开前边的固化盐值加密不说,我们再说说另外一种攻击方式:重放攻击(Replay Attacks)又叫重播攻击、回放攻击或新鲜性攻击(Freshness Attacks)。

  这里举个简单的例子:当用户A进行登录后,前台会将加密后的密码,以数据包的形式发送到服务端。服务端会进行盐化等加密手段后,再进行安全校验。可是如果这个数据包被攻击者截获。并且分析出数据包的结构(如哪些字段代表用户名、哪些代表IP/会话ID),然后进行适当的修改,再次发送给服务端后,服务端依然会进行常规的校验,依然会验证通过。也就是说无论客户端,服务端的加密手段多么的复杂,一旦攻击者有能力截获和修改前后台通信的数据包,那么这些加密手段都将不起作用。

那么如何防范呢?仔细想想重放攻击,攻击者利用的是每次发送的包中用户名密码等部分不变的机理。

那么我们可以让他改变,怎么改变呢?

大致思路如下:

1、每次登陆时,我们可以生成一个随机数(一个动态生成的salt),这个salt在前后台各自保存一份。

2、当用户名输入完密码pwd后。前台会进行 f1(pwd)加密,然后与动态生成的salt拼接,然后再次加密。

也就是 pwd1=f2(f1(pwd)+salt)。之后前台就把这个pwd1发送到后台。(注意由于动态salt每次都会改变,所以pwd1每次也会改变)

3、后台拿到数据后,如果没有使用固化盐值加密的话,直接将数据库中的数据采用相同的方式与服务端保存的动态salt拼接加密然后再对比即可。

如果同时存在固化盐值加密的话,需要想办法剔除掉这个动态salt(即f2()使用可逆的机密算法),然后再拼接固化salt接着再次加密,最后与数据库对比即可

参考:https://www.cnblogs.com/birdsmaller/p/5377104.html

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值