解决加密问题,代码需要很长时间才能运行,需要对其进行优化

时间:2017-03-23 00:27:49

标签: c linux cryptography time-complexity cs50

我正在构建一个程序,其中一个将使用linux命令行发出密码的哈希作为第二个参数(./program,运行程序,作为第一个),程序将找到具有相应的字符串哈希(又名密码)给他。密钥最多需要4个字符(a-z,A-Z),带有2位盐(a-z,A-Z,0-9)。作为一个初学者,我不能提出除了使用6个循环来计算所有可能的组合之外的东西,这必然需要花费数小时来解决。这个问题是在线课程问题集(Harvard的cs50)的一部分,我正在使用该课程的库,所以如果你想能够使用下面程序中的函数和数据类型,以免被迫来使用您使用的库的相应功能/类型,您可以在edx上创建一个帐户并输入cs50.io.如果您需要更多信息,请参阅以下问题:http://docs.cs50.net/problems/crack/crack.html

源代码:

#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, string argv [])
{
    if (argc != 2){
        printf ("Oops! Goodbye!\n");
        return 1;
    }

    char letters [] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',     'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
                        'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E',    'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    char leet [] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
                    'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    char key [4];
    char salt [2];
    int i, j, k, l, m, n;
    for (i = 0; i < 52; i++){
        for (j = 0; j < 52; j++){
            for (k = 0; k < 52; k++){
                for (l = 0; l < 52; l++){
                    for (m=0; m < 62; m++){
                        for (n=0; n < 62; n++){
                        key [0] = letters [i];
                        key [1] = letters [j];
                        key [2] = letters [k];
                        key [3] = letters [l];
                        salt [0] = leet [m];
                        salt [1] = leet [n];
                        if (strcmp(crypt (key, salt), argv [1])==0){
                            printf ("%c%c%c%c", key [0], key [1], key [2], key [3]);
                            break;
                       }   
                   }   

                }

            }
        }
    }
}
printf ("\n");
return 0;
}

除了复杂性之外,如果您发现任何其他可以改进或应该更改的内容,请告诉我。所有建议都将受到高度赞赏。

编辑:感谢您抽出时间回答。我已经考虑了你的所有建议并更改了代码,但它仍然不会因为某些原因而运行(它不会打印任何内容,就好像条件(strcmp函数)永远不会满足)。你能详细说明可能出现的问题吗?还有一个问题。如何在带有命令行参数的程序中使用调试器?每当我使用调试器运行程序时,默认情况下只显示“./program”参数并退出。以下是新代码的外观:

#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, string argv [])
{
    char salt [] = "50";
    if (argc != 2)
    {
        printf ("Oops! Goodbye!\n");
        return 1;
    }

    char letters [] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char key [4];
    int i, j, k, l;
    for (i = 0; i < 52; i++){
        for (j = 0; j < 53; j++){
            for (k = 0; k < 53; k++){
                for (l = 0; l < 53; l++){
                        key [0] = letters [i];
                        key [1] = letters [j];
                        key [2] = letters [k];
                        key [3] = letters [l];
                        if (strcmp(crypt (key, salt), argv [1])==0)
                        {
                            printf ("%c%c%c%c", key [0], key [1], key [2], key [3]);    
                            break;
                        }

                }
            }
        }
    }
    printf ("\n");
    return 0;
}

2 个答案:

答案 0 :(得分:2)

两件事:首先,正如有人所说,你必须将 NULL终止字符串传递给crypt。你传递的是指向你可能的钥匙的第一个角色的指针,然后你祈祷它后面的内存中没有任何东西。我的意思是你应该将key声明为char [5]并将char [4]设置为0(将值设置为0而不是char&#39; 0&#39;(这是char&#39; \ 0&#39的方式) ;))。如果你没有终止它,crypt只会读取并读取,直到它找到其他零值,从而给你错误的哈希,因为密钥是不同的。

另外,为什么最外面的循环计数直到52而其他循环计数到53?这是非常安全的,因为您只是在letters[52]的密钥中设置了一个字符,恰好是前面提到的字符,基本上会过早地终止密钥字符串。所有循环应该一直持续variable < 52,53只会使程序变慢(你甚至不会注意到),任何更大的结果都会导致未定义的行为,因为你正在访问超出界限的值数组。

答案 1 :(得分:1)

从问题陈述中:

  

请务必阅读crypt,特别注意提及&#34; salt&#34;:

     

man crypt

你做到了吗?然后你会注意到盐是作为哈希的前两个字符给你的。 等一下,查看那些哈希密码:他们真的对每个密码使用相同的盐吗?这种安全性很差。 (提示:你正在做一个名为CS50的课程,每个密码上的盐为50)。

做哈希时盐的目的是什么?它阻止攻击者做什么?这些问题的答案将为您提供如何提高绩效的方法。祝你好运。