如何安全地存储加密密钥?
Posted
技术标签:
【中文标题】如何安全地存储加密密钥?【英文标题】:How to store a crypto key securely? 【发布时间】:2012-03-01 04:38:47 【问题描述】:我正在考虑使用 pycrypto 等加密库来加密/解密我的 python webapp db 中的字段。但是加密算法需要密钥。如果我的源中有一个未加密的密钥,如果有人可以访问数据库文件,那么尝试在我的服务器上加密数据库字段似乎很愚蠢,他们也可以访问我的 python 源代码。
是否有保护所用密钥的最佳实践方法?或者加密数据库字段的替代方法(在应用程序而不是数据库级别)?
更新:我要保护的字段是 oauth 令牌。
更新:我想没有通用的方法可以避免这种情况。我认为无论如何我都需要加密这些字段,因为 db 文件很可能会被备份和移动,所以至少我会将问题减少到一个易受攻击的位置 - 查看我的源代码。
更新:oauth 令牌需要在用户离线时用于 api 调用,因此在这种情况下不适合使用他们的密码作为密钥。
【问题讨论】:
【参考方案1】:如果您要加密只需要验证(不回忆)的字段,则使用 SHA 进行简单散列或使用 DES 进行单向加密,或者使用盐来防止彩虹表实际显示它们的 IDEA。这对于密码或其他访问机密很有用。
Python 和 webapps 让我想到了 GAE,所以你可能想要一些不对每个数据库事务进行加密/解密的东西,因为这些在 GAE 上已经不便宜了。
加密数据库的最佳做法是使用用户自己的密钥对字段进行加密,但要包含一个非对称后门来加密用户的密钥,以便您(而不是任何有权访问数据库源文件或表的人) ) 可以使用您的密钥解密用户密钥,如果需要恢复或其他需要。
在这种情况下,用户(或您或受信任的代表)只能收回和解密他们自己的信息。如果您认为需要通过加密来保护其字段,您可能希望更严格地验证用户机密。
在这方面,一些秘密词的密码(而不是密码)例如“在丛林中强大的丛林”是一种鼓励的好习惯。
编辑:刚刚看到您的更新。存储 OAuth 的最佳方式是缩短它们的生命周期,只请求您需要的资源,然后重新请求它们而不是获得长令牌。最好围绕获得身份验证、获得访问权限和退出进行设计,而不是将密钥放在后门下 10 年。
因为,如果您需要在用户上线时调用 OAuth,您可以按照上述方法使用用户特定的密码进行加密。您还可以从加密计数器(使用用户密码加密)中生成密钥,以便实际加密密钥在每次交易中发生变化,并且计数器以明文形式存储。但在使用前请检查此模式的特定加密算法讨论。一些算法可能无法很好地解决这个问题。
【讨论】:
这不是意味着每次应用发出请求时用户都需要授权吗? 这取决于你。如果您想存储长寿命的 OAuth,那么他们将不需要对每个请求重新授权 OAuth。当用户在线时,您可以将明文 OAuth 保存在您的应用程序内存缓存中,并在会话开始时使用他们的密码(或其他用户密码)来解密您的 DB Oauth。但是,如果您对安全性很认真,那么每 2 周或 30 天重新请求一次似乎有点专业。 好的,我假设您已经对用户进行了某种形式的访问控制,在这种情况下,您将已经存储了他们的密码。因此,您可以从该密码形成加密密钥并使用它来加密 Oauth。但是,如果您将用户访问控制外包给第三方(即 Google),也许唯一的方法是将随机生成的密钥与用户一起存储在 cookie 中,并使用该密钥加密基于服务器的 oauth,并且仅当 cookie 不存在时重新请求权限。但是,如果您将身份验证外包给 Google,那么 Python 没有用户 API 没有。未散列的密码,因为您将其存储为散列,所以对攻击者具有未知值。即使黑客可以看到密码的哈希值,他仍然必须破解这些(如果您按照标准对它们进行加盐将使攻击者更难破解)以破解您基于(未哈希)密码值的任何加密。加密密钥基于 未散列 密码值,并在每次用户登录时重新计算该密钥。因此用户 OAuth 受到保护,并且只有在用户正确登录时才能访问。 您可能不想费尽心思,但您可以为您的 oauth 使用单独的服务器。您的应用程序可以从该服务器请求令牌。但是您的应用程序需要在不在源代码中留下密钥的情况下对自身进行身份验证。一种方法是使用基于上次交互的计数器键。有点像每次都会更改密码的汽车锁。如果有人可以破坏您的主服务器的运行状态,那么他们仍然可以获得 oauth 密钥,但如果他们只有源代码则不能。秘密存储在内存中。你可以用你的 ouath 加密这个计数器【参考方案2】:正如您所注意到的,对称加密确实没用;但是对于某些领域,可能可以使用非对称加密或陷门函数:
如果 Web 应用程序不需要回读数据,则使用非对称加密。这很有用,例如对于信用卡数据:您的应用程序将使用订单处理系统的公钥加密数据,该系统位于不可公开访问的单独机器上。
如果您只需要相等比较,请使用陷门函数,例如消息摘要,最好使用盐值。这对于在服务器上应该无法恢复的密码很有用。
【讨论】:
我已经使用 SSHA 对我的密码进行了哈希处理。对于我的用户的 oauth 令牌,我显然需要在代表用户的请求中使用它们之前解密。【参考方案3】:在确定哪种加密方法最好之前,您必须考虑要保护什么以及攻击者准备投入多少精力从您的系统中获取密钥/信息。
您试图通过使用加密来补救的攻击场景是什么?被盗的数据库文件?
【讨论】:
是的,一个被盗的数据库文件。我已经读过,期望 oauth 令牌和应用程序密钥应该被加密到与其他敏感信息(如密码)相同的级别。以上是关于如何安全地存储加密密钥?的主要内容,如果未能解决你的问题,请参考以下文章