ska*_*adt 10 delphi algorithm hash numbers
当处理一系列数字,并且出于安全原因想要使用哈希结果时,从给定的一系列数字生成哈希值的最佳方法是什么?输入的示例是信用卡号或银行帐号.首选输出将是单个无符号整数,以帮助匹配目的.
我的感觉是,当针对如此短的字符范围运行时,大多数字符串实现似乎具有低熵,并且因此,碰撞率可能高于针对较大样本运行时的碰撞率.
目标语言是Delphi,但是如果它们可以提供可以导致最佳解决方案的数学基础,则欢迎来自其他语言的答案.
此例程的目的是确定先前收到的卡/帐户是否先前已处理过.输入文件可能具有针对多个记录的数据库的多个记录,因此性能是一个因素.
Jim*_*eth 12
对于安全问题,所有答案都是从最安全到最方便的连续统一体.我会给你两个答案,一个非常安全,一个非常方便.鉴于此以及每个解释,您可以为您的系统选择最佳解决方案.
您声明您的目标是存储此值以代替实际信用卡,以便您稍后可以知道是否再次使用相同的信用卡号.这意味着它必须只包含信用卡号码,并且可能包含均匀的盐.包含CCV,到期日期,名称等将使其无用,因为它可能与相同的信用卡号不同.因此,我们假设您使用相同的盐值填充所有信用卡号码,这些盐值将对所有条目保持一致.
的方便的解决方案是使用一个FNV(如Zebrabox和尼克建议的).这将产生一个32位数字,可以快速索引搜索.当然,缺点是它只允许最多40亿个不同的数字,并且在实践中会产生更快的碰撞.因为它具有如此高的碰撞率,所以蛮力攻击可能会产生足够的无效结果,使其几乎没有用处.
在安全的解决方案是依靠SHA哈希函数(越大越好),但多次迭代.我会建议大约10,000的地方.是的,我知道,10,000次迭代很多,而且需要一段时间,但是当谈到强大对抗蛮力时,攻击速度就是敌人.如果你想要安全,那么你希望它是缓慢的.SHA旨在不会出现任何大小的输入冲突.如果发现冲突,则认为散列不再可行.AFAIK SHA-2系列仍然可行.
现在,如果您想要一个安全且快速搜索数据库的解决方案,那么我建议使用安全解决方案(SHA-2 x 10K),然后将完整哈希存储在一列中,然后取前32位,将其存储在不同的列中,索引位于第二列.首先对32位值进行查找.如果没有产生匹配则没有匹配.如果它确实产生匹配,那么您可以比较完整的SHA值并查看它是否相同.这意味着您正在执行完整的二进制比较(哈希实际上是二进制,但仅表示为字符串,以便于人类阅读和基于文本的协议中的传输)在更小的集合上.
如果你真的关心速度,那么你可以减少迭代次数.坦率地说,即使进行1000次迭代,它仍然会很快.您将需要对您期望数据库获得的大小以及可能影响持续时间的其他因素(通信速度,硬件响应,负载等)做出一些现实的判断调用.您可能会发现您优化了流程中的最快点,这几乎没有实际影响.
另外,我建议您对完整哈希与32位子集的查找进行基准测试.大多数现代数据库系统都相当快,并且包含许多优化,并且经常针对我们以简单的方式进行优化.当我们试图变得聪明时,我们有时会放慢速度.什么是关于过早优化的引用...?
只使用加密哈希函数(如SHA系列)将为您提供所需的分布,但对于非常有限的输入空间(如信用卡号),它们可以使用强力攻击轻松攻击,因为这种哈希算法通常设计得与可能.
UPDATE
好的,安全性不关心您的任务.因为您已经有了数字输入,所以您可以使用这个(帐户)数量模拟您的哈希表大小.如果将其作为字符串处理,则可能确实会遇到错误的分布,因为十个数字只构成所有可能字符的一小部分.
另一个问题可能是数字形成了大的已分配(帐户)数字集群,它们之间有大量未分配的数字区域.在这种情况下,我建议尝试高度非线性哈希函数来传播这个集群.这将我们带回到加密哈希函数.也许好老MD5.只需将128位散列分成四组32位,使用XOR组合它们,并将结果解释为32位整数.
虽然没有直接相关,但您也可以查看本福德定律 - 它提供了一些有关数字通常不均匀分布的见解.