繁体   English   中英

这是测试散列函数雪崩效应的正确方法吗?

[英]Is this the correct way of testing the avalanche effect of a hash function?

我正在尝试用 C 实现一个哈希表来丰富我对数据结构的理解。

有很多用于哈希表实现的哈希函数。

为了比较散列函数,有一个称为雪崩效应测试的测试。

为了测试我目前拥有的哈希函数集,我用 Java 编写了一个小程序:

    public static void testHashAvalanche() {
        Set<Long> collisionSet = new HashSet<>();
        // The input for the hash function with 128 bytes.
        byte[] bytes = new byte[128];
        long count = 0;
        long previous = 0;
        long totalAvalanche = 0;
        // Generate the inputs for hashing with a slight change of bit each time
        for (int i = 0; i < 128; i++) {
            // Byte value from 0 -> 255
            for (int j = 0; j < 256; j++) {
                long current = hash(bytes); // Any hash function with 64 bit output
                int avalanche = calculateAvalanche(previous, current);
                totalAvalanche += avalanche;
                bytes[i]++;
                count++;
                previous = current;
            }
        }
        System.out.println("Average Avalanche: " + (double) totalAvalanche / (double) count);
    }
    
    public static int calculateAvalanche(long a, long b) {
        long difference = a ^ b;
        return Long.bitCount(difference);
    }

我想知道这是否是一种正确的方法,或者还有其他方法来测试散列函数。

谢谢!

让我们从快速观察开始。 假设您正在散列 128 字节的值。 这意味着您正在对 1024 位长的输入进行哈希处理。 有多少个不同的 1024 位数字? 嗯,第一位可以是零或一。 独立地,第二位可以是零或一。 与此无关,第三位可以是零或一等。这意味着这些位的可能组合数是 2 × 2 × ... × 2,总共 1024 次,或 2 1024

就上下文而言,这个数字是惊人的 称其为“天文数字”实际上是对这个数字的侮辱,因为可观测宇宙中的原子数量大约为 2 300 您根本无法尝试所有 2 1024种输入组合以查看它们之间的差异。

那么你能做些什么呢? 一种选择是选择不同输入的样本,并为每个输入计算与它们有一点不同的所有数字。 然后,将所有这些散列,查看有多少输出位翻转,并将这些数字平均在一起。 另一种选择是选择一个随机值,在其中翻转一些位,计算输出散列的变化量,然后重复此过程以粗略估计散列在实践中的变化情况。 或者您可以在“真实”输入(可能来自数据库或某处的值列表)上使用这些方法,对输入进行“真实”编辑(对于某些定义,可能通过将一个值的哈希值与“相似”值的哈希值进行比较“类似”)。

您正在采取的方法是沿着这些路线的,但并不完全相同。 具体来说,您的方法通过维护一个字节数组来工作,循环浏览模式

0 0 0 0 ... 0 0
0 0 0 0 ... 0 1
0 0 0 0 ... 0 2
0 0 0 0 ... 0 3
0 0 0 0 ... 0 4
      ...
0 0 0 0 ... 1 0
0 0 0 0 ... 2 0
0 0 0 0 ... 3 0
0 0 0 0 ... 4 0
      ...

这有几个问题。 首先,这些输入可能不是可能输入的良好代表性样本。 (尽管在您的应用程序中散列这些类型的值可能很常见,在这种情况下您可以忽略这一点。^_^)

接下来的问题是,你改变一次一个字节,在一个时间,而不是一个 这可能是也可能不是问题,这取决于您要测量的内容。 如果您正在寻找单个字节级别的雪崩效应,这很好。 但是,如果您正在寻找单个级别的雪崩效应,这将不起作用。 例如,将一个字节从 15 (00001111) 滚动到 16 (00010000) 会更改 5 位。 通过使用格雷码以一次翻转一位的方式循环遍历所有可能的字节,您可以保持当前一次修改一个字节的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM