Safe way to store decryptable passwords
我正在用PHP开发一个应用程序,有一个要求是必须能够解密密码,以避免将来将用户数据库切换到不同系统时出现问题。考虑到不可能修改未来系统的密码方法,我需要纯文本密码才能生成密码。
计划是用存储在服务器上的公钥加密用户的密码。身份验证是通过加密输入并比较结果来完成的。没有解密完成。能够解密的私钥存储在非现场供以后使用。
您建议使用什么加密/解密算法?当您认为私钥对攻击者不可用时,加密的密码是否仍然像哈希(MD5/SHA1)一样安全?
- MD5和SHA1不是加密,而是哈希。你说的是加密还是哈希?
- 在散列上下文中,您谈论的是什么类型的"私钥"?你是说GPG/PGP吗?
- 为什么使用哈希会对移动到其他系统产生不利影响?
- @Matti Virkkennen和Erenon:问题是"密码是否仍然和MD5/SHA1一样安全"…当存储可解密的密码,但私钥存储在其他地方(对于Web服务器完全不可访问?)
- 如何在何处生成密码的加密版本?这是一个完全分离的过程吗(在一台单独的机器上)?或者用户会生成它并提交加密的密码和他们的公钥?还是…?
- @沃尔克,我不知道你为什么要使用非对称密码术来存储密码。这违反了CWE-257。
- 我说的是加密,而不是散列,以便自己能够访问纯文本密码,以便将来传输到新系统,我不想修改这些密码来支持任何旧的密码方案!加密和存储将在Web服务器中完成,所有身份验证将通过加密完成。解密留在那里,以便有一天可以使用纯文本密码。我知道这并不是一个"更好"的方法,但是如果你认为私钥不能被窃取…风险是什么?
- @干扰机违反了CWE-257。
- 风险在于,如果有人得到了您的数据库,他们也可能得到您的私钥,然后他们就拥有了您的所有密码,而不需要做额外的工作。
- @布兰登的问题是,他们将无法访问私钥,因为它存储在USB驱动器上,在我切换到其他系统之前不会被使用。
- 如果服务器获得了对密钥的访问权(它需要验证密码),那么其他任何人也可以获得访问权。
- @杰默:这就是为什么我想知道如何,在哪里,什么时候你计划创建加密的密码。你需要私人钥匙,不是吗?还有一个问题:"谁提出了这个要求?"也就是说,"我们"必须说服谁,否则(什么样的论点更有可能令人信服)?
- @volkerk@poke也许我应该澄清一下,我正在寻找公共/私有加密解决方案,其中加密是用公钥完成的,解密是用私钥完成的。服务器将只包含公钥和对加密值进行的身份验证。
- 好的,哪一个是公开的,哪一个是私人密钥并不重要。不知何故,在某个时候,您必须第一次存储加密的密码。对于一个新用户,该场景是什么?也就是说,我们是"只"谈论"CWE-257"还是有其他问题?(只是为了记录:我也反对存储可逆密码。关键在于是否还有其他问题使这项工作变得毫无意义。因为到目前为止,我们似乎还没有说服干扰机。)
- @Volkerk新用户注册到站点,站点用密钥A加密他的密码并将其存储到数据库中。当用户登录到站点时,密码将再次用密钥A加密,并与存储值进行比较。密钥B(解密密钥)是在Web系统发生更改时使用的,因此在更改之前,它将存储在一个保险箱中。
- 如果需要更改密码存储系统,则可以在用户下次登录时更新密码哈希。
- @干扰机使用消息摘要功能,它是唯一安全的密码存储方法。
- AfaikMD5和Sha1散列函数在每个系统上都是相同的,因此切换到另一个数据库并不是使用不同功能的原因。
- 生成一个解密密码的算法,或者在插入密码时在数据库中对其进行哈希处理。
我重新表述干扰器的方法-
生成公钥/私钥对。硬编码Web服务器上的公钥。将私钥存储在物理银行储物柜中,不在webserver/database/any developer可访问的范围内。
当用户注册时,使用公钥加密密码+salt。此步骤与使用哈希算法相同。将加密的密码+salt存储在数据库中。
当您想要验证密码时,再次对其进行加密,并将其与数据库中存储的值进行比较。
如果攻击者获得了数据库,他就不能解密密码,因为他没有私钥。他拿不到那把私人钥匙,因为它在他够不到的银行金库里。由于salt的存在,两个相同的密码在数据库中的存储方式仍然不同。
我不建议使用上述方法,因为将来任何时候都可能有人滥用私钥并访问所有密码。
但是,如果您保证私钥始终保持私有,那么我看不到技术缺陷。
当然,我可能是错的。
- 与仅仅散列密码相比,它的处理成本也相当高。
- @sripathi正确,但我应该使用什么算法?
- @symcbean它可能更贵,但我想这不是问题。另外,任何攻击者在对数据库执行字典攻击时都需要花费更多的时间。
- 事实上,之所以建议使用bcrypt来散列密码,是因为它的设计速度很慢。
- @jammer-您应该阅读此线程中的讨论-stackoverflow.com/questions/2283937/…。讨论得很长,但与你的问题很相关。
不要解密密码。如果以后需要更改密码系统,请添加一个名为"存储类型"(或其他类型)的字段。
然后,当您需要更改密码时,您将检查它是否是旧密码。如果是,下次他们登录时,您可以更改密码编码。否则,使用新系统登录。
能够解密密码是一个坏主意(而且可能没有任何方法可以比不加密地存储密码更好)。听起来你的主要问题是,如果你改变了你的存储方法,你就可以使用密码。只需做Linux所做的,存储如何用密码散列密码。例如$1$salt$hash就是MD5。这样,如果您决定更改密码的存储方式,您仍然可以检查旧密码(如果有人正确登录,您可以使用新的哈希更新他们的密码)。
- 这将要求我修改未来的平台,我宁愿不这样做。当然,它也需要一些努力才能将普通密码移动到那里,但至少在一次性移动之后不需要任何管理工作。
- 你不能用一些你知道将来会被支持的东西吗?例如,在几乎所有的平台上,sha512都很容易实现(如果您可以找到一个库来进行加密,那么您也可以实现sha512)。
- 我同意,您不应该为了更容易切换到下一个加密方法而牺牲安全性。从一开始就要有一个好的开始,你不需要太在意未来的变化。
我看到的唯一问题是,大多数公钥-私钥加密代码将使用公钥加密对称密钥,并依赖于私钥解密,然后使用对称密钥加密消息。
您希望使用公钥直接加密密码+salt。
因此,对系统的攻击归结为:
针对普通公钥/私钥加密的攻击
攻击您的私人密钥存储。
对于大多数应用程序来说,存储sha-1散列密码已经足够了。
是的,在大多数散列算法中都存在已知的冲突,但这并不意味着实际的攻击向量。尤其是当你在加盐时。
对于salt:将其存储在一个配置文件中,该文件不能从外部访问,但可以由PHP安装读取。
- -1你提出的是一个公认的弱点。我会在Bugtraq上见到你。
- 我在寻找加密解决方案,而不是散列。
- 存储一个单独的salt只比不使用它好一点,为每个密码使用salt是一个更好的主意。
- 这完全取决于你实际需要多少安全保障。如我所说:对于大多数应用,简单的盐散列就足够了。遗憾的是,许多应用程序也充满了它们自己的安全问题,因此一个不太完美的哈希算法是它们的问题中最小的一个。