我有一个关于密码哈希的问题。我找到了关于http://crackstation.net/hashing-security.htm的精彩教程。这是我使用以下代码从密码创建哈希的方法:
$hashed_password = create_hash(form_password);
此代码的问题在于它每次都为同一密码创建不同的哈希。我想这是因为在密码中添加了一个随机盐:
function create_hash($password)
{
// format: algorithm:iterations:salt:hash
$salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" . $salt . ":" .
base64_encode(pbkdf2(
PBKDF2_HASH_ALGORITHM,
$password,
$salt,
PBKDF2_ITERATIONS,
PBKDF2_HASH_BYTES,
true
));
}
因此,我无法将登录时用户输入的密码创建的哈希值与从数据库中检索到的哈希值进行比较,因为该哈希值与数据库中存储的哈希值不会相同。我认为可以做到的唯一方法是将盐存储在另一列中,或者我错了吗?
一件事也让我烦恼。 hast的格式是例如SHA256:1000:u9p + OqAZgVkIBtlTBkr9ZxhFvtt + zjcA:PvhJY + oesrdBeD5pjeXMQ / 3wficCU0EG。黑客显然知道这种形式的哈希,所以创建这个哈希的算法对他来说是清楚的。假设数据库已被泄露,并且显示了数千个这些哈希码。没有这种形式的哈希代码会引发安全问题吗?我想一个简单的OqAZgVkIBtlTBkr9ZxhFvtt + zjcA:PvhJY + oesrdBeD5pjeXMQ / 3wfic会更好,因为它没有揭示加密机制。
答案 0 :(得分:4)
它解释了有关使用随机盐的更多信息。关键信息是随机盐存储在与散列密码相同的数据库中。当用户创建或更改密码时,它只会随机创建几次。无论何时需要身份验证,都会使用它。
留下有关用于创建密码哈希的算法的信息,您可以选择在将来的某个时间更改算法,而不会中断您的用户。如果您决定升级哈希算法,则需要等到用户登录。此时,您的密码将以纯文本形式显示。对旧算法进行身份验证后,将rehash并将新哈希存储在其数据库行中。所有用户登录可能需要数月或数年,但一旦他们拥有,他们将获得更好的散列的好处。因此,您会发送一封电子邮件,要求他们登录并阅读有关更好安全性的特殊新闻(以及副作用,改进他们的哈希密码)。
的有趣讨论答案 1 :(得分:3)
同一密码的两个哈希值不匹配的原因是因为create_hash()
的结果包含随机生成的salt。
要获得相同的哈希值,您必须在验证时提供salt。 CrackStation.net提供的代码使这非常简单 - 只需将create_hash()
的结果存储在您的数据库中即可。要确认用户输入了正确的密码,请使用
validate_password('provided-password','hash-from-database');
这将返回密码是否正确的布尔值。使用此方法比编写自己的方法更好,因为它专门用于根据返回答案所花费的时间来防止对正确密码的某些提示。这是一个小小的弱点,但无论如何最好还是避免它,特别是因为提供的功能会为你处理它。
所提供的功能为您提供了可靠的实施方案,因此请不要过多地使用它。散列包括那些额外的细节 - sha256:1000 - 以便将来允许更改散列而不影响现有用户登录的能力;它将简单地使用散列中提供的方法,无论当前的方法是什么。
至于向潜在的攻击者展示如何创建哈希:格式确实显示了如何做,但这根本不重要。攻击者可以轻松找出使用一个或两个已知密码的方法:哈希对。比这更重要的是使用一个好的算法。目标是即使有了所有细节也难以破解密码,因为默默无闻的安全性很差。
最后,重申一下,你不需要将盐存储在一个单独的列中,只需将它返回的70-80字符大块保留为哈希值,让函数为你处理所有事情 - 其他任何事情是浪费时间和资源
答案 2 :(得分:1)
要为优秀的答案添加更多内容:
关于腌制哈希的观点是让某人无法携带大量预先加密的哈希值并逐一尝试。即使在数据库中使用salt,他们也必须对每个可能的字典条目进行哈希处理以成功匹配哈希值。并且盐每次都需要不同以防止重复条目(它们破解一个密码,它们具有与其他用户输入的密码相同的密码)。
至于无法将登录哈希值与存储的哈希值进行比较,这是故意的:您使用验证函数根据存储的密码检查登录密码,而不是字符串比较函数。
答案 3 :(得分:1)
存储salt然后将salt添加到密码中,然后将其转换为哈希值,然后存储它。
然后比较你检索盐的密码并将其添加到密码中,将其转换为哈希值,然后比较两个哈希值。
(例如,当我从代码中复制代码时,缩进就搞砸了)
def Createpassword():
import random
import hashlib
username = input("type your username")
newpassword = input("type your new password? ")
#adds some salt
b = random.randint(1, 2000000000000)
randomsalt = str(b)
saltedpassword = (newpassword + randomsalt)
#hashes the newpassword
saltedpassword = saltedpassword.encode('utf-8')
h = hashlib.sha256(saltedpassword)
finsh = h.hexdigest()
#creates file names
saltname = username + "salt.txt"
username = username + ".txt"
#saves the hashedpassword and the salt
text_file = open(username, "w")
text_file.write(finsh)
text_file.close()
text_file = open(saltname, "w")
text_file.write(randomsalt)
text_file.close()
print("your new password has been saved")
def EnterPassword():
trys = 0
while (trys < 3):
username = input("type your username: ")
#takes password input
password = input("type your password: ")
#gets file names
saltname = username + "salt.txt"
username = username + ".txt"
#opens salt file
text_file = open(saltname, "r")
salt1 = text_file.read(50)
text_file.close()
#opens the hashed passwords file
text_file = open(username, "r")
correctpassword = text_file.read(500)
text_file.close()
#adds the salt to the password input
saltedpassword = password + salt1
#hashes the saltedpassword
saltedpassword = saltedpassword.encode('utf-8')
m = hashlib.sha256(saltedpassword)
hashedpassword = m.hexdigest()
#compears hashed passwords
if hashedpassword != correctpassword:
trys += 1
print("your password or username is incorrect")
if trys == 3:
print("you have been locked out for using to many failed trys")
if hashedpassword == correctpassword:
print ("Password Correct ")
#done give access
trys = 0
break
(我是编程新手所以随时纠正我)