修改
我碰到了这个,因为我还没有一个确定的答案(不过有一个或两个很接近)。我要寻找的基本上是是或否答案,并提供一些信息来备份它。
我们有一个系统,该系统存储由数据库中的通用系统密钥加密的用户密码。如果具有数据库访问权限的人掌握了该系统密钥,那么(显然)可能会造成灾难性的后果。
我们现在知道的正确方法(根据大多数(?))是将PW的盐化哈希存储在数据库中,但相对接近我们想要发布的版本尽量减少代码更改,因此防止他人从DB读取PW的一种非常简单的方法是简单地逆转过程并切换参数。
也就是说,我们将使用用户密码作为密钥来加密每个系统(数百个)唯一的咸字符串(每个加密中添加了随机尾部),并将结果存储在数据库中。在PW验证中,我们将使用输入的PW解密存储在数据库中的字符串,并与系统密钥匹配以进行验证。
System key+random
使用password
存储在数据库encrypted key
中进行加密。
即用户的密码永远不会被存储,并且以我们简单的头脑是无法挽回的。
但是作为加密领域的新手,我们想知道在该领域有更多经验的人是否可以回答简单问题-
是否可以从原始字符串和加密字符串中找出密钥?
我们认为这是一种 brilliant ;)方式,可以确保用户密码不被泄露,但无法在线找到该方法。这使我们不确定,因此询问了这个很棒的社区。 p>
(而强力并不是一个适当的答案,因为(在这种情况下)无法避免。)
修改:
我将在此处粘贴我的评论之一,以(希望)使一些事情变得更清楚:
@zaph感谢您的输入,但我认为大多数人都没有在这里指出要点。我们将在几天后冻结代码以用于即将发布的版本,并且我已经实现了我在问题中提到的方法。在下一个发行版之前,我将继续学习该主题并实现scrypt或类似的第三方库。我真的只需要知道是否存在可行的算法来逆转该过程,从而使我的新实现比旧的加密密码方法更糟糕。
答案 0 :(得分:6)
我们有一个系统,该系统存储由数据库中的通用系统密钥加密的用户密码。
这是非常不好的做法,因为密码可能是可逆的。根据我的经验-数据泄漏和您可能发生的灾难性情况变为现实只是时间问题。
我们现在知道的正确方法(根据most(?))是将PW的盐化哈希存储在数据库中,
当今最好的选择是使用“慢散列”,请参阅https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords/31846#31846
在PW验证中,我们将使用输入的PW解密存储在数据库中的字符串,并与系统密钥匹配以进行验证。
有问题。一旦系统密钥泄漏(或由内部人员使用),所有密码都可能遭到破坏。使用散列更为安全(并且代码之间的差异不应太大)。
是否可以从原始字符串和加密字符串中找出密钥?
使用任何当前的现代密码,当前无法基于对明文和加密值的了解来计算/猜测加密密钥。
答案 1 :(得分:4)
很抱歉,但是大多数人都会这么做,并使用bcrypt或scrypt之类的密码将密码散列成盐。尝试使用一些著名的流行库使事情变得更快捷,更轻松(如果需要帮助,请注意一下)。
是的,您所描述的听起来像是安全的,但是正如@ gusto2所提到的,您将没有足够的熵来进行安全加密,从而迫使您使用密钥派生方案。
使用密钥派生方案的唯一问题是,密钥派生基本上是一种特殊的哈希,在这种情况下,您应该只选择第一个选项,然后做其他人都可以做的事情。
答案 2 :(得分:2)
根据要求:“来自可靠和/或官方来源的答案” -国家标准技术研究院。
NIST Digital Identity Guidelines第15页: ...验证程序应以能抵抗脱机攻击的形式存储存储的机密。使用适当的单向密钥推导功能,应将存储的机密加盐并散列。密钥派生函数将密码,盐和成本因素作为输入,然后生成密码哈希。
该盐必须是加密安全的,并且对于每个密码都是唯一的,它可以(通常)与哈希密码一起保存。成本因素应在1us CPU(不经过)时间范围内。成本因素也可以与密码一起保存,因此将来可以根据需要进行更新。
关键是使攻击者花费大量时间通过蛮力查找密码。
具有类似属性的其他函数包括PBKDF2
,Rfc2898DeriveBytes
,Argon2i
,password_hash
,Bcrypt
。
针对:蛮力是不恰当的答案,因为(在这种情况下)无法避免。
这正是必须而且可以防御的攻击类型。当前的最佳实践是要求每次尝试都唯一且耗时。因此,随机盐和〜100ms的迭代。因此,针对用户哈希密码的尝试密码的每次尝试都需要大量时间。在Dark Web中进行销售攻击需要大量用户凭据,因此大多数密码必须被强行盗窃才能获利。
针对:我真的只需要知道是否存在可行的算法来逆转该过程,从而使我的新实现比旧的加密密码方法更糟糕。
是的,建议的方法极易暴露大多数用户密码。这不是一个比现有方法好还是坏的问题,而是一个通过现行做法保护用户凭据以保护用户和您的责任的问题。
针对OP提出的解决方案的潜在攻击:
我之前曾发布过一种可能且简单的攻击,这里又是一次攻击:获取数据库和系统密钥以进行验证。从frequent passwords列表中选择一个条目,然后尝试使用系统密钥。这非常快,不到一微秒,因此可以很快找到大多数密码。常规攻击无需查找所有密码,只需找到足够高的百分比即可在Dark Web上出售用户信息和密码。
答案 3 :(得分:2)
很抱歉在最近几个小时内进入赏金计划,但是我有一些重要的想法可做。
首先,我在这里没有看到对OWASP的引用。他们可能是最大的软件安全社区,您应该经常检查他们的建议,不仅是密码保护,还包括其他任何安全主题。他们每年都会发布一个名为“ OWASP Top 10 ”的文档,其中列出了最常见的Web应用程序漏洞。
根据去年的OWASP Top 10,您要缓解的风险是列表中的#3,即“ 敏感数据暴露”。例如,它不仅适用于密码,还适用于敏感数据,例如信用卡号。对于您的问题中描述的问题,我想重点介绍第三个攻击方案示例:
方案#3:密码数据库使用无盐或简单的哈希来 存储每个人的密码。文件上传漏洞使攻击者能够 检索密码数据库。所有未加盐的散列都可以暴露 带有彩虹表的预先计算的哈希值。散列由 即使简单或快速的哈希函数也可能会被GPU破解 被腌了。
为防止此类攻击(有时称为“彩虹攻击”),以下是OWASP的建议:
- 对应用程序处理,存储或传输的数据进行分类。根据隐私法,法规确定哪些数据敏感 需求或业务需求。
- 按照分类应用控件。
- 不要不必要地存储敏感数据。尽快将其丢弃,或使用符合PCI DSS的标记或什至截断。 未保留的数据无法被盗。
- 确保对所有敏感数据进行加密。
- 确保采用最新且强大的标准算法,协议和密钥;使用适当的密钥管理。
- 使用具有完美前向保密(PFS)密码的安全协议(例如TLS)加密传输中的所有数据,并通过 服务器和安全参数。使用指令实施加密 例如HTTP严格传输安全性(HSTS)。
- 对包含敏感数据的响应禁用缓存。
- 使用具有工作因数(延迟因数)(例如Argon2,scrypt,bcrypt或工作因数(延迟因数)的强大自适应和盐化哈希函数来存储密码 PBKDF2。
- 独立验证配置和设置的有效性。
它们都是平等的,但是对于您的用例,请特别看一下#8和我在其中包含的链接。总之,您需要具有工作因子的 strong自适应盐腌哈希函数 。
此外,不要忘记在生产环境中定期运行penetration tests (pen tests)。这非常重要。
如果您想开始测试/验证Rainbow攻击防御,则OWASP提供了一个名为“ OWASP Rainbow Maker”的工具。
OWASP Rainbow Maker是旨在破坏哈希签名的工具。它 允许测试人员插入哈希值以及可能的关键字和值 可能被应用程序用来创建它,然后它尝试 多种组合以查找用于生成哈希的格式 值。
我希望它能有所帮助,如果您有任何问题,请在评论中提出。
答案 4 :(得分:0)
我认为gusto2有点像OTT,尽管虽然它比您尝试替换的主密码解决方案要好,但仍然远远不能接受。
crypt works in DES mode或多或少。但是,在您的实现中,每个用户没有使用唯一的盐,当两个用户使用相同的密码时,这将很明显(为哈希切换可逆加密并不能减轻它)。您可能正在使用具有更多比特的更好算法,但是您的实现落后于40年历史的技术。
答案 5 :(得分:0)
正如其他用户所建议的那样,您不应在数据库中存储可解密的密码,因为如果密钥泄露(或管理不善,组织中的任何人用于欺诈目的),则可能会导致灾难性的后果。
作为一种安全标准方法,passwords should NEVER be retrievable by the database通过主密钥或密码恢复方法。如果攻击者要获得对应用程序源或数据库的访问权限,他们仍将很难窃取用户的身份,因为他们可能无法检索用户的密码。
因此,您的方法可以为每个用户使用 per system (hundreds of them) unique salted string (with a per encryption added random tail)
,将其存储在数据库中,并将用户的密码输入用作哈希盐(而不是密钥,如您建议)。此方法与您的方法的区别在于,您不会解密存储的哈希,而是将用户输入生成的哈希与存储的哈希进行比较。
Here's和other resources上的一些password management,您可以阅读这些内容以确保用户的隐私。
答案 6 :(得分:-1)
在一个快速的google上,我找到了这个Stack Exchange thread。
尝试找出基于明文和密文的密钥称为Known-plaintext attack。大多数加密算法都不容易受到这种攻击。