RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 881045
Accepted
Сергей
Сергей
Asked:2020-09-14 01:09:46 +0000 UTC2020-09-14 01:09:46 +0000 UTC 2020-09-14 01:09:46 +0000 UTC

计算 CRC32 的冲突

  • 772

问题出现了——例如,如果有一个函数值CRC32——a50985e0它是从一个字节数组中获得的—— (即从一个只有字符的字符串。)那么当函数出现时Hello,完全相同的值()的概率是多少a50985e0处理从12345即获得的字节数组 从数?

更新。

根据受人尊敬的@Alex 和@Harry 的回答,我得出结论,原则上无法避免冲突。并且随着数值数组的范围越来越大(从 0 到 1,000,000,000),总会有一个与从字符串获得的哈希匹配的哈希。在这方面,我将重新提出问题 - 这些碰撞的数量是否存在模式(是否有可能检测到它)?例如,在总的哈希数组 (0 - 2,000,000,000) 中检查X了一个数字Y(例如 12345)的哈希,发现了 10 个冲突,对于任何数字,结果数组中至少有 10 个冲突。虽然来自字符串的哈希Hello只会产生 1 次冲突,并且就像任何其他字符串一样,不会产生超过 1 次冲突。这样的模式存在吗?

алгоритм
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    Zergatul
    2020-09-14T04:55:13Z2020-09-14T04:55:13Z

    首先,我想指出,如果您问这个问题,那么您很可能将校验和函数用于其预期目的之外的用途。这意味着你做错了什么。

    据我了解,您想知道如果输入是一串字母或一串数字,发生碰撞的机会是否相同。我想指出,如果您从某个地方(例如)获得 5 个字符长的随机字符串,那么您将拥有相同数字字符串的机会比字母字符串出现时高出许多数量级。

    为了证明发生碰撞的机会是相同的,我为长度为 20 的字符串生成了 1 亿个校验和(我取了 20,以便不会创建相同的数字字符串),并计算数字字符串内部的碰撞,字母串内部,数字串和字母串相互碰撞。这是我的 C# 代码:

    private static uint crc32(byte[] data)
    {
        uint crc = 0xffffffff;
        uint poly = 0xedb88320;
        for (int i = 0; i < data.Length; i++)
        {
            uint c = (crc ^ data[i]) & 0xff;
            for (int k = 0; k < 8; k++)
                c = (c & 1) != 0 ? poly ^ (c >> 1) : c >> 1;
            crc = c ^ (crc >> 8);
        }
        return crc ^ 0xffffffff;
    }
    
    static void Main(string[] args)
    {
        byte[][] digits = new byte[0x10000][];
        for (int i = 0; i < 0x10000; i++)
            digits[i] = new byte[0x10000];
    
        byte[][] chars = new byte[0x10000][];
        for (int i = 0; i < 0x10000; i++)
            chars[i] = new byte[0x10000];
    
        var rnd = new Random(123);
        int iterations = 100000000;
    
        byte[] buffer = Encoding.ASCII.GetBytes("12345678901234567890");
        for (int i = 0; i < iterations; i++)
        {
            int index = rnd.Next(20);
            buffer[index]++;
            if (buffer[index] > '9')
                buffer[index] = (byte)'0';
    
            uint crc = crc32(buffer);
            digits[crc >> 16][crc & 0xFFFF]++;
        }
    
        buffer = Encoding.ASCII.GetBytes("abcdefwxyzabcdefwxyz");
        for (int i = 0; i < iterations; i++)
        {
            int index = rnd.Next(20);
            buffer[index]++;
            if (buffer[index] > 'z')
                buffer[index] = (byte)'a';
    
            uint crc = crc32(buffer);
            chars[crc >> 16][crc & 0xFFFF]++;
        }
    
        int digitsCollisions = 0;
        for (int i = 0; i < 0x10000; i++)
            for (int j = 0; j < 0x10000; j++)
                if (digits[i][j] > 1)
                    digitsCollisions += digits[i][j];
    
        int charsCollisions = 0;
        for (int i = 0; i < 0x10000; i++)
            for (int j = 0; j < 0x10000; j++)
                if (chars[i][j] > 1)
                    charsCollisions += chars[i][j];
    
        int digitsCharsCollisions = 0;
        for (int i = 0; i < 0x10000; i++)
            for (int j = 0; j < 0x10000; j++)
                if (chars[i][j] > 0 && digits[i][j] > 0)
                    digitsCharsCollisions += chars[i][j] * digits[i][j];
    
        Console.WriteLine(digitsCollisions);
        Console.WriteLine(charsCollisions);
        Console.WriteLine(digitsCharsCollisions);
    }
    

    结果:

    2298490
    2304243
    2330855
    

    如您所见,发生碰撞的概率是相同的。

    在另一个测试中,我将输入数据长度设为 10 个字节,而不是随机数,我只是简单地采用数字的字符串表示形式i。结果不一样:

    4431872
    2301156
    2324554
    

    如您所见,尽管校验和是根据唯一的输入数据计算的,但数字上的碰撞次数增加了 2 倍。这是因为 10 字节字母的随机字符串比数字字符串具有更多的熵。CRC-32 不是一个完整的加密散列函数,没有雪崩效应。使用一个好的散列函数,我们会得到相同的结果。

    • 8
  2. Alex Titov
    2020-09-14T02:04:42Z2020-09-14T02:04:42Z

    如果散列函数是“好”的,那么就不可能从它产生的内容(数字或字母)中理解它。但!CRC32 给出的重复概率超过 50%(惊喜!)已经在 80,000 个输入行上。

    • 2
  3. Harry
    2020-09-14T02:09:08Z2020-09-14T02:09:08Z

    实现。在你的问题陈述中,概率是 1。
    总会有一个非数字序列会给你相同的 crc32 值。

    如果问题陈述是在 crc32 中与给定值之一匹配的非数字字符串的概率是多少。

    • 2
  4. Anton Shchyrov
    2020-09-14T03:44:03Z2020-09-14T03:44:03Z

    我认为您的问题的答案在此声明中

    对于任何 CRC32 散列,总是存在一个由四个字节组成的序列,其散列将给出给定的

    (此说法源于多项式的所有 256 个值都有不同的高字节)

    根据此声明,在最大长度的消息中,您将有多达四个字节的冲突

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5