非随机盐用于密码哈希

12 浏览
0 Comments

非随机盐用于密码哈希

更新:我最近从这个问题中得知,在下面的讨论中,我(我相信其他人也是)有些混淆:我一直称为彩虹表的东西实际上被称为哈希表。彩虹表是更复杂的实体,实际上是Hellman哈希链的一种变体。尽管我认为答案仍然是一样的(因为它并不涉及密码分析),但讨论可能有些偏差。

问题是:“什么是彩虹表,它们是如何使用的?


通常,我始终建议使用具有密码学强度的随机值作为盐,与哈希函数(例如密码)一起使用,以防止彩虹表攻击。但是盐是否真的需要具有密码学意义上的随机性呢?任何唯一值(每个用户唯一,例如用户ID)是否足够?实际上,它确实可以防止使用单个彩虹表来破解系统中的所有(或大多数)密码...

但是缺乏熵真的会削弱哈希函数的密码学强度吗?


请注意,我不是在询问为什么要使用盐,如何保护它(不需要保护),使用单个常量哈希(不要使用),或者使用什么类型的哈希函数。

只是盐是否需要熵。


感谢大家迄今为止的答案,但我希望专注于我(有点)不太熟悉的领域。主要是密码分析的影响-如果有人从密码数学的角度提供一些意见,我会非常感激。

此外,如果还有其他未被考虑的因素,那也是很好的意见(请参见@Dave Sherohman关于多个系统的观点)。

除此之外,如果您有任何理论、想法或最佳实践,请通过证据、攻击场景或经验证据来支持。或者甚至对可接受的权衡考虑给出有效的观点...我熟悉该主题的最佳实践(大写B大写P),我想证明这实际上提供了什么价值。


编辑:这里有一些非常好的答案,但我认为正如@Dave所说,这归结为常见用户名的彩虹表...以及可能是较少见的用户名。然而,如果我的用户名是全局唯一的呢?不一定是对于我的系统来说是唯一的,但对于每个用户来说是唯一的-例如电子邮件地址。

没有动机为单个用户构建彩虹表(正如@Dave强调的,盐并不是保密的),这仍然可以防止聚类。唯一的问题可能是我在其他网站上可能有相同的电子邮件和密码-但盐无论如何也不能防止这种情况。

所以,问题又回到密码分析-熵是否必要?(我目前的想法是从密码分析的角度来看,它并不是必要的,但从其他实际原因来看,它是必要的。)

0
0 Comments

非随机盐值用于密码哈希的原因是为了提高密码的安全性。如果用户名的熵不足够高,例如用户名较短,将用户名与密码相结合可能导致密码易受彩虹表攻击。此外,如果攻击者创建了一个包含最常见用户名的彩虹表,他们可以使用这些用户名的盐值来破坏用户账户。

为了解决这个问题,以前使用的12位盐值已经不再安全,因为现在可以轻松存储如此多的信息。同样,对于最常用的4096个用户名,很可能有一些用户会选择这些用户名作为自己的用户名。

为了评估密码的熵,可以使用密码检查器。如果密码的熵较低(例如使用用户名作为密码的一部分),则彩虹表更容易破解,因为它们通常尝试破解所有熵较低的密码。

然而,有用户指出,要覆盖所有可能的gsMyPassword长度(假设使用大小写字母和数字),需要在彩虹表中存储36^12行。对于分布式彩虹表项目来说,他们已经破解了63970个哈希,但36^12等于4738381338321616896!

另外,使用用户名作为盐值也是一个坏主意,特别是对于那些具有可预测命名的高权限账户的系统,比如Windows的"Administrator",*nix的"root",MSSQL的"sa"等。

然而,在大多数应用程序和业务系统中,并没有内置的"Administrator"、"root"等账户。

"高熵盐值"并不会增加搜索空间,因为"盐值部分"总是已知的。举个例子,如果使用4096位盐值和8位密码,只要你知道盐值,你的搜索空间仍然是256。

0
0 Comments

问题的出现原因是因为用户在不同网站上可能会共享用户名,这可能导致密码哈希的不安全性。解决方法是使用非随机盐(salt)来增加密码哈希的安全性。

非随机盐是一种将固定值与密码组合在一起进行哈希的方法。在这种方法中,将网站的URL、用户名和密码组合在一起进行哈希运算,以确保每个网站的密码哈希值都是唯一的。这种方法可以防止用户在不同网站上使用相同的用户名和密码。

以下是使用非随机盐的示例代码:

import hashlib

def hash_password(username, password, website_url):

salt = website_url + "/" + username + "/"

hashed_password = hashlib.sha256(salt.encode() + password.encode()).hexdigest()

return hashed_password

website_url = "www.yourpage.com"

username = "user123"

password = "password123"

hashed_password = hash_password(username, password, website_url)

print(hashed_password)

使用非随机盐可以提高密码哈希的安全性,因为即使用户在不同网站上使用相同的密码,由于盐值的不同,哈希值也会不同。这样即使黑客获取了一个网站的密码哈希值,也不能轻易地破解其他网站的密码。

尽管使用非随机盐可以提高密码哈希的安全性,但仍然需要注意密码哈希算法的选择和密码的复杂性。密码哈希算法应选择安全性较高的算法,并且密码应该足够复杂以抵御常见的猜测攻击。

使用非随机盐是一种增加密码哈希安全性的有效方法,尤其是在用户在不同网站上使用相同用户名的情况下。尽管可能存在未来密码哈希算法被破解的风险,但使用非随机盐可以增加密码的安全性。

0
0 Comments

非随机盐用于密码哈希的原因是为了增加密码的安全性。传统上,盐是作为哈希密码的前缀存储的,这使得任何具有密码哈希访问权限的攻击者都能知道它。使用用户名作为盐或不使用都不会影响单系统安全性。然而,使用用户名或任何其他用户可控的值作为盐将降低跨系统安全性,因为在使用相同密码哈希算法的多个系统上,用户名和密码相同的用户将在每个系统上得到相同的密码哈希值。这并不是一个重大的安全问题,因为作为攻击者,我会首先尝试已知目标账户在其他系统上使用过的密码,而不是尝试其他任何攻击手段来破坏账户。相同的哈希值只会提前告诉我已知密码将起作用,但并不会使实际攻击变得更容易。(注意,尽管如此,快速比较账户数据库将提供一个更高优先级目标的列表,因为它会告诉我谁是和谁不是重复使用密码的人。)

这个想法的更大危险是用户名通常会被重复使用 - 例如,你访问的任何网站上都会有一个名为“Dave”的用户账户,“admin”或“root”更是常见 - 这将使得构建针对那些常见用户名的彩虹表变得更容易和更有效。

这些缺陷都可以通过在哈希密码之前添加第二个盐值(可以是固定和隐藏的,也可以像标准盐一样公开)来有效解决,但是在这一点上,与其将用户名作为盐值,不如直接使用标准的熵盐值。

不少人都在谈论熵以及熵在盐值中的重要性。熵是重要的,但原因与大多数关于它的评论所认为的原因不同。

一般的想法是,熵很重要是为了使攻击者难以猜测盐值。这是不正确的,事实上,完全无关紧要。正如一些人多次指出的那样,只有拥有密码数据库的人才能进行受盐影响的攻击,而拥有密码数据库的人可以轻松查看每个账户的盐值。当你可以轻易地查看盐值时,无论它是否可猜测都无关紧要。

熵的重要性在于避免盐值的聚集。如果盐值基于用户名,并且你知道大多数系统将有一个名为“root”或“admin”的账户,那么你可以为这些两个盐值制作彩虹表,并且它将破解大多数系统。另一方面,如果使用随机的16位盐值且随机值具有均匀分布,那么你需要为所有可能的2^16个盐制作彩虹表。

这不是为了防止攻击者知道每个账户的盐值是什么,而是为了不给他们提供一个大大的目标,即在大部分潜在目标中将使用的单个盐值。

同意。我更加强调用户名的重复使用,因为我认为这是最有可能成功攻击使用用户名作为盐的假设系统的攻击,而这种攻击在使用随机盐的系统中会失败。

我理解你对跨系统安全性的看法。另外,我认为将来可能会出现用户特定的彩虹表...

你这么认为吗?这是一个非常具体的攻击向量。

不,例如,如果你想要使用被破坏的账户发送垃圾邮件,你不在乎账户名是什么。

我指的是使用用户名作为盐值是一个非常具体的攻击向量。

不,这不是一个攻击向量,这是我要问的问题-这样做是否足够好?跨系统安全性是需要考虑的一个因素。

在这种情况下,是否值得投资额外的时间来使用加密安全的随机数生成器?任何随机数生成器都可以防止用户登录冲突。

对于生成盐值来说,不需要。只有那些直接针对哈希密码的攻击才会受到盐值的影响。攻击者不可能进行这种攻击,除非他们拥有你的密码数据库,而密码数据库也将包含盐值。由于攻击者已经拥有盐值,他们只需要足够的熵来避免多个密码使用相同的盐值,而任何基本的(伪)随机数生成器都可以提供这种熵。

第三句应该以“攻击者”开头。

那么,将盐值前缀存储在密码中是否安全?例如,如果我将密码存储为passhash = md5("urhu2389udfcbdvalk" + UserPassword),那是否安全?

对于所有密码使用单个固定盐值(通常在我的经验中称为“nonce”)比为每个密码使用唯一的随机盐值来说,安全性较低,因为它仍然允许攻击者轻松确定两个或更多账户是否共享相同的密码。另一方面,这个nonce很可能存储在你的代码中,而不是数据库中,所以只有仅仅拥有你的数据库的攻击者是不能访问它的。因此,最安全的选择是同时使用系统级的nonce(存储在代码中)和每个密码的盐值(存储在数据库中)。

对于最后一段的解释点赞。它让我理解了为什么需要每个用户使用不同的盐值,而不是单独使用的盐值。

非常有启发性,根据这些建议,我找到了一个非常好的Java库,可以实现你所建议的:jasypt.org/encrypting-passwords.html

使用用户名还会导致与密码之间不必要的耦合,因此你不能再创建一个“更改用户名”的功能,而无需再要求输入密码。

0