密码学原理_Crypto++实现SHA-1近似碰撞寻找

Requirements

请用 Crypto++实现一个程序,寻找 SHA-1 的 “近似碰撞”。也就是说,要找到两个输入a 和 b,满足 a≠b,但是 SHA1(a)和 SHA1(b)有尽可能多的对应比特相同。请说明你找到的 SHA1(a)和 SHA1(b)有多少个比特相同。请提交找到的 a 和 b 的值,以及它们的 Hash 值。

Compilation Options

g++ SHA1.cpp -o SHA1 -lcryptopp

Description

According to birthday attack, I calculate that the probability of no less than 113 bits’ partial collision with 10,000,000 attempts is 60.88% and 31.57% for 114 bits. With the help of Mathematica, I get the exact probability. Here is the source code:

In[1]:= p = N[Sum[Binomial[160, i]/(2^160), {i, 113, 160}]]
Out[1]= 9.38456*10^-8
In[2]:= N[1 - (1 - p)^10000000]
Out[2]= 0.608768
In[3]:= p = N[Sum[Binomial[160, i]/(2^160), {i, 114, 160}]]
Out[3]= 3.79404*10^-8
In[4]:= N[1 - (1 - p)^10000000]
Out[4]= 0.315731

Source Code

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace CryptoPP;

const int SIZE_CHAR = 32;
const int SIZE_SPACE = 10000000;
const int UP_BOUND = 113;
const char CCH[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";

string gen_rand_str();
string calculate_hash(string);
string convert_hex_binary(string);

int main() {

    srand((unsigned)time(NULL));

    int no = SIZE_SPACE;
    while (no--) {
        string str1 = gen_rand_str();
        string str2 = gen_rand_str();
        string hash1 = calculate_hash(str1);
        string hash2 = calculate_hash(str2);
        string binary_str1 = convert_hex_binary(hash1);
        string binary_str2 = convert_hex_binary(hash2);
        int counter = 0;
        for (int i = 0; i < 160; i++) {
            if (binary_str1[i] == binary_str2[i]) counter++;
        }
        if (counter > UP_BOUND) {
          cout << str1 << ": " << hash1 << endl;
          cout << str2 << ": " << hash2 << endl;
          cout << counter << endl;
        }

    }

    return 0;
}

string gen_rand_str() {

    char ch[SIZE_CHAR + 1] = {0};
    for (int i = 0; i < SIZE_CHAR; ++i) {
        int x = rand() / (RAND_MAX / (sizeof(CCH) - 1));
        ch[i] = CCH[x];
    }
    return ch;

}

string calculate_hash(string str) {

      int bs_size = SIZE_CHAR * sizeof(wchar_t);

      byte* bytes_string = new byte[bs_size];

      int n = 0; //real bytes count
      for (int i = 0; i < SIZE_CHAR; i++) {
            wchar_t wcharacter = str[i];

            int high_byte = wcharacter & 0xFF00;

            high_byte = high_byte >> 8;

            int low_byte = wcharacter & 0xFF;

            if (high_byte != 0) {
                bytes_string[n++] = (byte)high_byte;
            }

            bytes_string[n++] = (byte)low_byte;
          }
      SHA1 sha1;
      string hash;
      StringSource ss(bytes_string, n, true, new HashFilter(sha1, new HexEncoder(new StringSink(hash))));
      return hash;

}

string convert_hex_binary(string str) {

    string binary_str;

    for (int i = 0; i < str.size(); i++) {

      if (str[i] == '0') {
          binary_str += "0000";
      }
      else if (str[i] == '1') {
          binary_str += "0001";
      }
      else if (str[i] == '2') {
          binary_str += "0010";
      }
      else if (str[i] == '3') {
          binary_str += "0011";
      }
      else if (str[i] == '4') {
          binary_str += "0100";
      }
      else if (str[i] == '5') {
          binary_str += "0101";
      }
      else if (str[i] == '6') {
          binary_str += "0110";
      }
      else if (str[i] == '7') {
          binary_str += "0111";
      }
      else if (str[i] == '8') {
          binary_str += "1000";
      }
      else if (str[i] == '9') {
         binary_str += "1001";
      }
      else if (str[i] == 'A') {
          binary_str += "1010";
      }
      else if (str[i] == 'B') {
          binary_str += "1011";
      }
      else if (str[i] == 'C') {
          binary_str += "1100";
      }
      else if (str[i] == 'D') {
          binary_str += "1101";
      }
      else if (str[i] == 'E') {
          binary_str += "1110";
      }
      else if (str[i] == 'F') {
          binary_str += "1111";
      }

  }

  return binary_str;

}

Conclusion

I find a partial collision of 114 bits.

string 1

wjVaOoXXTn3BlSfmeHsjKlDIhkIV2mJe

hash1

38AB61B399F8FFB4AB159983C3FD757EED9B5CAD

string 2

7zjH48XHmH8J7xM15IZT0CJgInvjGryR

hash2

100A253FD8B06795A35DDDABE7F92466869A0E95

你可能感兴趣的:(理论基础)