当前位置:  开发笔记 > 编程语言 > 正文

加密/散列数据库中的纯文本密码

如何解决《加密/散列数据库中的纯文本密码》经验,为你挑选了3个好方法。

继承了一个Web应用程序,我刚刚在SQL Server数据库中以纯文本形式存储了超过300,000个用户名/密码.我意识到这是一件非常糟糕的事情.

知道我必须更新登录和密码更新过程以加密/解密,并且对系统其余部分的影响最小,您会建议从数据库中删除纯文本密码的最佳方法是什么?

任何帮助表示赞赏.

编辑:对不起,如果我不清楚,我打算问你的加密/哈希密码的程序,而不是特定的加密/散列方法.

我应该只是:

    备份数据库

    更新登录/更新密码代码

    几小时后,浏览用户表中记录密码的所有记录并替换每个记录

    测试以确保用户仍然可以登录/更新密码

我想我的关注更多来自于大量的用户,所以我想确保我正确地做到这一点.



1> orip..:

编辑(2016):按优先顺序使用Argon2,scrypt,bcrypt或PBKDF2.尽可能使用适合您情况的减速因子.使用经审查的现有实施.确保使用适当的盐(尽管您正在使用的库应该为您确保这一点).


当您对密码进行散列时,请使用DO NOT USE PLAIN MD5.

使用PBKDF2,这基本上意味着使用随机盐来防止彩虹表攻击,并且迭代(重新散列)足够的时间来减慢散列 - 不要太多,以至于你的应用程序需要太长时间,但足以让攻击者暴力破解大量不同的密码会注意到

从文件:

迭代至少1000次,最好是更多 - 实现时间,看看有多少次迭代是可行的.

8个字节(64位)的盐就足够了,并且随机不需要是安全的(盐是未加密的,我们不担心有人猜它).

在散列时应用salt的一种好方法是使用HMAC和您喜欢的哈希算法,使用密码作为HMAC密钥,使用salt作为哈希文本(请参阅本文档的这一部分).

Python中的示例实现,使用SHA-256作为安全哈希:

编辑:正如Eli Collins所提到的,这不是PBKDF2的实现.您应该更喜欢坚持标准的实现,例如PassLib.

from hashlib import sha256
from hmac import HMAC
import random

def random_bytes(num_bytes):
  return "".join(chr(random.randrange(256)) for i in xrange(num_bytes))

def pbkdf_sha256(password, salt, iterations):
  result = password
  for i in xrange(iterations):
    result = HMAC(result, salt, sha256).digest() # use HMAC to apply the salt
  return result

NUM_ITERATIONS = 5000
def hash_password(plain_password):
  salt = random_bytes(8) # 64 bits

  hashed_password = pbkdf_sha256(plain_password, salt, NUM_ITERATIONS)

  # return the salt and hashed password, encoded in base64 and split with ","
  return salt.encode("base64").strip() + "," + hashed_password.encode("base64").strip()

def check_password(saved_password_entry, plain_password):
  salt, hashed_password = saved_password_entry.split(",")
  salt = salt.decode("base64")
  hashed_password = hashed_password.decode("base64")

  return hashed_password == pbkdf_sha256(plain_password, salt, NUM_ITERATIONS)

password_entry = hash_password("mysecret")
print password_entry # will print, for example: 8Y1ZO8Y1pi4=,r7Acg5iRiZ/x4QwFLhPMjASESxesoIcdJRSDkqWYfaA=
check_password(password_entry, "mysecret") # returns True


人们应该意识到这段代码没有实现PBKDF2算法; 而是旧的PBKDF1功能的非标准变体,修改为使用PRF(在这种情况下为HMAC-SHA256).有关两个kdfs的参考实现,请参见[rfc2898](http://tools.ietf.org/html/rfc2898#page-9).虽然这个算法可能不是不安全的,但它与PBKDF1或PBKDF2不是字节兼容的,它的确切行为也没有给出相同的安全性审查 - 我关注的是它将HMAC应用于固定盐,并且密码而不是 - 这可能会削弱HMAC.
@orip:密码学不是_close足够_通常是一个好主意; 特别是如果人们将其误认为是PBKDF2实现,只是为了稍后发现输出与现有代码/数据不匹配.确实如果代码的盐/密码缺陷是固定的,它将更符合附录,但这只描述了如何使用HMAC _in_ PBKDF2; 而不是PBKDf2如何工作.除了省略变量keylen部分之外,最重要的问题是上面的代码完全省略了PBKDF2中F()函数的XOR部分 - 这是它的前映像阻力的核心.

2> erickson..:

基本策略是使用密钥派生函数用一些盐"哈希"密码.salt和哈希结果存储在数据库中.当用户输入密码时,盐和它们的输入以相同的方式进行散列并与存储的值进行比较.如果匹配,则对用户进行身份验证.

细节决定成败.首先,很大程度上取决于所选择的哈希算法.像PBKDF2这样的密钥派生算法,基于基于散列的消息认证代码,使得在计算上不可行地找到将产生给定输出的输入(在这种情况下,密码)(攻击者在数据库中找到的内容) ).

预先计算的字典攻击使用预先计算的索引或字典,从散列输出到密码.散列很慢(或者它应该是,无论如何),因此攻击者一次性地散列所有可能的密码,并以这样的方式存储索引结果,即给定散列,他可以查找相应的密码.这是时间空间的经典权衡.由于密码列表可能很大,因此有一些方法可以调整权衡(如彩虹表),这样攻击者就可以放弃一点速度来节省大量空间.

使用"加密盐"阻碍了预计算攻击.这是一些使用密码进行哈希处理的数据.它不需要是秘密,它只需要对给定的密码不可预测.对于盐的每个值,攻击者需要一个新的字典.如果使用一个字节的salt,攻击者需要256个字典副本,每个副本使用不同的盐生成.首先,他使用salt查找正确的字典,然后他使用hash输出来查找可用的密码.但是如果添加4个字节怎么办?现在他需要40亿份字典.通过使用足够大的盐,排除了字典攻击.实际上,来自加密质量随机数发生器的8到16个字节的数据是很好的.

通过预先计算表,攻击者可以在每次尝试时计算哈希值.现在找到密码需要多长时间完全取决于散列候选人所需的时间.通过散列函数的迭代来增加该时间.数字迭代通常是密钥导出函数的参数; 今天,许多移动设备使用10,000到20,000次迭代,而服务器可能使用100,000或更多.(bcrypt算法使用术语"成本因子",它是所需时间的对数度量.)



3> xan..:

我想你必须在数据库中为加密密码添加一列,然后在获取当前密码的所有记录上运行批处理作业,对其进行加密(因为其他人提到像md5这样的哈希是非常标准的编辑:但不应该单独使用 - 请参阅其他答案以获得良好的讨论),将其存储在新列中并检查所有内容是否顺利进行.

然后,您需要更新前端以在登录时散列用户输入的密码,并验证是否与存储的散列相比,而不是检查明文与明文.

在最终删除明文密码之前,将两个列保留一段时间以确保没有任何异常发生,这似乎是谨慎的做法.

不要忘记,只要密码被访问,代码就必须更改,例如密码更改/提醒请求.你当然会失去通过电子邮件发送忘记密码的能力,但这不是坏事.您将不得不使用密码重置系统.

编辑:最后一点,您可能要考虑避免我第一次尝试在测试床安全登录网站上犯的错误:

处理用户密码时,请考虑进行散列的位置.在我的例子中,哈希是由在Web服务器上运行的PHP代码计算的,但密码是以明文形式从用户机器传输到页面的!这在我工作的环境中是可以的(ish),因为它无论如何都在https系统内(uni网络).但是,在现实世界中,我想你会想要在离开用户系统之前对密码进行哈希处理,使用javascript等,然后将哈希传输到你的站点.


您无法在用户的计算机上哈希密码.散列必须由可信系统完成.(否则,任何窃取密码表副本的人都可以向您发送哈希值;哈希值已成为密码.)但是,是的,这确实需要来自用户的HTTPS安全传输.
哈希或不哈希.欺骗客户端毫无意义.您使用哈希处理的威胁模型是密码数据库的泄露.如果这不是问题,请不要哈希.否则,您无法使用用户生成的哈希进行身份验证(或从被盗数据库副本中读取).
如果他们关闭了javascript会发生什么?
推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有