user-0 提问: 关于MD5加密的问题！(C)为什么超过2G就会错误？

回复:
user: user-0
content: 解决了，不管是我一开始的方法 还是 zhao4zhong1 的方法来获取文件长度都是对的，不过相比较而言zhao4zhong1的方法根号代码量少，至于计算是没有问题的，是我开始在网上找的软件有问题，后来又下载了几个软件，结果OK啦 不过还是谢谢zhao4zhong1

user: user-1
content: 我只解决你获取文件长度问题。 至于你计算结果错误，参考下面： #include <stdio.h> #include <math.h> #include <string.h> #include <memory.h> const unsigned int s[4][4]={{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}}; const unsigned long t[64]={//t[i]=4294967296*fabs(sin(i+1));  0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,  0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,  0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,  0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,  0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,  0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,  0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,  0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 }; const int serial[64]={  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,  1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,  5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,  0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 }; void func(unsigned long& a,           unsigned long b,           unsigned long c,           unsigned long d,           unsigned long M,           unsigned long t,           int s,           int turn) {     unsigned long temp;     switch(turn) {     case 0:         temp=(b&c)|((~b)&d);         break;     case 1:         temp=(d&b)|((~d)&c);         break;     case 2:         temp=b^c^d;         break;     case 3:         temp=c^(b|(~d));         break;     }     temp+=M+t+a;     _asm {         mov ecx,s         rol temp,cl     }     a=b+temp; } void MD512(const unsigned long M[16],unsigned long hash[4]) {     int i,j,index=0;     for (i=0;i<4;i++)         for (j=0;j<4;j++) {             func(hash[0],hash[1],hash[2],hash[3],M[serial[index]],t[index],s[i][0],i);             index++;             func(hash[3],hash[0],hash[1],hash[2],M[serial[index]],t[index],s[i][1],i);             index++;             func(hash[2],hash[3],hash[0],hash[1],M[serial[index]],t[index],s[i][2],i);             index++;             func(hash[1],hash[2],hash[3],hash[0],M[serial[index]],t[index],s[i][3],i);             index++;         } }  void MD5(char* M,int nLen,unsigned long output[4]) {     int i,j;     unsigned long Hash[4]={0x67452301,0xefcdab89,0x98badcfe,0x10325476};     unsigned long hash[4];      //填充     __int64 BitsLen=nLen*8;     int oldlen=nLen;     while(nLen%64!=56) {         M[nLen++]=0;     }     M[oldlen]=0x80u;     *(__int64*)(M+nLen)=BitsLen;     nLen+=8;      //开始处理分组     for (i=0;i<nLen;i+=64) {         memcpy(hash,Hash,sizeof(long)*4);         MD512((const unsigned long*)&M[i],hash);//处理512bits分组         for (j=0;j<4;j++)             Hash[j]+=hash[j];     }      //处理输出。     for (i=0;i<4;i++)         for (j=3;j>=0;j--) {             *((char*)(output+i)+j)=*((char*)(Hash+i)+3-j);         } } int main() {     int i;     char szMessage[1000]={0};     printf("input a string:\n>>>");     scanf("%s",szMessage);     unsigned long output[4];     MD5(szMessage,strlen(szMessage),output);     for (i=0;i<4;i++)         printf("%08lx",output[i]);     printf("\n");     return 0; }

user: user-2
content: fopen只能打开2G以下的文件，大于2G的需要打开64bit支持。

user: user-0
content: 抱歉，貌似是错的！给张图片

user: user-1
content: #include<stdio.h> #include<string.h> #include<malloc.h> #include <sys/types.h> #include <sys/stat.h> #ifdef _WIN32 #include<windows.h> #include<io.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); //MD5.c  uint64 Get_File_Len_Linux_Windows(char *filename) { #ifdef __linux     struct stat64 statbuf;     if (stat64(filename, &statbuf)==0)     {         File_S.Get_Len = true;         return statbuf.st_size;     } else {         File_S.Get_Len = false;         return 0;     } #endif #ifdef _WIN32     struct _stat64 statbuf;     if (_stat64(filename, &statbuf)==0)     {         File_S.Get_Len = true;         return statbuf.st_size;     } else {         File_S.Get_Len = false;         return 0;     } #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(); }