让我解释一下我的程序的整体功能。用户可以输入一个字符串,该字符串将根据MD5哈希算法进行哈希处理。然后它将字符串打印到stdout。
我发现使用并集结构简化了代码:
union md5hash
{
uint ui[4]; //= 16 bytes --> 128 bits
char ch[16]; //= 16 bytes --> 128 bits
};
我的程序在那种情况下运行良好。
但是,我想扩展我的程序的功能。我希望通过stdin输入MD5散列,而不是输入要散列的字符串。
以下是一个尝试复制此功能的短程序:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
typedef unsigned int uint;
union md5hash
{
uint ui[4]; //= 16 bytes --> 128 bits
char ch[16]; //= 16 bytes --> 128 bits
};
int main(void){
std::string hash = "abcdefghjklqwertyuiopasdfghjklzx";
std::cout << hash.length();
char* chash = (char*) malloc(sizeof(hash.length()+1));
memcpy(chash, hash.c_str(), hash.size()+1);
for(int i = 0; chash[i] ; i++) printf("%c",chash[i]);
md5hash test = chash;
getchar();
}
是的,我知道我的数组有32个字符长,而联合中的数组只有16个字符(这是我尚未解决的问题)。在任何情况下,我都需要通过stdin输入的散列与散列后的字符串的形式相同。
例如:
Enter string: "Hello"
Goes through hash algorithm: 5d41402abc4b2a76b9719d911017c592
Enter hash:"5d41402abc4b2a76b9719d911017c592"
Are they equal? (Compare their hash values).
但是,hash是一个char数组,而hashed值是一个md5hash数据类型。如何将通过stdin输入的hash转换为md5hash数据类型?
此外,我使用的是Dev C++,它使用GCC(GNU编译器集合)的Mingw端口作为编译器。我收到的错误是
conversion from `char*' to non-scalar type `md5hash' requested.
(我收到上述程序的错误并不感到惊讶)。
欢迎提供任何建设性意见。
编辑:
这就是我对字符串进行哈希的方式(这不是完整的代码,但这是字符串进行哈希准备的方式):
void md5_prep(char *c0)
{
uint len = 0;
char *c = c0;
while(*c) {len++; c++;}
c[0] = 0x80; // bit 1 after the message (Appears counterintuitive, but remember c was incremented in the above loop
((uint*)c0)[14] = len * 8; // message length in bits (Note: 4 * 14 is 56 - appends to end of buffer as stated in Wikipedia's psuedocode)
}
void print_md5(uint *hash, bool crlf)
{
for(int i = 0; i != 16; i++) { printf("%02x", (uint)(((unsigned char *)hash)[i])); }
if(crlf) printf("n");
}
union md5hash
{
uint ui[4]; //= 16 bytes --> 128 bits (allows the message to be divided into chunks due to union structure)
char ch[16]; //= 16 bytes --> 128 bits
};
md5hash single_md5(char* ptext)
{
md5hash h;
char w[64] = {0}; //Declare an empty array
//for(int i = 0; ptext[i]; i++) w[i] = ptext[i];
strncpy(w, ptext, 56); //Copy over the text to be hashed; this effectively "zero pads" the string (limiting to 56 - my choice)
md5_prep(w);
MD5_CPU((uint*)&w[0], h.ui[0], h.ui[1], h.ui[2], h.ui[3]); //Hash the message
return h;
}
//Test
int main(void){
//Declarations
std::string target = "Hello";
char tes[120] = {0};
tes[0] = 'h';
tes[1] = 'e';
for(int i =0; tes[i]; i++)
printf("%c", tes[i]);
printf("n");
//Execute
md5hash test = single_md5(tes);
print_md5(test.ui, false);
return 0;
}
因此,如果我想将输入的哈希与从输入的字符串中计算的哈希进行比较,我可以执行以下
a == target[0] && b == target[1] && c == target[2] && d == target[3]
其中a,b,c,d
是ui[1], ui[2], ui[3], ui[4]
。
然而,我需要以某种方式将散列字符串转换为联合定义的形式。
您的问题似乎是用户输入了哈希的32位文本(十六进制)表示,而您需要原始数据。因此,您必须在两者之间进行转换:
int hex2int(char ch)
{
if (isdigit(ch))
return ch - '0';
switch (ch) {
case 'a': case 'A': return 10;
case 'b': case 'B': return 11;
case 'c': case 'C': return 12;
case 'd': case 'D': return 13;
case 'e': case 'E': return 14;
case 'f': case 'F': return 15;
default: abort(); // shan't happen
}
}
char md5_hex2raw(char raw[16], const char hex[32])
{
for (int i = 0; i < 32; i += 2) {
raw[i] = (hex2int(hex[0]) << 4) | hex2int(hex[1]);
}
}
然后,您可以调用转换函数,使其直接复制到联合中:
md5hash hash;
md5_hex2raw(hash.ch, user_entered_string);
我认为您应该编写一个函数来实现这种覆盖,如下所示:
union md5hash str2md5hash(const char *str)
{
union md5hash out = {0};
strcpy(out.ch,str);
return out;
}
union md5hash int2md5hash(int data)
{
union md5hash out = {0};
out.ui = data;
return out;
}