考虑到平台的兼容性,所以代码有点冗长,刚完成,2G以上的文件无法校验,所以,性能也没有优化,代码也没有整理,求大神指点迷津,为什么检验2G以上的文件会出错?
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#ifdef _WIN32
#include<windows.h>
#endif
//the program can't get right result;
//MD5.h
#ifdef uint64
#undef uint64
#define uint64 unsigned long long
#else
#define uint64 unsigned long long
#endif
#ifdef uint32
#undef uint32
#define uint32 unsigned int
#else
#define uint32 unsigned int
#endif
#ifdef uchar
#undef uchar
#define uchar unsigned char
#else
#define uchar unsigned char
#endif
//when you write a Macro,you should be care for bracket,because of Operation sequence
#ifdef crol
#undef crol
#define crol(temp,s) ((temp<<s)|(temp>>(0x20-s)))
#else
#define crol(temp,s) ((temp<<s)|(temp>>(0x20-s)))
#endif
#define F(X,Y,Z) ((X&Y)|((~X)&Z))
#define G(X,Y,Z) ((X&Z)|(Y&(~Z)))
#define H(X,Y,Z) (X^Y^Z)
#define I(X,Y,Z) (Y^(X|(~Z)))
#define FF(a,b,c,d,Mj,s,ti) a=b+(crol((a+F(b,c,d)+Mj+ti),s))
#define GG(a,b,c,d,Mj,s,ti) a=b+(crol((a+G(b,c,d)+Mj+ti),s))
#define HH(a,b,c,d,Mj,s,ti) a=b+(crol((a+H(b,c,d)+Mj+ti),s))
#define II(a,b,c,d,Mj,s,ti) a=b+(crol((a+I(b,c,d)+Mj+ti),s))
#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
#define BIT 8
#define BLOCK_SIZE 512
#define MOD_SIZE_BT 448
#define MOD_SIZE_BY MOD_SIZE_BT/BIT
#define FIRST_APPEND_BYTE 0x80
#define FILE_LEN 8
#define BLOCK_BYTE 64
typedef struct File_Info
{
bool Get_Len;
FILE *File_Point;
uint64 Info_Len, Info_Mod, Info_Size, Info_Div;
}FILE_POINT, *PFILE_POINT;
FILE_POINT File_S;
uint32 State[4] = { 0 };
uchar Ciphertext_32[16];
inline void Init_Info();
void MD5(char *Msg);
bool Init(char *Msg, char Type);
uint32 *Block_Sort(char *Info);
void GetMd5(char *Info, char);
uint64 Get_File_Len_Linux_Windows(char *filename);
#ifdef _WIN32
LPCTSTR Multi_To_Wide(char * Old_Name);
#endif
//MD5.c
#ifdef _WIN32
LPCTSTR Multi_To_Wide(char * Old_Name)
{
int num = MultiByteToWideChar(0, 0, Old_Name, -1, NULL, 0);
LPTSTR Now_Name = (LPTSTR)malloc(sizeof(wchar_t)*num);
MultiByteToWideChar(0, 0, Old_Name, -1, Now_Name, num);
return Now_Name;
}
#endif
uint64 Get_File_Len_Linux_Windows(char *filename)
{
#ifdef __linux
int i;
struct stat statbuf;
if ((i = stat(Msg, &statbuf)) == 0)
{
File_S.Get_Len = true;
return statbuf.st_size;
}
else{
File_S.Get_Len = false;
}
#endif
#ifdef _WIN32
uint64 File_Len = 0x0;
LPCTSTR Win_filename;
DWORD High, Low;
WIN32_FIND_DATA wfd = { 0 };
Win_filename = Multi_To_Wide(filename);
HANDLE hFile = FindFirstFile(Win_filename, &wfd);
if (hFile != NULL)
{
Low = wfd.nFileSizeLow;
High = wfd.nFileSizeHigh;
File_Len = Low | ((File_Len = High) << 32);
File_S.Get_Len = true;
}
else File_S.Get_Len = false;
FindClose(hFile);
return File_Len;
#endif
}
inline void Init_Info()
{
File_S.Info_Div = (File_S.Info_Len*BIT) / BLOCK_SIZE;
File_S.Info_Mod = (File_S.Info_Len*BIT) % BLOCK_SIZE;
File_S.Info_Size = File_S.Info_Len*BIT;
}
bool Init(char *Msg, char Type)
{
State[0] = A;
State[1] = B;
State[2] = C;
State[3] = D;
if (Type == 'M')
{
File_S.File_Point = NULL;
File_S.Info_Len = strlen(Msg);
Init_Info();
return true;
}
else if (Type == 'F')
{
File_S.File_Point = fopen(Msg, "rb");
File_S.Info_Len = Get_File_Len_Linux_Windows(Msg);
if (File_S.Get_Len == false) return false;
Init_Info();
return true;
}
else
return false;
}
uint32 *Block_Sort(char *Info)
{
static uint32 Num[16] = { 0 };
int i;
for (i = 0; i<16; i++)
{
memmove(&Num[i], &Info[i * 4], 4);
}
return Num;
}
void MD5(char *Msg)//只需要传入512位
{
uint32 *M, a, b, c, d;
M = Block_Sort(Msg);
a = State[0];
b = State[1];
c = State[2];
d = State[3];
FF(a, b, c, d, M[0], 7, 0xd76aa478);
FF(d, a, b, c, M[1], 12, 0xe8c7b756);
FF(c, d, a, b, M[2], 17, 0x242070db);
FF(b, c, d, a, M[3], 22, 0xc1bdceee);
FF(a, b, c, d, M[4], 7, 0xf57c0faf);
FF(d, a, b, c, M[5], 12, 0x4787c62a);
FF(c, d, a, b, M[6], 17, 0xa8304613);
FF(b, c, d, a, M[7], 22, 0xfd469501);
FF(a, b, c, d, M[8], 7, 0x698098d8);
FF(d, a, b, c, M[9], 12, 0x8b44f7af);
FF(c, d, a, b, M[10], 17, 0xffff5bb1);
FF(b, c, d, a, M[11], 22, 0x895cd7be);
FF(a, b, c, d, M[12], 7, 0x6b901122);
FF(d, a, b, c, M[13], 12, 0xfd987193);
FF(c, d, a, b, M[14], 17, 0xa679438e);
FF(b, c, d, a, M[15], 22, 0x49b40821);
GG(a, b, c, d, M[1], 5, 0xf61e2562);
GG(d, a, b, c, M[6], 9, 0xc040b340);
GG(c, d, a, b, M[11], 14, 0x265e5a51);
GG(b, c, d, a, M[0], 20, 0xe9b6c7aa);
GG(a, b, c, d, M[5], 5, 0xd62f105d);
GG(d, a, b, c, M[10], 9, 0x2441453);
GG(c, d, a, b, M[15], 14, 0xd8a1e681);
GG(b, c, d, a, M[4], 20, 0xe7d3fbc8);
GG(a, b, c, d, M[9], 5, 0x21e1cde6);
GG(d, a, b, c, M[14], 9, 0xc33707d6);
GG(c, d, a, b, M[3], 14, 0xf4d50d87);
GG(b, c, d, a, M[8], 20, 0x455a14ed);
GG(a, b, c, d, M[13], 5, 0xa9e3e905);
GG(d, a, b, c, M[2], 9, 0xfcefa3f8);
GG(c, d, a, b, M[7], 14, 0x676f02d9);
GG(b, c, d, a, M[12], 20, 0x8d2a4c8a);
HH(a, b, c, d, M[5], 4, 0xfffa3942);
HH(d, a, b, c, M[8], 11, 0x8771f681);
HH(c, d, a, b, M[11], 16, 0x6d9d6122);
HH(b, c, d, a, M[14], 23, 0xfde5380c);
HH(a, b, c, d, M[1], 4, 0xa4beea44);
HH(d, a, b, c, M[4], 11, 0x4bdecfa9);
HH(c, d, a, b, M[7], 16, 0xf6bb4b60);
HH(b, c, d, a, M[10], 23, 0xbebfbc70);
HH(a, b, c, d, M[13], 4, 0x289b7ec6);
HH(d, a, b, c, M[0], 11, 0xeaa127fa);
HH(c, d, a, b, M[3], 16, 0xd4ef3085);
HH(b, c, d, a, M[6], 23, 0x4881d05);
HH(a, b, c, d, M[9], 4, 0xd9d4d039);
HH(d, a, b, c, M[12], 11, 0xe6db99e5);
HH(c, d, a, b, M[15], 16, 0x1fa27cf8);
HH(b, c, d, a, M[2], 23, 0xc4ac5665);
II(a, b, c, d, M[0], 6, 0xf4292244);
II(d, a, b, c, M[7], 10, 0x432aff97);
II(c, d, a, b, M[14], 15, 0xab9423a7);
II(b, c, d, a, M[5], 21, 0xfc93a039);
II(a, b, c, d, M[12], 6, 0x655b59c3);
II(d, a, b, c, M[3], 10, 0x8f0ccc92);
II(c, d, a, b, M[10], 15, 0xffeff47d);
II(b, c, d, a, M[1], 21, 0x85845dd1);
II(a, b, c, d, M[8], 6, 0x6fa87e4f);
II(d, a, b, c, M[15], 10, 0xfe2ce6e0);
II(c, d, a, b, M[6], 15, 0xa3014314);
II(b, c, d, a, M[13], 21, 0x4e0811a1);
II(a, b, c, d, M[4], 6, 0xf7537e82);
II(d, a, b, c, M[11], 10, 0xbd3af235);
II(c, d, a, b, M[2], 15, 0x2ad7d2bb);
II(b, c, d, a, M[9], 21, 0xeb86d391);
State[0] += a;
State[1] += b;
State[2] += c;
State[3] += d;
}
void GetMd5(char *Info, char Type = 'M')//
{
int i;
char *Data_Temp = (char*)malloc(BLOCK_BYTE);
char *Temp = (char*)malloc(BLOCK_BYTE);
if (Init(Info, Type))
{
for (i = 0; i <= File_S.Info_Div + 1; i++)
{
memset(Data_Temp, 0x0, BLOCK_BYTE);
memset(Temp, 0x0, BLOCK_BYTE);
if (Type == 'F')
{
fread(Temp, 4, 16, File_S.File_Point);
}
else{
strncpy(Temp, &Info[i*BLOCK_BYTE], File_S.Info_Len);//strncpy,memmove,src不够长直接接着地址往下读,但是memmove全部读,strncpy,读指定字节只读0x0之前的
}
if (File_S.Info_Mod<448){
if (i == File_S.Info_Div)
{
memmove(Data_Temp, Temp, BLOCK_BYTE);
memmove(&Data_Temp[BLOCK_BYTE - FILE_LEN], &File_S.Info_Size, FILE_LEN);
Data_Temp[File_S.Info_Mod / BIT] = FIRST_APPEND_BYTE;
goto Do_5;
}
if (i == File_S.Info_Div + 1) goto End;
}
else{
if (i == File_S.Info_Div + 1)
{
memmove(&Data_Temp[BLOCK_BYTE - FILE_LEN], &File_S.Info_Size, FILE_LEN);
goto Do_5;
}
else if (i == File_S.Info_Div)
{
memmove(Data_Temp, Temp, BLOCK_BYTE);
Data_Temp[File_S.Info_Mod / BIT] = FIRST_APPEND_BYTE;
goto Do_5;
}
}
memmove(Data_Temp, Temp, BLOCK_BYTE);
Do_5: MD5(Data_Temp);
End:;
}
}
free(Data_Temp);
free(Temp);
}
int main()//文件太大时,时间长且结果错误,需优化算法<2G左右计算OK
{
char *p = "E:\\Test_.exe";
GetMd5(p, 'F');//完全版,p可以是字符串,也可以是文件名,main函数自己写,F代表file,M代表字符串
int i;
for (i = 0; i<16; i++)
{
Ciphertext_32[i] = (State[i / 4] >> (i % 4) * 8) & 0xff;
}
printf("32BIT:");
for (i = 0; i < 16; i++)
{
printf("%02x", Ciphertext_32[i]);
}
printf("\n16BIT:");
for (i = 4; i < 12; i++)
{
printf("%02x", Ciphertext_32[i]);
}
getchar();
}