![小心当您处理信用卡号码时!](https://linux22.com/image/1305908/%E5%B0%8F%E5%BF%83%E5%BD%93%E6%82%A8%E5%A4%84%E7%90%86%E4%BF%A1%E7%94%A8%E5%8D%A1%E5%8F%B7%E7%A0%81%E6%97%B6%EF%BC%81.png)
我的安全官员正在寻找一种哈希算法,该算法将采用最多 20 个字符的字符串,然后输出一个唯一的 12 个字符的字母数字哈希值。20 个字符的字符串通常只是数字(好吧,我会告诉你,它是信用卡号),所以对我来说它似乎是可压缩的。
如果它是公开可用且经过测试的东西,他可能会更舒服,但我迄今为止的研究表明,流行的散列算法通常具有固定长度的输出(或可变输出,但具有特定的预定长度)。
答案1
小心当您处理信用卡号码时!
只需遵守您所在地区适用的标准和法律,或由您的安全官员提供的标准和法律即可。如果您确实需要这样做,那么请确保重新考虑您的设计,您真的不想在您的代码中传递信用卡号,或者让信用卡号因哈希而发生冲突。
这迟早会自找麻烦……
信用卡号在代码中的存在时间应该很短,仅用于付款,不能超过这个时间。您最多可以存储一个精简版本,仅用于显示目的。但不要在其哈希值发生冲突或以可以检索原始数据的方式使用它,如果您确实需要这样做,请确保您有一个良好的哈希和/或安全系统,确保不会发生冲突,并且当您的数据库/软件安全性受到破坏时,您能够联系所有客户。
答案2
商家没有理由存储完整的信用卡号,无论是否经过散列处理。
我认为你确实需要评估为什么你需要这样做。
如果您存储的是信用卡号,那么数字空间可能足够小,以至于可以强制计算哈希值,这使得存储此哈希值变得很危险,并且可能违反 PCI。
几乎肯定有一个更好的解决方案可以帮助您解决所面临的实际问题。
答案3
如果您的输入是 20 位数字,则有 10 20 种可能的输入。
如果您的输出是 12 个字符的字母数字字符串,则有 62 12 种可能的输出。
输入:
100000000000000000000
输出:
3226266762397899821056
如果我们仔细观察,我们会发现底部的数字更长。
这意味着输出的可能性大于输入的可能性。
这意味着哈希毫无意义,因为每个可能的输出都可以直接映射到一个输入。这意味着破解并恢复实际数字将非常容易。
因此,我们只需使用更短的哈希!
这有什么意义呢?只需使用一个整数,如果有必要,可以使用一个随机整数。
让我们以密码为例。
您从不存储密码。您只存储哈希值。这样就可以轻松地根据该哈希值检查给定的输入(以查看提供的密码是否正确),而无需存储实际密码。
这是因为:
- 我们的哈希算法不容易对两个输入产生相同的哈希值(不太可能发生冲突)
- 假设有人可以算出给定哈希的原始输入是不合理的
那为什么呢?好吧,我使用的密码可能有 1,000,000 个字符长。你怎么能从一个短哈希中算出这个长度呢?你做不到。你只能尝试计算尽可能多的哈希,将它们与你已有的哈希进行比较,并希望找到匹配的哈希。在这种情况下,找到实际的原始输入通常并不重要,因为任何产生相同哈希的输入都可以。
因此,如果我是一名攻击者,并且掌握了包含哈希值的数据库,我就可以将这些哈希值与一组先前计算的找到该哈希的有效输入。这通常由盐你的哈希。
因此,攻击者将被迫进行长时间的暴力破解,直到找到匹配哈希的有效输入(这将需要很长时间,因为可能的哈希数量非常多)。
但是,如果密码的长度被限制在一定范围内,并且只能包含数字,情况
会怎样?这大大减少了可能的输入,从而减少了暴力破解匹配哈希所需的时间。
这基本上就是您在哈希信用卡号时所做的。但情况更糟,因为如果攻击者得到匹配结果,那么它就不仅仅是一个任意字符串,而且很可能是一个有效的信用卡号!
答案4
忽略上述所有问题,有一个非常非常简单的解决方案。
伪代码如下:
function my_hash(string data, int length){
string t = md5sum(data);
return t.substring(0,length)
}
或者 sha512 sum 或者任何你喜欢的。我个人建议多轮 blowfish。如果有人抓住了数据库,并且知道你是如何创建这个哈希的,他们也可以简单地遍历所有 CC 号码的空间并比较数据来逆转它。这是坏的。
但是,要小心。阅读所有其他答案,它们都有非常有效的观点。