2013-04-23 52 views
1

想象一下这种情况:你的用户给你他们的凭据(用户名/口令)来访问第三方服务。所以当连接到服务时你必须产生这些凭据,你不能只存储一个盐渍散列。如何存储的用户名/密码安全(散列不会做)在DB

环境是Grails,其中psql为DB。从程序员的角度来看,理想情况下,用户/密码仍然是域对象的一部分(因此它们易于使用)。

安全存储它们的最佳做法是什么?

+1

我猜第三方服务不提供不错,revokeable API密钥/秘密的访问? – 2013-04-23 09:27:45

+0

顺便说一句,如果你的应用程序能够解密/解码这个证书,那么一个黑客可以完全访问你的应用程序,只需使用你现有的代码即可。 – 2013-04-23 09:29:51

+0

@CraigRinger正确,没有办法 – Persimmonium 2013-04-23 10:02:16

回答

2

*(我不一个安全或加密专家,这是我的理解基于我的阅读和研究,而且是很远的权威意见获得web应用安全专业人士的意见,并得到适当的。安全审计。)*

你真的可以做的是有你的应用程序无法对其进行解密,当用户不积极。

加密登录部分地基于用户的原料用钥匙凭据最好的,未加密的密码。你从来没有存储用户的密码登录到你的系统上的服务,当然,所以你只有在认证过程中短暂的时间访问它(只有这样,因为网络还没有赶上90年代中期并采用了健全的质询 - 响应认证方案)。您可以在用户登录时解密第三方服务保存的凭据,并将其存储在易失性服务器端会话中以供用户使用。

对于加密密钥,您可以使用您为每个(用户,第三方凭据)对随机生成的大型盐值对用户名和用户原始密码进行哈希加密,并将其与加密凭据一起存储。盐应该与用于存储散列密码的盐不同。

这是很不理想,有各种各样的问题 - 但用户的会话过期或者他们登录我们和你清除他们的会话后的凭证将无法访问。

这也意味着你的应用程序不能代表其行事的时候都不会主动登录,这可能是您根据您的要求了搅局者的限制。

疲软的选择是让该应用程序重新启动时手动真实由系统管理员输入的所有用户证书的关键。这个密钥必须存储在内存中,但它至少不在磁盘或数据库中,因此有人窃取数据库转储将难以解密存储的凭证。

如果攻击者找到一种方法来欺骗你的应用程序在解密后泄露这些域对象 - 或者让它们冒充该用户,让它代表第三方服务执行操作另一个用户等。它至少可以防止数据库转储和类似攻击的盗窃。

一个进一步的建议:与其使用pgcrypto在DB的密码,这样做在应用程序端。这意味着数据库从不会看到解密数据所需的密钥材料;它永远不会被泄漏到数据库日志,嗅到了的pg_stat_activity

+0

感谢您的精心贡献。你的第一个想法很棒......但不幸的是,对于我们来说,这是一个很好的选择,我们需要在用户没有登录时使用凭据。第二个建议是迄今为止我得到的最好的结果......谢谢! – Persimmonium 2013-04-23 12:05:19