可以对此自定义MD5比较进行哪些优化?

时间:2013-12-30 14:57:03

标签: c++ optimization md5 password-recovery

我正在尝试优化此代码,该代码将maskprocessor生成的字符串通过命令行管道提供,在它们上运行两轮OpenSSL libary MD5(其中第二次运行仅使用部分数量的来自第一个的结果)并将它们与命令行上提供的散列进行比较。

目前在Core i7 2.67GHz联想ThinkPad X201上以大约800,000线/秒的速度运行,在10秒内完成7,311,616线。我真的很想看看是否有任何可以改进的方法。我使用Visual Studio 2012,现在使用2013作为我的基础(从bash演变而来是Perl脚本)。

我认为这个过程中唯一的瓶颈就是比较,我已经从strcmp切换到了memcmp(虽然没有看到大的提升)。 MD5和掩码处理器的生成超出了我用自己的代码替换的能力。

此代码是我通过哈希冲突恢复StuffIt 5密码的项目的一部分,并且运行得非常好,但速度的提升将是一个很大的好处(特别是在运行多个实例时)。

Performance Perl vs. compiled

提供了该流程的图片

我绝不是一个称职的程序员,而且我知道如果Hashcat或任何GPU加速密码破解程序都可以实现这个算法,它会让我失去水力,但是没有足够的需求来实现它。相信我,我问:(

    #define _CRT_SECURE_NO_WARNINGS 
    // Need OpenSSL Libs linked, headers linked, dlls linked
    #include <stdio.h>
    #include <string.h>
    #include <openssl/md5.h>
    #include <iostream>
    #include <ctime>

    using namespace std;
    int main(int argc, char* argv[]) 
    { 
    /* Start - Setup Timer */

    std::clock_t start;
    double duration;
    start = std::clock();

    /* End - Setup Timer */

    /* Start - Hash Length Check */

    int j;
    for(int i = 1; i < argc; i++) {
      j = strlen(argv[i]);
    if (j != 10){
            std::cout<<argv[i]<<" is "<<j<<" characters long - not 10! Quitting\n";
            return 0;}
    }

    /* End - Hash Length Check */

    /* Start - Line Entry and Count */
     char string[40]; 
     int i;
     __int64 linecount = 0; // caps at 9,223,372,036,854,775,807
     int millioncount = 0;
//  printf("Enter a string: ");
  while(fgets(string, 40, stdin)){

  /* remove newline, if present */
  i = strlen(string)-1;
  if( string[i] == '\n') 
      string[i] = '\0';

  //printf("This is your string: %s", string);
  linecount++;
  if(linecount%10000000 == 0){
      millioncount++;
    duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
    double linespersec = linecount/duration;
    std::cout<<millioncount*10<<" million tries ("<<linespersec<<" l/s)\n";
  }
    /* End- Line Entry */

  /* Start - MD5 Round 1 */

   unsigned char digest[MD5_DIGEST_LENGTH];
    char string2[5];     
    MD5((unsigned char*)&string, strlen(string), (unsigned char*)&digest);    

    /* End - MD5 Round 1 */

    /* Start - MD5 Round 2 */

// Set the string to the second MD5 hash of the first 5 characters (10 bit)
    //for(int i = 0; i < 5; i++)
        //string2[i] = digest[i];
    memcpy(string2, digest, 5);
    MD5((unsigned char*)&string2, 5, (unsigned char*)&digest);    

    char mdString3[33];

    for(int i = 0; i < 5; i++)
         sprintf(&mdString3[i*2], "%02x", (unsigned int)digest[i]);

  //  printf("\nmd5 digest: %s\n", mdString3);
       /* End - MD5 Round 2 */

    /* Start - Hash Check */
for(int i = 1; i < argc; i++) {

    //if (mdString3[0] == argv[i][0] && strcmp(mdString3, argv[i]) == 0){ // added the 0 comp, no real improvements
    if (memcmp(mdString3, argv[i], 10) == 0){ // 785-795k
            printf("Success at: %s", string);
    duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
    double linespersec = linecount/duration;
    std::cout<<" for "<< argv[i]<<" in "<< duration <<" seconds at line "<<linecount<<" ("<<linespersec<<" l/s)\n";
    }
}
  }
    /* End - Hash Check*/

  /* Start - Timer Closeout */
    duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
        double linespersec = linecount/duration;
    std::cout<<"Exhausted search of "<<linecount<<" lines in "<< duration <<" seconds ("<<linespersec<<" l/s)\n";
/* End - Timer Closeout */
    return 0;
}

1 个答案:

答案 0 :(得分:0)

您可以通过消除sprintf调用周围的循环来获得改进,并改为使用它:

sprintf(&mdString3[0], 
        "%02x%02x%02x%02x%02x", 
        (unsigned char)digest[0],
        (unsigned char)digest[1], 
        (unsigned char)digest[2], 
        (unsigned char)digest[3], 
        (unsigned char)digest[4]);