algorithm - 散列数值的最佳算法?

标签 algorithm delphi hash numbers

当处理一系列数字,并且出于安全原因想要使用散列结果时,从给定的一系列数字生成散列值的最佳方法是什么?输入的示例是信用卡号或银行帐号。首选输出将是一个无符号整数,以帮助进行匹配。

我的感觉是,大多数字符串实现在针对如此短的字符范围运行时似乎具有较低的熵,因此,冲突率可能比针对较大样本运行时更高。

目标语言是 Delphi,但是如果其他语言的答案可以提供可以得出最佳解决方案的数学基础,我们也欢迎。

此例程的目的是确定先前收到的卡/帐户是否已被处理。输入文件可能有针对多条记录的数据库的多条记录,因此性能是一个因素。

最佳答案

对于安全问题,所有答案都在一个连续体上,从最安全最方便。我会给你两种答案,一种是非常安全的,一种是非常方便的。鉴于此以及对每个问题的解释,您可以为您的系统选择最佳解决方案。

您声明您的目标是存储此值以代替实际的信用卡,这样您以后就可以知道是否再次使用了相同的信用卡号。这意味着它必须只包含信用卡号和统一盐。包含 CCV、到期日期、名称等会使它变得无用,因为它的值可能与相同的信用卡号不同。因此,我们假设您使用相同的盐值填充所有信用卡号,该盐值将对所有条目保持统一。

方便的解决方案是使用 FNV (正如 Zebrabox 和 Nick 所建议的那样)。这将产生一个 32 位数字,可以快速索引搜索。缺点当然是它最多只允许 40 亿个不同的数字,并且实际上会比这更快地产生碰撞。因为它有如此高的碰撞率,暴力攻击可能会产生足够多的无效结果,以至于它几乎没有用处。

安全解决方案是依靠 SHA 散列函数(越大越好),但要进行多次迭代。我会建议在 10,000 左右的某个地方。是的,我知道,10,000 次迭代很多而且需要一段时间,但是当谈到对抗蛮力的力量时,攻击速度就是敌人。如果你想安全,那么你希望它很慢。 SHA 旨在为任何大小的输入都不会发生冲突。如果发现冲突,则认为散列不再可行。据我所知,SHA-2 家族仍然可行。

现在,如果您想要一种安全且快速的解决方案来在数据库中进行搜索,那么我建议使用安全解决方案 (SHA-2 x 10K),然后将完整的哈希存储在一个列,然后取前 32 位并将其存储在不同的列中,索引在第二列中。首先对 32 位值执行查找。如果没有产生匹配项,那么您就没有匹配项。如果它确实产生匹配,那么您可以比较完整的 SHA 值并查看它是否相同。这意味着您要在一个更小的集合上执行完整的二进制比较(哈希实际上是二进制的,但仅表示为字符串以便于人类阅读和在基于文本的协议(protocol)中传输)。

如果您真的很在意速度,那么可以减少迭代次数。坦率地说,即使有 1000 次迭代,它仍然会很快。您需要对您期望数据库有多大以及可能影响持续时间的其他因素(通信速度、硬件响应、负载等)做出一些现实的判断。您可能会发现您优化了过程中的最快点,这几乎没有实际影响。

此外,我建议您基准完整哈希与 32 位子集的查找。大多数现代数据库系统都相当快,并且包含许多优化,并且经常优化我们以简单的方式做事。当我们试图变得聪明时,有时我们只是放慢速度。关于过早优化的引用是什么。 . . ?

关于algorithm - 散列数值的最佳算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1359654/

相关文章:

python - 计算 n 个进程下载到可用存储的磁盘已满时间

java - 为什么Java HashMap调整大小或重新哈希不能采用像Redis这样的渐进方法

c - 从 C 中的字符串中删除多余的空格

delphi - 如何在不滚动到顶部的情况下查看函数或过程是私有(private)的、 protected 还是公共(public)的

c - 在不使用除法或模运算符的情况下找到两个数字的 GCD?

delphi - Delphi 可以用来创建和处理自定义协议(protocol)处理程序吗?

delphi - Delphi:通过查询结果填充下拉框的最快方法是什么?

arrays - 如何找到其值具有最多元素的散列的键

node.js - 根据mongodb '_id`属性创建hashid

c# - 循环在构造函数中设置变量