好的,所以如果这是您必须满足的业务要求(检查系统中是否已经存在卡),这就是我将这样做的方式。
首先,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。