我正在做一个作业,其中我必须破解基于DES的哈希密码。
用户在命令行参数中输入哈希密码;我对每种可能性进行哈希处理(假设盐是50,传递的长度不超过4个字符,并且字符可以是abc ... xyz和ABC ... XYZ);当我的哈希值和命令行中的哈希值相等时,我将打印未加密的密码。
密码长度为1个字符,一切正常,但是密码长度为2个字符时,我遇到了一些麻烦。我希望这个问题简短,不要让您不知所措,因此,如果您希望看到它,我将在整个结尾发布我的整个代码。
因此,我在这一行中输入了密码可能包含的可能字符:
string options="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
然后我建立可能的密码。
我从选项中取出第一个字符,并将其存储在变量
pass2
的位置[0]中(此时,pass2 ='a')。然后,对位置[1]进行相同次数的选择(包含存储pass2的第二个值-> pass2 ='aa'..'aZ')。如果这些选项都不是我要查找的密码,则再次使用第一个字符(pass2 ='bZ'),然后尝试使用位置[1]的其他选项(pass2 ='ba') ... 等等。代码:char pass2[0][1] = "aa";
for (int j=0, n=strlen(options); j<n; j++)
{
pass2[0]=options[j];
for (int i=0; i<n; i++)
{
pass2[1]=options[i];
string hash2=crypt(pass2, "50");
if (memcmp(hash2, argv[1], 13)==0)
{
printf("%s\n", pass2);
}
}
}
使用上面的代码,我希望我的程序使用变量
pass2
并存储以下内容:aa,ab,ac,...,aX,aY,aZ,...,Za,Zb,Zc,... ,ZX,ZY,ZZ。当我阅读代码时,它对我很有意义。 (我的经验为零,但是我真的感觉这次我写了一些连贯的,应该起作用的东西)。但是,事实并非如此。这使我认为我编写/声明/初始化某些东西的方式可能存在一些问题。此外,以下错误代码也支持该想法:
error: array initializer must be an initializer list
char pass2[][1] = "ab";
如果有人意识到问题出在哪里,请告诉我,因为我已经尝试了所有可能的方法来对在此answer上找到的数组进行delcare,但仍然会收到错误消息。好吧,即使我没有收到错误消息,它也不起作用,因此任何解决方案都将受到欢迎。
谢谢你们!
就像我之前说过的,如果有人想检查一下,这是我的完整代码:
#define _XOPEN_SOURCE
#include <cs50.h>
#include <string.h>
#include <stdio.h>
#include <crypt.h>
int main(int argc, string argv[])
{
if (argc!=2){
printf("Usage: ./crack hash\n");
return 1;
}
string options="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char pass1[]="A";
for (int i=0, n=strlen(options); i<n; i++)
{
pass1[0]=options[i];
string hash1=crypt(pass1, "50");
if (memcmp(hash1, argv[1], 13)==0)
{
printf("%c\n", options[i]);
return 0;
}
}
char pass2[0][1] = "aa";
for (int j=0, n=strlen(options); j<n; j++)
{
pass2[0]=options[j];
for (int i=0; i<n; i++)
{
pass2[1]=options[i];
}
string hash2=crypt(pass2, "50");
if (memcmp(hash2, argv[1], 13)==0)
{
printf("%s\n", pass2);
}
}
}
最佳答案
首先,了解C数组的真正含义并不容易。麻烦的是,括号符号[]
在指针和数组之间造成各种混乱。
在这里,您需要的是一个能够容纳最大可能的密码候选者的数组。由于它限制为4个字符,并且C字符串必须带有终止\0
字符,因此最多需要5个字节。
然后,您将必须使用1到4个字母的所有可能组合来初始化该候选字符串,这是经典的组合问题。
这等效于枚举以52为底的所有n位数字(所有可能的字符),或以0到52n-1进行计数(以52为底),n在1到4之间。
将生成所有可能的密码候选者的循环如下所示:
// despite the array notation, this is a pointer to a constant string of 53 chars
// (including the automatically generated terminating \0)
char Letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define ALPHABET_SIZE 52
#define MAX_PASSWORD_LENGTH 4
void try_password (long enumerator, int length)
{
// this is an actual array that can hold 4 chars plus the \0 terminator
char candidate[MAX_PASSWORD_LENGTH+1];
int i;
// convert the enumerator into a base 52 number
// (will be written in reverse order, but in that case we don't care)
for (i = 0 ; i != length ; i++)
{
candidate[i] = Letters[enumerator%ALPHABET_SIZE];
enumerator /= ALPHABET_SIZE;
}
candidate[i] = '\0'; // add string terminator
// check password candidate
if (check_password (candidate))
{
printf ("Yay! %s\n", candidate);
}
}
void try_fixed_length_passwords (int length)
{
long enumerator = 1; // must be big enough to hold 52^^4 - 1 (>= 24 bits)
int i;
for (i = 0 ; i != length ; i++) enumerator *= ALPHABET_SIZE;
// now enumerator = 52^^length
// you could also use math.h and compute enumerator = (long)pow(52,length)
// enumerate all password candidates of a given length
while (enumerator != 0)
{
enumerator--; /// will count from 52^^lenght-1 to 0
try_password (enumerator, length);
}
}
void try_all_passwords (void)
{
// try all possible password lengths
int i;
for (i = 1 ; i <= MAX_PASSWORD_LENGTH ; i++) try_fixed_length_passwords(i);
}