简体   繁体   English

发现哈希冲突的可能性增加

[英]Increasing probability of finding a hash collision

I'm trying to find a hash collision of my modified hash function. 我正在尝试查找修改后的哈希函数的哈希冲突。 Assuming my modified hash only outputs the first 36 bits of SHA-1. 假设修改后的哈希仅输出SHA-1的前36位。 As we know, SHA-1 is a 160-bit hash value, hence, we only need to output 9 characters out of 40 characters for comparison. 众所周知,SHA-1是一个160位的哈希值,因此,我们只需要输出40个字符中的9个字符进行比较即可。

How i begin my program is by hashing a string (I have a SHA-1 algorithm running and i will name it as sha1. I have also ensured that the output of the SHA-1 algorithm is correct.) 我如何通过哈希字符串开始程序(我正在运行SHA-1算法,并将其命名为sha1。我还确保SHA-1算法的输出正确。)

Firstly, i would hardcode 2 string and extract out 9 characters out of 40 characters since i require only the first 36 bits of SHA-1. 首先,我将硬编码2个字符串并从40个字符中提取9个字符,因为我只需要SHA-1的前36位。 The function below basically return a true if a collision is found and false if a collision is not found 如果发现冲突,下面的函数基本上返回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;
}

Lastly, i will have a main function that will random Integers up to MAX_VALUE in a infinite loop and will break out if and only if a hash is found. 最后,我将拥有一个主函数,该函数将在无限循环中将Integer最多随机化到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);
}

If i tried taking only the first 24 bits of SHA-1, i could easily find a collision. 如果我仅尝试使用SHA-1的前24位,那么我很容易发现冲突。 However, i'm unable to find a collision for 36 bits instead despite running it for hours. 但是,尽管运行了几个小时,但我找不到36位的碰撞。 Hence, I'm wondering what is other alternative way for me to find a collision with just 36 bits of SHA-1. 因此,我想知道还有什么其他方法可以找到仅36位SHA-1的碰撞。

https://stackoverflow.com/users/1081110/dawood-ibn-kareem is correct that the optimal method is to remember the previous hashes and check against them, as long as this is practical ie fits in memory, and the roughly 2^18 values needed for 36 bit collision do fit in memory, though only a little more (about 50 bits) would not. https://stackoverflow.com/users/1081110/dawood-ibn-kareem是正确的,最佳方法是记住以前的哈希并检查它们,只要可行(即适合内存),大约2 ^ 36位冲突所需的18个值确实适合内存,尽管只有一点点(大约50位)不适合。

This code finds 8 collisions below 2^20 (the first one slightly under 2^18 as expected) in about a second: 这段代码会在大约一秒钟的时间内找到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()) );
    }

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

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