什么是用于保护数据库中密码的良好、简单的加密方案?我不一定需要任何超安全的东西,也不需要任何闪电般快速的东西,但那些东西会很好。首先,我只想要一些易于实现而又不会非常缓慢或不安全的东西。
14 回答
正如 mk 所说,SHA1 或 MD5 是标准的,以及 SHA2。
更新:多年来,随着处理器变得越来越快,哈希变得更加暴力。现在建议您使用bcrypt
.
您想要的通常称为加密哈希函数。加密哈希被设计为单向的(给定生成的哈希,您不应该能够导出原始输入)。此外,两个任意字符串具有相同散列(称为散列冲突)的可能性应该很低(理想情况下是 1/散列值的数量)。
不幸的是,仅仅因为您的密码被散列并不能使您免于努力确保散列版本的安全。太多人会使用容易受到离线暴力攻击的弱密码。
编辑 - 一些人也已经指出了使用盐的重要性。盐是在使用散列函数之前与输入混合的常量值。拥有独特的盐可以防止离线攻击者使用预先计算的常用密码表(彩虹表)来更快地暴力破解您的密码。
如果您使用 MD5 或 SHA1,请使用盐来避免彩虹表黑客攻击。
在 C# 中,这很容易:
MD5CryptoServiceProvider hasher = new MD5CryptoServiceProvider();
string addSalt = string.Concat( "ummm salty ", password );
byte[] hash = hasher.ComputeHash( Encoding.Unicode.GetBytes( addSalt ) );
简单:BCrypt。
Jeff 的您可能错误地存储了密码一文是该主题的优秀读物。
这是我几周前的一个问题。我们正在将一个大型 MIS 项目部署到 975 个不同的地理位置,我们自己的用户凭证存储将用作不同组已实施和正在使用的应用程序的身份验证器。我们已经提供了基于 REST 和 SOAP 的身份验证服务,但客户坚持能够从其他应用程序访问用户凭据存储,只需一个数据库连接到相关表或视图的只读视图。叹息...... (这个高度耦合的糟糕设计决策是另一个问题的主题)。
这迫使我们坐下来将我们的加盐和迭代哈希密码存储方案转换为规范,并提供一些不同的语言实现以便于集成。
我们简称它为相当安全的散列密码或FSHP。在 Python、Ruby、PHP5 中实现它并将其发布到公共领域。可在http://github.com/bdd/fshp上的 GitHub 上消费、分叉、燃烧或吐出
FSHP 是一种加盐的、迭代散列的密码散列实现。
设计原理与RFC 2898 中 的PBKDF1规范(又名:PKCS #5:基于密码的加密规范 2.0 版) 类似。FSHP 允许在 SHA-1 和 SHA-2 中选择盐长度、迭代次数和底层加密哈希函数(256、384、512)。在每个输出的开头自定义元前缀使其可移植,同时让消费者选择自己的密码存储安全基线。
安全:
默认 FSHP1 使用 8 字节盐,SHA-256 散列的 4096 次迭代。- 通过将所需空间乘以 2^64,8 字节盐使彩虹表攻击变得不切实际。- 4096 次迭代导致蛮力攻击相当昂贵。- 在此版本发布时,没有已知的针对 SHA-256 的攻击可以通过少于 2^128 次操作的计算工作来发现冲突。
实现:
- Python:使用 2.3.5(带 hashlib)、2.5.1、2.6.1 进行测试
- Ruby:用 1.8.6 测试
- PHP5:用 5.2.6 测试
非常欢迎每个人创建缺失的语言实现或完善当前的实现。
基本操作(使用 Python):
>>> fsh = fshp.crypt('OrpheanBeholderScryDoubt')
>>> print fsh
{FSHP1|8|4096}GVSUFDAjdh0vBosn1GUhzGLHP7BmkbCZVH/3TQqGIjADXpc+6NCg3g==
>>> fshp.validate('OrpheanBeholderScryDoubt', fsh)
True
自定义地穴:
让我们削弱我们的密码散列方案。- 将盐长度从默认的 8 减少到 2。 - 将迭代轮次从默认的 4096 减少到 10。 - 选择具有 SHA-1 的 FSHP0 作为底层哈希算法。
>>> fsh = fshp.crypt('ExecuteOrder66', saltlen=2, rounds=10, variant=0)
>>> print fsh
{FSHP0|2|10}Nge7yRT/vueEGVFPIxcDjiaHQGFQaQ==
将SHA单向散列算法与唯一盐一起使用。这是我用于将密码存储在数据库中的主要算法。
如果您使用的是 SQL Server,则有 HashBytes 函数:
我用盐支持 MD5 或 SHA 的投票。任何主要的 Web 开发语言都具有用于计算哈希的内置函数(例如,在 PHP 中,mcrypt 包包含必要的函数)。
您需要使用单向哈希算法,如上面建议的 SHA-1 和盐。我会建议这个网站以获取更多信息。它包括一些示例代码/实现。 http://www.obviex.com/samples/hash.aspx
我认为,提高安全性的关键是使用动态盐。这意味着您为每个新用户生成一个随机字符串,并使用该字符串对哈希进行加盐。当然,您需要将这个盐存储在数据库中,以便以后能够验证密码(我没有以任何方式对其进行加密)。
对于不可逆加密,我绝对会使用 SHA256 或 SHA1。MD5现在有很多碰撞,并且已经付出了很多努力来破解它,所以不是一个好用的。
如果您想使您的解决方案面向未来,我建议您使用 SHA256 或 SHA512。Cryptographic geekworld 对 MD5 感到不安,对 SHA1 的担忧程度略低。
或者,如果可以,请等待SHA-3
我注意到关于如何正确进行密码散列的很多困惑,尤其是在 stackoverflow 上。所以我写了一个应该清除所有内容的页面。除了使用简单的哈希之外,还有更多内容。
更多信息:如何正确进行密码散列