我们有一个系统,我们希望阻止为两个不同的帐户注册相同的信用卡号码。由于我们不在内部存储信用卡号码 - 只是最后四位数和到期日期 - 我们不能简单地比较信用卡号码和到期日期。
我们目前的想法是在注册卡时在我们的信用卡信息系统中存储哈希(SHA-1),并比较哈希以确定之前是否使用过卡片。
通常,使用salt来避免字典攻击。我假设在这种情况下我们很容易受到攻击,所以我们应该将哈希值与哈希一起存储起来。
你们看到这种方法有什么缺陷吗?这是解决这个问题的标准方法吗?
答案 0 :(得分:17)
让我们做一些数学计算:信用卡号码长16位。前七位是“主要行业”和发行人数字,最后一位是luhn校验和。留下8位“免费”,总计100,000,000个账号,再乘以潜在发行人数的数字(不太可能非常高)。有些实现可以在日常硬件上每秒进行数百万次哈希,所以不管你做什么腌制,这对暴力来说都不是什么大问题。
纯粹巧合的是,在寻找给出哈希算法基准的东西时,我找到了this article about storing credit card hashes,其中说:
使用哈希算法的简单单次传递存储信用卡,即使在加盐时也是如此,这是非常愚蠢的。如果哈希值受到损害,那么对信用卡号码进行暴力破解就太容易了。
...
当散列信用卡号时,必须仔细设计散列,以通过使用最强的可用加密散列函数,大盐值和多次迭代来防止暴力强制。
完整的文章非常值得仔细阅读。不幸的是,结果似乎是任何使得存储哈希信用卡号码“安全”的情况也会使搜索重复数据的成本过高。
答案 1 :(得分:10)
我认为人们正在考虑设计这个问题。使用像sha-256这样的盐渍的,高度安全的(例如“计算上昂贵的”)散列,以及每个记录的独特盐。
您应首先进行低成本,高精度检查,然后仅在检查结果时进行高成本的最终检查。
第1步:
查找与最后4位数的匹配(也可能是exp。日期,尽管那里有一些可能需要解决的细微之处)。
第2步:
如果简单检查命中,请使用salt,获取哈希值,进行深入检查。
cc#的最后4位是最独特的(部分原因是因为它还包括LUHN校验位),因此深入检查的百分比将与最终不匹配(误报率)非常非常低(百分之几),相对于天真的“每次进行哈希检查”设计,可以节省大量的开销。
答案 2 :(得分:5)
不存储信用卡号码的简单SHA-1,方式易于破解(特别是因为已知最后4位数字)。我们公司遇到了同样的问题:这就是我们解决问题的方法。
第一个解决方案
hash(stored_CC1_salt+CC2)==stored_CC1_hash
。由于我们的数据库中有大约10万张信用卡,我们需要计算大约10个哈希值,因此我们得到的结果大约需要10秒钟。在我们的例子中,这很好,但你可能想稍微调整bcrypt。不幸的是,如果你这样做,这个解决方案将不那么安全。另一方面,如果您将bcrypt调整为更加CPU密集型,则需要更多时间来匹配CC编号。
即使我认为这个解决方案方式比简单地存储CC号的未加盐的哈希更好,但它不会阻止一个非常有动力的盗版者(谁设法获得数据库的副本)打破一张信用卡平均2至5年的时间。因此,如果您的数据库中有100k的信用卡,并且盗版者拥有很多的CPU,那么他每天都可以恢复一些信用卡号码!
这让我相信你不应该自己计算哈希:你必须将其委托给其他人。这是第二个解决方案(我们正在迁移到第二个解决方案)。
第二个解决方案
只需让您的付款服务提供商为您的信用卡生成别名。
这很简单,速度快,安全性好(至少如果您的支付服务提供商是这样)。我看到的唯一问题是它会将您与您的支付提供商联系起来。
希望这有帮助。
答案 3 :(得分:3)
PCI DSS表示您可以使用强大的单向哈希存储PAN(信用卡号)。它们甚至不要求它被腌制。那就是说你应该用每张卡的唯一值加盐。到期日是一个良好的开端,但也许有点太短。您可以从卡中添加其他信息,例如发卡行。您不应使用CVV /安全号码,因为您不允许存储它。如果您确实使用了到期日,那么当持卡人获得一张具有相同号码的新卡时,它将被视为另一张卡。根据您的要求,这可能是好事也可能是坏事。
使数据更安全的方法是使每个操作的计算成本都很高。例如,如果你md5两次,则攻击者需要更长时间来破解代码。
生成有效的信用卡号码并尝试每个可能的到期日收费都相当简单。但是,它的计算成本很高。如果你破坏哈希的成本更高,那么任何人都不值得烦恼;即使他们有盐,哈希和你使用的方法。
答案 4 :(得分:2)
@Cory R. King
SHA 1本身并没有被破坏。文章显示的是,可以生成2个字符串,这些字符串具有相同的哈希值,而不是暴力时间。您仍然无法在合理的时间内生成等同于SPECIFIC哈希的字符串。这两者之间有很大的不同。
答案 5 :(得分:2)
我相信我找到了解决这个问题的万无一失的方法。如果我的解决方案存在缺陷,请有人纠正我。
这样,即使黑客得到你的哈希,他们也需要闯入你的服务器才能找到你的公式。
答案 6 :(得分:1)
比较哈希是一个很好的解决方案。但是,请确保您不要仅使用相同的恒定盐来填充所有信用卡号码。在每张卡上使用不同的盐(如失效日期)。这应该会让你完全不受字典攻击。
为您存储的每个密码添加一个长而独特的随机盐。盐(或者nonce,如果你愿意的话)的要点是使每个密码都是唯一的,并且足够长,以至于暴力攻击是浪费时间。因此,用户的密码,而不是存储为“myspace1”的散列,最终被存储为随机unicode字符串+“myspace1”的128个字符的散列。你现在完全不受彩虹桌攻击的影响。
答案 7 :(得分:1)
几乎是一个好主意。
存储哈希是一个好主意,它已经在密码世界中服务了几十年。
添加salt 似乎就像一个公平的想法,并且确实使攻击者更加难以进行暴力攻击。但是当你实际检查以确保新的CC是唯一的时,那盐就会花费你很多额外的努力:你必须将你的新CC号数量SHA-1次,其中N是你拥有的盐的数量已经用于所有与之比较的CC。如果您确实选择了好的随机盐,则必须为系统中的每个其他卡执行哈希。所以现在你正在做蛮力。所以我想说这不是一个可扩展的解决方案。
你会看到,在密码世界中,盐不会增加任何成本,因为我们只想知道明文+盐是否为我们为这个特定用户存储的内容。您的要求实际上非常不同。
你必须自己权衡利弊。添加盐不会使数据库安全,如果它被盗,它只会使解码更难。多难多少?如果它将攻击从需要30秒改为需要一天你就没有取得任何成果 - 它仍将被解码。如果它从一天变为30年,那么你已经考虑了一些值得考虑的问题。
答案 8 :(得分:0)
是的,比较哈希在这种情况下应该可以正常工作。
答案 9 :(得分:0)
盐渍哈希应该可以正常工作。拥有salt-per-user系统应该具有足够的安全性。
答案 10 :(得分:0)
SHA1是broken。当然,没有太多关于什么是好的替代品的信息。 SHA2?
答案 11 :(得分:0)
如果您将卡号的最后4位数与卡持有人的姓名(或姓氏)和到期日相结合,您应该拥有足够的信息以使记录具有唯一性。哈希对于安全性很好,但是你不需要存储/调用盐来复制哈希以进行重复检查吗?
答案 12 :(得分:0)
我认为上面提到的一个好的解决方案是存储卡号,有效期和名称的哈希值。这样你仍然可以做快速比较......
答案 13 :(得分:0)
Sha1 损坏在这里不是问题。 所有破坏的方法是,可以比您预期的更容易计算碰撞(具有相同sha1的2个数据集)。 这可能是基于sha1接受任意文件的问题,但它对内部散列应用程序没有任何意义。
答案 14 :(得分:0)