【问题标题】:Increasing probability of finding a hash collision增加发现哈希冲突的概率
【发布时间】:2019-05-22 19:33:24
【问题描述】:

我正在尝试查找修改后的哈希函数的哈希冲突。假设我修改后的哈希只输出 SHA-1 的前 36 位。众所周知,SHA-1 是一个 160 位的哈希值,因此,我们只需要输出 40 个字符中的 9 个字符进行比较。

我如何开始我的程序是通过散列一个字符串(我正在运行一个 SHA-1 算法,我将其命名为 sha1。我还确保 SHA-1 算法的输出是正确的。)

首先,我将硬编码 2 个字符串并从 40 个字符中提取 9 个字符,因为我只需要 SHA-1 的前 36 位。如果发现碰撞,下面的函数基本上返回 true,如果没有发现碰撞,则返回 false

public static boolean findCollision(int x1, int x2) {

    String message1 = "I tried " + x1 + " iteration to find a collision";
    String message2 = "I tried " + x2 + " iteration to find a collision";       


    //hashing my string and extracting 9 characters
    String message_hash1 = sha1(message1);
    String message_hash2 = sha1(message2);

    String modified_hash1 = message_hash1.substring(0, 9);
    String modified_hash2 = message_hash2.substring(0, 9);

    if (modified_hash1.equals(modified_hash2))  
        return true; 
    else 
        return false;
}

最后,我将有一个 main 函数,它会在无限循环中随机整数到 MAX_VALUE,并且当且仅当找到哈希时才会中断。

public static void main(String[] args) {

    Random random = new Random();
    int x1 = 0;
    int x2 = 0;
    int counter = 0;

    while (true) {

        while(true){

            x1 = random.nextInt(Integer.MAX_VALUE);
            x2 = random.nextInt(Integer.MAX_VALUE);

            if (x1 != x2) 
                break;  
        } 

        if (findCollision(x1, x2) == true) {
            break;
        }
        counter++;
    }

    System.out.println("\nNumber of trials: " + counter);
}

如果我尝试只获取 SHA-1 的前 24 位,我很容易找到冲突。但是,尽管运行了几个小时,但我无法找到 36 位的冲突。因此,我想知道还有什么其他方法可以让我找到仅 36 位 SHA-1 的冲突。

【问题讨论】:

  • 购买一台(或多台)速度更快的计算机;并行运行。
  • 增加两个随机 36 位整数相等概率的唯一方法是阻止它们随机化。
  • Integer.MAX_VALUE 范围内可能没有冲突
  • 我认为马克提出了一个公平的观点。为什么不直接生成随机字符串/字节,而不是使用随机数嵌入字符串?
  • 此任务的目标是通过使用该特定字符串同时仅更改数字来查找哈希冲突。我确实理解生成随机字符串/字节会直接增加冲突的概率,但这不是这种情况的目的:(

标签: java hash collision sha1


【解决方案1】:

https://stackoverflow.com/users/1081110/dawood-ibn-kareem 是正确的,最佳方法是记住以前的哈希并检查它们,只要这是可行的,即适合内存,并且 36 位冲突所需的大约 2^18 值确实适合内存,虽然只有一点点(大约 50 位)不会。

此代码在大约一秒钟内发现 8 个低于 2^20 的碰撞(第一个略低于 2^18 的碰撞):

    static void SO56263762TruncCollision (String[] args) throws Exception {
        int[][] known = new int[1<<24][];
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        for( int i = 0; i < (1<<20); i++ ){
            byte[] raw = sha1.digest(("I tried "+i+" iterations to find a collision").getBytes());
            int key = 0; for( int j = 0; j < 3; j++ ) key = key<<8 | (raw[j]&0xFF);
            char[] val = new char[9]; for( int j = 0; j < 9; j++ ) val[j] = Character.forDigit(j%2==0? (raw[j/2]>>4)&0xF: raw[j/2]&0xF, 16);
            int[] test = known[key]; 
            if( test == null ){ (known[key] = new int[1])[0] = i; }
            else{ 
                for( int k = 0; k < test.length; k++ ){
                    byte[] raw2 = sha1.digest(("I tried "+test[k]+" iterations to find a collision").getBytes());
                    char[] val2 = new char[9]; for( int j = 0; j < 9; j++ ) val2[j] = Character.forDigit(j%2==0? (raw2[j/2]>>4)&0xF: raw2[j/2]&0xF, 16);
                    if( Arrays.equals(val, val2)) System.out.println ("found "+i+" and "+test[k]);
                }
                (known[key] = Arrays.copyOf(test, test.length+1))[test.length] = i;
            }
        }
        System.out.println ("Memory="+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()) );
    }

【讨论】:

    猜你喜欢
    • 2020-10-21
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    相关资源
    最近更新 更多