【问题标题】:Checksum for SSNSSN 的校验和
【发布时间】:2011-08-31 13:33:12
【问题描述】:

我有一个项目需要在前端验证美国社会安全号码(格式 ddd-dd-dddd)。一个建议是使用散列算法,但考虑到使用的字符集很小 ([0-9]),这将是灾难性的。以高概率验证数字是否正确并允许后端进行最终的== 检查是可以接受的,但我需要做得比“有九位数字”等要好得多。

在寻找更好的替代方案时,我发现了 ISBN 数字和 UPC 的验证校验和。这些看起来是一个很好的选择,在前端成功的可能性很高。

鉴于这些限制,我有三个问题:

  1. 有没有办法证明像 ISBN13 这样的算法可以处理不同类别的数据(如 SSN),或者从安全角度来看它是否或多或少符合目的?对于我相当大的一个真实 SSN 样本,校验和似乎是合理的,但我不想发现它们由于某种原因通常不适用。
  2. 这是在某个地方解决的问题,以便我可以简单地使用预先存在的验证方案来解决问题吗?
  3. 是否有任何此类算法也可以轻松地验证 SSN 的最后 4 位数字而不放弃太多额外信息?

一如既往的感谢, 乔


更新:

回答下面的问题,更详细一点。我有之前输入的客户 SSN,安全地存储在应用程序的后端。我需要做的是验证(尽最大可能)客户在 this 页面上再次输入了相同的值。问题是我需要防止信息被意外透露给前端,以防某些未经授权的人能够访问该页面。

这就是为什么 MD5/SHA1 散列是不合适的:即它可以用来毫无困难地推导出完整的 SSN。校验和(例如,模 11)几乎不向前端提供任何信息,同时仍然允许现场验证的高度准确性。但是,如上所述,我对其普遍适用性感到担忧。

【问题讨论】:

  • 为什么使用 sha1 会是灾难性的?
  • @Nick 这将是灾难性的,因为你可以很快地暴力破解这么大的数字。此外,SSN 是一种固定格式,因此并非所有数字都有效,从而进一步减少了搜索量。现代硬件(尤其是 GPU)可以快速计算大量哈希,因此这对于个人识别信息的安全性不足。
  • 我对这个问题有些困惑。你不是以明文形式传输 SSN 吗?
  • @Joseph 谢谢,我现在对这个问题有了更好的理解。不过,我担心你提出的任何算法的信息泄露。例如,一个简单的 mod 11 校验和仍然会“泄漏”SSN 搜索空间 10:1 的减少——这种泄漏(对于每个用户)是否值得在用户错误输入 SSN 的不太常见的情况下节省少量往返行程?就个人而言,我会进行最少的客户端验证(即 9 位数字等),然后进行正常的服务器端验证。简单且没有信息泄露的可能性。如果偶尔用户需要重新提交,那就这样吧。
  • 我同意埃里克的观点。听起来像过早的优化。只需使用 Regex,您就可以在前端进行基本的完整性检查,甚至是一些特定于 SSN 的模式验证。然后做一个完整的验证 - 无论如何你最终都必须这样做,一个检查像 SSN 之类的东西的功能可能会导致一个不同的页面,大多数客户可能会在第一时间得到他们的 ssn。所以它只是偶尔的往返被保存。往返旅行和网络应用程序 - 这是生活中的事实。您的应用中肯定还有其他更值得优化的地方吗?

标签: algorithm security validation


【解决方案1】:

维基百科不是这类事情的最佳来源,但考虑到这一点,http://en.wikipedia.org/wiki/Social_Security_number

与许多类似的数字不同,它不包含校验位。

但在此之前,它提到了一些广泛使用的过滤器:

SSA 发布用于每个区域号的最后一个组号。由于组号以常规(如果不寻常)模式分配,因此可以识别包含无效组号的未发布 SSN。尽管采取了这些措施,但仅使用公开可用的信息并不能轻易地检测到许多欺诈性 SSN。为此,有许多提供 SSN 验证的在线服务。

【讨论】:

  • 感谢您的回复,迈克。虽然我可能可以合理地确定一个号码是否是一个 SSN,但我需要知道一个号码是否是您的 SSN。
  • @Joseph,当 HTTP 连接的请求端的某些东西向您提供 SSN 时,您想测试演示者是否代表拥有该 SSN 的真实美国公民/居民工作已签发但未随后撤销?
  • 对含糊之处深表歉意。我已经拥有客户的 SSN(安全地存储在后端),我需要验证他们在前端输入的 SSN 是否与我记录的 SSN 匹配,而无需向前端透露我必须提供的任何更多信息(在如果会话以某种方式受到损害)。
  • @Joseph,啊。所以冒充不是问题,因为您已经进行了一些身份验证?但是您不信任在任何帐户信息表中都有完整行的前端?所以你想要一个返回布尔值或异步等效值的函数 isSsnOfCurrentUser(ssn) 吗?是否存在窃听问题,或者您发送 SSN 的任何渠道是否已经受到保护以防窃听?
  • 假冒是一个潜在的问题(例如,如果会话被破坏),你是对的,我不信任客户端的数据。您的函数 sig 大致正确,但由于往返的时间延迟,我对异步调用犹豫不决。为了速度考虑,我会牺牲一些误报(认为它是正确的,是错误的)。窃听不在问题范围内,但它通过普通浏览器 SSL 得到保护。
【解决方案2】:

重申您的基本要求:

  • 相当强大的校验和,可防止简单的人为错误。
  • “预期”校验和从服务器 -> 客户端发送,允许客户端验证。
  • 校验和不得泄露过多的 SSN 信息,以尽量减少敏感信息的泄露。

我可能会建议使用加密算法(SHA-1 等),但不要将完整的哈希值发送给客户端。例如,仅发送 160 位哈希结果 [1] 的最低 4 位。通过发送 4 位校验和,您检测到数据输入错误的几率为 15/16——这意味着您将在 93% 的时间内检测到错误。但另一方面,您已经“泄露”了足够多的信息以将他们的 SSN 减少到搜索空间的 1/16。由您决定客户端验证的便利性是否值得这种泄漏。

通过调整发送的“校验和”位数,您可以在方便用户(即检测错误)和信息泄露之间进行调整。

最后,鉴于您的要求,我怀疑这种便利性/泄漏权衡是一个固有问题:当然,您可以使用更复杂的加密挑战/响应算法(正如 Nick ODell 敏锐地建议的那样)。但是,这样做需要一个单独的往返请求——你说你一开始就试图避免这种情况。

[1] 在一个好的加密散列函数中,由于雪崩效应,所有输出数字都很好地随机化,因此您选择的特定数字并不特别重要——它们实际上都是随机的。

【讨论】:

    【解决方案3】:

    简单的解决方案。将数字 mod 100001 作为校验和。有 1/100_000 的机会你会不小心用错误的数字得到正确的校验和(并且它会非常难以消除一位或两位数的错误),并且可能有 10,000 个可能的 SSN,所以你没有透露向攻击者发送 SSN。

    唯一的缺点是很容易找出 10,000 个可能的其他 SSN。如果这个人可以从其他地方获得 SSN 的最后 4 个,那么他们可能会找出 SSN。如果您对此感到担心,那么您应该获取用户的 SSN 号码,添加盐,然后对其进行哈希处理。并故意使用昂贵的哈希算法来做到这一点。 (你可以只迭代一个更便宜的算法,比如 MD5,固定次数来增加成本。)然后只使用一定数量的比特。这里的重点是,虽然有人当然可以通过所有十亿个可能的 SSN 来提出有限的可能性列表,但这样做会花费他们更多。希望他们不要打扰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      相关资源
      最近更新 更多