我们目前的想法是,在信用卡注册时在系统中存储信用卡信息的哈希值(SHA-1),通过比对哈希值来确定该卡是否已被使用。
通常,为避免字典攻击,会使用盐。我认为在这种情况下我们是有漏洞的,因此应该将盐值与哈希值一起存储。
你们看到这种方法有什么缺陷吗?这是解决该问题的标准方法吗?
让我们来算一下:信用卡号共有16位数字。前七位是“主要行业”和发卡行号码,最后一位是Luhn校验和。这留下了8位“自由”,总共有1亿个帐户号码,乘以可能的发卡行号码(不太可能很高)。有实现可以在日常硬件上每秒执行数百万次哈希,因此无论您做什么样的加盐,暴力破解都不是什么大问题。
出于巧合,当我在寻找一些提供哈希算法基准的东西时,我发现了关于存储信用卡哈希的文章,其中说:
即使加了盐,只使用哈希算法的简单单次操作存储信用卡是愚蠢的。 如果哈希被攻破,轻松地暴力破解信用卡号码。
...
在对信用卡号进行哈希处理时,必须仔细设计哈希函数,采用最强大的可用密码哈希函数、大盐值和多次迭代,以防止暴力破解。
完整的文章值得仔细阅读。不幸的是,结果似乎是任何使存储哈希信用卡号码“安全”的情况都会使查找重复项的成本过高。
人们对此设计进行了过度思考,我认为。使用像sha-256这样的盐值高度安全(例如“计算密集型”)哈希函数,加上每个记录的唯一盐。
首先应该进行低成本、高准确度的检查,只有当该检查命中时才进行高成本的决定性检查。
步骤1:
查找与最后4位数字(可能也包括有效期限,但其中有一些细节需要处理)相匹配的条目。
步骤2:
如果简单检查符合条件,使用盐,获取哈希值,进行深入检查。
信用卡号的最后4位数字是最独特的(因为它还包括LUHN校验位),因此您将进行的深入检查不会最终匹配的百分比(误报率)非常非常低(不到百分之一),这可以帮助你节省大量相对于朴素的“每次都进行哈希检查”的设计的开销。
它简单、快速、安全(至少如果您的支付提供商是的话)。我唯一看到的问题是它让您受制于您的支付提供商。
希望这能帮助您。
@Cory R. King
SHA 1算法本身并没有被破解。这篇文章展示了一种方法,可以在不使用暴力破解的情况下生成两个具有相同哈希值的字符串。但是,你仍然无法在合理的时间内生成与特定哈希值相等的字符串。这两者之间有很大的区别。
差不多是个好主意。
只存储哈希值是个好主意,它在密码世界中已经使用了几十年。
添加盐似乎是一个公平的想法,确实使攻击者的暴力破解更加困难。但是当你实际检查新的CC是否唯一时,这种盐会让你付出很大的额外努力:你将不得不对新的CC号码进行N次SHA-1哈希运算,其中N是你已经用于比较所有CC的盐的数量。如果你选择了好的随机盐,你就必须为系统中的每张卡片做哈希运算。所以现在变成了你在进行暴力破解。因此,我认为这不是可扩展的解决方案。
你看,在密码世界中,盐不增加任何成本,因为我们只想知道明文+盐是否与我们为该特定用户存储的哈希值匹配。你的要求实际上相当不同。
你必须自己权衡利弊。如果数据库被盗,添加盐并不能使其更安全,只是使解码变得更困难。有多困难呢?如果攻击所需时间从30秒变成了一天,那么你什么也没做——它仍然会被解码。但如果它从一天变成了30年,那么你就值得考虑了。
是的,在这种情况下比较哈希值应该可以正常工作。