密码学原理_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 <iostream>
#include <string.h>
#include <time.h>
#include <cryptopp/cryptlib.h>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>

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
sha碰撞,MD5碰撞实现,#!/usr/local/bin/perl # It was noted that Intel IA-32 C compiler generates code which # performs ~30% *faster* on P4 CPU than original *hand-coded* # SHA1 assembler implementation. To address this problem (and # prove that humans are still better than machines:-), the # original code was overhauled, which resulted in following # performance changes: # # compared with original compared with Intel cc # assembler impl. generated code # Pentium -25% +37% # PIII/AMD +8% +16% # P4 +85%(!) +45% # # As you can see Pentium came out as looser:-( Yet I reckoned that # improvement on P4 outweights the loss and incorporate this # re-tuned code to 0.9.7 and later. # ---------------------------------------------------------------- # Those who for any particular reason absolutely must score on # Pentium can replace this module with one from 0.9.6 distribution. # This "offer" shall be revoked the moment programming interface to # this module is changed, in which case this paragraph should be # removed. # ---------------------------------------------------------------- # $normal=0; push(@INC,"perlasm","../../perlasm"); require "x86asm.pl"; &asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386"); $A="eax"; $B="ecx"; $C="ebx"; $D="edx"; $E="edi"; $T="esi"; $tmp1="ebp"; $off=9*4; @K=(0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6); &sha1_block_data("sha1_block_asm_data_order"); &asm_finish(); sub Nn { local($p)=@_; local(%n)=($A,$T,$B,$A,$C,$B,$D,$C,$E,$D,$T,$E); return($n{$p}); } sub Np { local($p)=@_; local(%n)=($A,$T,$B,$A,$C,$B,$D,$C,$E,$D,$T,$E); local(%n)=($A,$B,$B,$C,$C,$D,$D,$E,$E,$T,$T,$A); return($n{$p}); } sub Na { local($n)=@_; return( (($n )&0x0f), (($n+ 2)&0x0f), (($n+ 8)&0x0f), (($n+13)&0x0f), (($n+ 1)&0x0f)); } sub X_expand { local($in)=@_; &comment("First, load the words onto the stack in network byte order"); for ($i=0; $i<16; $i+=2) { &mov($A,&DWP(($i+0)*4,$in,"",0));# unless $i == 0; &mov($B,&DWP(($i+1)*4,$in,"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值