密码加密

密码在服务器一般不能明文存储,这样做的好处是即使用户数据表泄漏,攻击者也无法通过逆操作还原出用户密码。

Hash

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预哈希, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。具有单向的特点。

Hash的基本性质

  1. 如果两个hash是不相同的(根据同一函数),那么这两个hash的原始输入也是不相同的。
  2. Hash函数的输入和输出不是一一对应的,如果两个散列值相同,两个输入值很可能是相同的。
  3. Hash函数是从一个非常大的取值空间映射到一个非常小的取值空间,由于不是一对一的映射,HASH函数转换后不可逆,即不可能通过逆操作和HASH值还原出原始的值,受到计算能力限制(注意,不是逻辑上不可能,前面的不可能是逻辑上的)而且也无法还原出所有可能的全部原始值。

这里我们总结出hash对于我们密码加密非常有用的两个特性:

  • 不可逆 即hash过程过程不可逆,你不可以通过hash后的值得到原值。
  • 无冲突 你知道一个值(x),但无法求出另一个值(y),使这两个值得hash值相同。

以上性质对于对于密码加密而言就是:

  1. 原始密码经哈希函数计算后得到一个哈希值
  2. 改变原始密码,哈希函数计算出的哈希值也会相应改变
  3. 同样的密码,哈希值也是相同的
  4. 哈希函数是单向、不可逆的。也就是说从哈希值,你无法推算出原始的密码是多少

常用的hash实现

MD5

它对输入仍以512位分组,其输出是4个32位字的级联

SHA-1 SHA256

它对长度小于264的输入,产生长度为160bit的散列值

hash算法加盐

密码中混入一段“随机”的字符串再进行哈希加密,这个被字符串被称作盐值

为什么要加盐

同一个密码经过哈希算法后得到的密码是一致,攻击者可以通过建立一个密码和哈希机密后的表的对应关系的表提高破解效率。

如果加盐,这使得同一个密码每次都被加密为完全不同的字符串。为了校验密码是否正确,我们需要储存盐值。通常和密码哈希值一起存放在账户数据库中,或者直接存为哈希字符串的一部分。

每次哈希加密都使用相同的盐值是很容易犯的一个错误,这个盐值要么被硬编码到程序里,要么只在第一次使用时随机获得。这样加盐的方式是做无用功,因为两个相同的密码依然会得到相同的哈希值。

用户创建账户或每次修改密码时,都应该重新生成新的盐值进行加密。

慢哈希

加盐使攻击者无法采用特定的查询表和彩虹表快速破解大量哈希值,但是却不能阻止他们使用字典攻击或暴力攻击。高端的显卡(GPU)和定制的硬件可以每秒进行数十亿次哈希计算,因此这类攻击依然可以很高效。为了降低攻击者的效率,我们可以使用一种叫做密钥扩展的技术。

这种技术的思想就是把哈希函数变得很慢,于是即使有着超高性能的GPU或定制硬件,字典攻击和暴力攻击也会慢得让攻击者无法接受。最终的目标是把哈希函数的速度降到足以让攻击者望而却步,但造成的延迟又不至于引起用户的注意。这里推荐一种标准算法:bcrypt

这类算法使用一个安全因子或迭代次数作为参数,这个值决定了哈希函数会有多慢。对于桌面软件或者手机软件,获取参数最好的办法就是执行一个简短的性能基准测试,找到使哈希函数大约耗费0.5秒的值。这样,你的程序就可以尽可能保证安全,而又不影响到用户体验。

results matching ""

    No results matching ""