建立从头开始的服务器或使用轻量级的框架具有强大的功能。 这种权力带来了责任,尤其是安全存储用户密码的责任。
不了解密码存储的安全隐患可能导致破坏性的破坏和泄漏。 如果要构建应用程序并且需要存储用户凭据,请了解哈希函数。
我可以用纯文本格式存储密码吗?
为了演示潜在的危险,让我们假设我们不要在假的示例网站LoveMatchingToday上哈希密码。 当黑客或心怀不满的员工获得对LoveMatchingToday数据库的访问权限后,他们将不可避免地下载所有用户名和密码:
user.one@gmail.com – somePa $$ wordHere
user.two@hotmail.com – otherPlainTextPass
现在,攻击者可以访问其他网站,并且由于大多数人在不同的网站上重复使用密码,因此他们可以入侵其他系统。
解决方案–散列
一个 哈希函数 (或者更具体地说是在我们的情况下, 密钥导出函数 )确定性从创建密码的强密钥 。 由于哈希是单向的,因此攻击者无法从哈希中重新创建纯文本密码。 现在,攻击者将在数据库中找到类似的内容:
user.one@gmail.com – cab864878af008fbc550087940ffacdb79a7f82201725e3350e25d6cfbdd4255
user.two@hotmail.com – 42a7fd2b639d18b3aba5db8504d4530f1f1ab58ab9615414b7629d6ec5c157b8
他们将无法使用哈希登录其他系统,因为他们无权访问原始密码。
在Python中, Bcrypt是强大的密钥派生函数,可以在生产系统中使用:
<code style="box-sizing: border-box; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; color: rgb(255, 255 , 255 ); background-color: transparent; border: 0 px; padding: 0 px; font-size: 0.85 em; border-radius: 3 px;">import bcrypt
bcrypt.hashpw('userPlainTextPassword'.encode(), bcrypt.gensalt())</code>
彩虹桌和盐
您可能想知道上面的代码片段中gensalt()函数的作用。 如果我们要散列没有盐的密码,则攻击者可以进行彩虹表攻击以找到原始的纯文本。
盐是随密码一起散列的随机数据字符串,以保持散列结果唯一。 每次保存新密码时都应重新创建盐,并将盐与散列结果一起存储,以便可以再次将其用于比较。 像bcrypt之类的库足够聪明,可以将salt存储在结果字符串中,因此开发人员无需执行额外的工作。
例如,让我们说,LoveMatchingToday wisened,并开始散列密码,但不包括独特的盐。 攻击者可能拥有预先计算的哈希表:
aab864878af008fbc550087940ffacdb79a7f82201725e3350e25d6cfbdd425f = password123
afg3683232297323f2f0087940ffacdb79a7f8284723732350e25d6cfbdd4cccc = shadowTheHedgehog1234
然后,他们可以检查找到的每个哈希,并查看哈希是否与表中的条目匹配。 如果是这样,他们可以有效地“反转”哈希并学习原始的纯文本。
因此,我们需要对密码加盐。 幸运的是,Bcrypt自动处理盐分。 但是,为了学习,让我们假设他们没有。 如果没有,我们的伪代码将如下所示:
<code style="box-sizing: border-box; font-family: Consolas, " ;Andale Mono WT " ;, " ;Andale Mono " ;, " ;Lucida Console " ;, " ;Lucida Sans Typewriter " ;, " ;DejaVu Sans Mono " ;, " ;Bitstream Vera Sans Mono " ;, " ;Liberation Mono " ;, " ;Nimbus Mono L " ;, Monaco, " ;Courier New " ;, Courier, monospace; color: rgb( 255 , 255 , 255 ); background-color: transparent; border: 0 px; padding: 0 px; font-size: 0.85 em; border-radius: 3 px;"> # Save new password
salt = creatRandomSalt()
hashedPassword = hash(newPassword.concat(salt))
database.save(hashedPassword, salt)
# Check password
hashedPassword, salt = database.GetUserCredentals()
passwordInput = userInput
if hash(passwordInput.concat(salt)) == hashedPassword:
login()
else:
failure() </code>
但是,由于Bcrypt自动将盐和散列结果以“ {salt} {hashed} ”格式存储,因此我们可以使用以下代码:
<code style="box-sizing: border-box; font-family: Consolas, " ;Andale Mono WT " ;, " ;Andale Mono " ;, " ;Lucida Console " ;, " ;Lucida Sans Typewriter " ;, " ;DejaVu Sans Mono " ;, " ;Bitstream Vera Sans Mono " ;, " ;Liberation Mono " ;, " ;Nimbus Mono L " ;, Monaco, " ;Courier New " ;, Courier, monospace; color: rgb( 255 , 255 , 255 ); background-color: transparent; border: 0 px; padding: 0 px; font-size: 0.85 em; border-radius: 3 px;"> import bcrypt
# password = userInput
hashAndSalt = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
# save "hashAndSalt" in data base
# To check:
# password = userInput
valid = bcrypt.checkpw(password.encode(), hashAndSalt) </code>
谢谢阅读
如果您有任何疑问,请在推特上打我!
先前发布在https://qvault.io/2020/01/29/hashing-passwords-python-cryptography-examples/
From: https://hackernoon.com/hashing-passwords-in-python-bcrypt-tutorial-with-examples-77dh36ef