散列信用卡号以用作指纹

信息安全 哈希 信用卡
2021-09-06 15:38:37

将信用卡号码转换为指纹

散列信用卡号以便用于指纹识别的最佳方法是什么(即比较两个散列值可以让您知道卡号是否匹配)?

理想情况下,我正在寻找哪种哈希 + 盐可能非常适合此用例的建议。散列将唯一标识一个特定的卡号。例如,您可以使用此属性检查与您注册的两个客户是否使用相同的卡号。(因为您无法以纯文本形式访问卡号)

指纹匹配

要给出一些上下文,请参阅Stripe API 文档并搜索fingerprint. 这是我第一次听说这个概念的地方。信用卡信息将存储在客户无法访问的安全机器上(在 Stripe 后端的某个位置),并且 API 返回指纹以允许 API 使用者进行比较(例如,回答诸如has这张卡以前用过吗?)。

让我们把这一点说清楚,因为我知道你会问:我不想复制它。我只是想了解如何实现这一点

4个回答

我无法评论 Stripe 是如何做到这一点的,但我可以准确地告诉你Braintree是如何做到的(因为那是我工作的地方)。如果我不得不猜测,Stripe 可能使用了类似的方法。

在 Braintree API 中,我们为信用卡提供了一个唯一的数字标识符这个标识符是一个随机的不透明令牌,对于存储在我们系统中的卡号,它总是相同的。这个数字的种子在我们系统中每个商家都不同,因此您无法在商家之间进行比较。

当一张新卡进来时,我们通过将其与散列 + 加盐列进行比较来查找它。如果它与现有列匹配,我们知道我们可以返回相同的唯一编号标识符。如果它不匹配任何现有记录,我们会使用加密安全的伪随机数生成器来创建一个新的唯一编号标识符,并确保它不会与现有的标识符冲突。

这样,哈希 + 加盐值永远不会离开我们的后端,但我们仍然可以为商家提供一种唯一识别存储信用卡的方法。

好的,所以如果这是您必须满足的业务要求(检查系统中是否已经存在卡),这就是我将这样做的方式。

首先,PCI-DSS 确实允许使用“强加密”以散列形式存储 PAN(主帐号或信用卡号),并且他们建议(但不要求)也使用盐。 PCI-DSS v3 § 3.4(PDF 链接) 原因是为了阻止获得散列的恶意方确定用作散列输入的 PAN 的能力。

其次,您计划将其存储在一个单独的、安全的系统中并仅通过 API 公开它是一个很好的纵深防御措施。如果我正在实现这个,我不会让它将哈希发送回主系统,我只需将哈希作为 API 调用的参数,并让 API 返回“true”或“false”,具体取决于哈希是否已存在于系统中。

对于散列函数,防止输入恢复的关键(根据 PCI-DSS 的要求)是选择一种算法,使您的过程计算困难,因此蛮力的任务相对较小的输入空间有效的 PAN 相当慢。另一个答案建议的 SHA-512 不是这种算法。查看hashcat.net提供的哈希破解测试矩阵,其矩阵中最快的机器每秒可以计算近 20 亿个 SHA-512 哈希。估计输入空间大约为 30,000,000,000,000 张卡**,这意味着在未加盐的情况下,您可以在 4 多小时内计算每个 PAN 的 SHA-512,并在数据库中拥有所有卡的卡号(如果有的话)被盗。

所以,我们需要的是一个慢速散列函数,但是随着计算机变得更快和技术的发展,慢速的定义一直在变化。这意味着安全散列函数将是一个具有可调节工作因子的函数,因此随着时间的推移,您可以增加计算给定输入的散列所需的计算量。有几种候选算法可以满足这个标准,包括 PBKDF2、bcrypt 和 scrypt。密码散列的一般共识是 bcrypt,这就是我在这里的建议。对于成本,请将其设置为您的应用程序允许的最高值。它可能不是您要非常频繁地计算的东西(我想,根据您的应用程序,您将查看每分钟或每小时或每天而不是每秒的 x 哈希值)并且更高成本,

** 我的估计是基于一个 9 位数的帐号、一个不会增加复杂性的可计算校验位以及基于我找到的列表的 30,000 个有效银行识别号(卡的前 6 位数字)的 WAG。

散列信用卡号码并不能替代保护数据。如果您的系统不够安全,无法存储原始信用卡号码,那么存储 CC 哈希值就不够安全。

任何固定大小和有限字符集的东西都是一样的:出生日期、电话号码、zip 等。

信用卡都是 16 位数字,虽然 10^16 似乎是一个很大的数字,但它对于计算资源来说非常简单。如果我有你的 CC# 哈希表,我可以轻松地用彩虹表攻击它并获得完整的信用卡列表。在散列之前对值加盐会使搜索变得不可能。

所有可能的 CC 值:小于 10^16。

作为比较,假设您的用户使用了一个合理的 8 字符密码和 20 字节的盐:62^28。

(如果我是您的 PCI 审计员,我会认为散列信用卡等同于存储卡号本身。)

答案会让你失望:如果一个服务/oracle/hash 可以告诉你输入的数字是否在文件中,它可以被非常少量的暴力破解。

考虑到在该国大部分地区,信用卡是由其所在地理区域内相对较少的银行发行的。您可以很容易地了解这些银行中最受欢迎的 BIN 号码。假设您有一张孟菲斯商店的收据,上面写着 VISA ****1234。它将成为孟菲斯地区最大银行的十个不同 BIN 之一的可能性约为 20%。这是前六位数的 10^1 次猜测。接下来,您知道最后 4 个,因为它们打印在收据上。现在只有 10^1 次猜测覆盖了 16 位数字中的 10 位。在剩下的六位数字中,迭代 5 位并使用 Luhn 计算最后一位。那是 10^6 次测试,将在 20% 的时间内产生有效的帐号。

要测试一个数字,您所要做的就是在服务中循环 100,000 次。服务是否使用哈希或加密或魔术棒来保护帐号并不重要,只要它告诉您您的输入是否匹配即可。

您可能会注意到,这仅在大约 20% 的情况下有效。想想那个从塔吉特偷走 4000 万个账号的人,他不能全部卖掉,因为世界上没有足够的骗子买那么多。其中 20% 是 800 万,他可能也没卖出那么多。所以 20% 的几率对于攻击者来说已经足够了。