在不暴露基础数据的情况下检测重复项

信息安全 加密 哈希 hmac 加密
2021-08-13 06:12:10

我们有一个场景,我们需要防止两个用户使用相同的标识符。标识符是敏感的(例如社会安全号码),所以我们不想将它存储在我们的数据库中。我们只想存储某种哈希值,以防止后续用户再次使用它。我们希望安全地做到这一点,以便在数据库泄漏的情况下,攻击者无法找出原始值。

是否可以安全地进行?推荐的方法是什么?

根据一些研究,HMAC 似乎可以工作。如果是这样,推荐的算法是什么?它应该是缓慢的(比如使用固定密钥盐的 scrypt),因此如果密钥被暴露,仍然很难发现这些值?还是没有针对这种情况的保护措施?

1个回答

我认为您离可能的解决方案不远了(也就是使用现代 KDF 并有效地将其视为密码)。但是,还有更多考虑因素(评论中已经提到):

  1. SSN 的熵非常低,这意味着暴力破解是一种特别容易的攻击
  2. 由于您需要查找 SSN 是否已在任何地方使用过,因此您基本上必须在没有盐的情况下进行操作,这也使得暴力破解变得更加容易。

1 和 2 的组合会使 KDF 成为一个坏主意,即使它是您唯一的选择。因此,可能需要找到不同的业务解决方案。但是,如果 SSN 匹配是绝对要求,我认为您可以采取一些步骤来降低风险:

  1. 确保并使用大的“胡椒”。Peppers 不太常与密码一起使用,所以如果您不熟悉:使用 Peppers 基本上意味着在散列之前向 SSN 添加一个大的、恒定的、随机字符串,该字符串不存储在数据库中。在这种情况下,我会使用特别长的辣椒。所以在实践中,这意味着你创建了一个不存储在数据库或代码库中的 256 位密钥但在散列之前将其添加到 SSN。您可以将它存储在生产服务器或 CD 管道中的环境变量中,因此开发人员不容易访问它(因为他们有时是攻击者,很遗憾)。这样做的原因是,如果您的数据库泄漏但攻击者没有辣椒,那么他们就无法暴力破解 SSN(因为暴力破解 SSN 基本上需要首先暴力破解您的 256 位密钥,这是不可能的)。
  2. 使用非常大的成本函数。所有现代 KDF 都有一个可配置的成本函数,这增加了构建哈希所需的时间(因此使蛮力变得更加困难)。对于这样的事情,我会设置一个比平常更高的成本函数。我可能会对其进行调整,以便您的系统需要 1-2 秒来散列 SSN+pepper。如果您的用户可以忍受等待,那就走得更高!这不会解决您的暴力破解问题,但会有所帮助。
  3. 匿名化这些散列的 SSN!基本上,将它们单独存储在一个表中,而无法将它们与系统中的任何其他数据相关联(即,不要为该表或条目时间分配一个自动递增的 id,因为这些可能与其他表相关)。有一个只有一列的表,用于此目的且仅用于此目的。虽然 SSN 本身仍然是个人信息,但如果它在没有任何进一步信息的情况下自行泄露,对您的用户的危险要小得多。拥有一个仅包含散列 SSN 的表仍然可以让您验证之前是否输入了 SSN,因此您的总体目标仍然可以实现。

同样,您最好的选择可能只是找到一种完全不同的方法来做到这一点,而无需使用 SSN。但是,如果这是绝对的业务要求,那么上述步骤可以大大保护您客户的个人数据。尽管如此,我也会检查您所在行业的监管要求,以确保您遵守所有适用的规则。