Из википедии: MD5("md5") = 1bc29b36f623ba82aaf6724fd3b16718 MD5("md4") = c93d3bf7a7c4afe94b64e30c2ce39f4f MD5("") = d41d8cd98f00b204e9800998ecf8427e Уменя получилось: MD5("md5") = 8972340305b0d53ba4492ac367424f3e MD5("md4") = 8972340305b0d53ba4492ac367424f3e MD5("") = d41d8cd98f00b204e9800998ecf8427e - сходится Реализовывал двумя способами и получается, что последняя буква в строке не играет роли. А если строка большая, то несколько последних букв любые с итоговым одинаковым хэшем. Где ошибка?
void Ccrypt_hashDlg::OnBnClickedButton1() { // Declare and initialize variables. HCRYPTPROV hCryptProv = NULL; // handle for a cryptographic provider context PTCHAR UserName = L"MyKeyContainer"; // name of the key container to be used // Attempt to acquire a context and a key // container. The context will use the default CSP // for the RSA_FULL provider type. DwFlags is set to zero // to attempt to open an existing key container. if(CryptAcquireContext(&hCryptProv,UserName,NULL,PROV_RSA_FULL,0)) { MessageBox(UserName,L"context has been acquired"); } else { // An error occurred in acquiring the context. This could mean // that the key container requested does not exist. In this case, // the function can be called again to attempt to create a new key // container. Error codes are defined in Winerror.h. if(GetLastError() == NTE_BAD_KEYSET) { if(CryptAcquireContext(&hCryptProv,UserName,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET)) { MessageBox(L"A new key container has been created"); } else { MessageBox(L"Could not create a new key container"); return; } } else { MessageBox(L"A cryptographic service handle could not be acquired"); return; } } // A cryptographic context and a key container are available. // Acquire a hash object handle. HCRYPTHASH hOriginalHash; if(CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hOriginalHash)) { MessageBox(L"An empty hash object has been created"); } else { MessageBox(L"Error during CryptCreateHash()"); return; } UpdateData(); // текст из Edit1 в m_Str BYTE *pbBuffer = (BYTE*)m_Str.GetBuffer();//(BYTE *)"The data that is to be hashed and signed."; DWORD dwBufferLen = m_Str.GetLength();//strlen((char *)pbBuffer)+1; if(CryptHashData(hOriginalHash,pbBuffer,dwBufferLen,0)) { MessageBox(L"The data buffer has been added to the hash"); } else { MessageBox(L"Error during CryptHashData()"); return; } // At this point, the content of pbBuffer has been added to the hash. // Additional data can be added by repeatedly calling CryptHashData. Get_And_Print_Hash(hOriginalHash); // After processing, hCryptProv and hHash must be released. if(hOriginalHash) CryptDestroyHash(hOriginalHash); // When the handle is no longer needed, it must be released. if(hCryptProv) { if(CryptReleaseContext(hCryptProv,0)) { MessageBox(L"The handle has been released"); } else { MessageBox(L"The handle could not be released"); } } } //-------------------------------------------------------------------- void Ccrypt_hashDlg::Get_And_Print_Hash(HCRYPTHASH hOHash) { HCRYPTHASH hHash; BYTE *pbHash; BYTE *pbHashSize; DWORD dwHashLen = sizeof(DWORD); // Duplicate the hash passed in. // The hash is duplicated to leave the original hash intact. if(!CryptDuplicateHash(hOHash,NULL,0,&hHash)) { MessageBox(L"Error during CryptDuplicateHash()"); return; } if(!(pbHashSize =(BYTE *) malloc(dwHashLen))) { MessageBox(L"Memory allocation failed"); return; } if(CryptGetHashParam(hHash,HP_HASHSIZE,pbHashSize,&dwHashLen,0)) { free(pbHashSize); } else { MessageBox(L"CryptGetHashParam failed to get size"); return; } if(!CryptGetHashParam(hHash,HP_HASHVAL,NULL,&dwHashLen,0)) { MessageBox(L"CryptGetHashParam failed to get length"); return; } pbHash = (BYTE*)malloc(dwHashLen); if(!pbHash) { MessageBox(L"Allocation failed"); return; } if(CryptGetHashParam(hHash,HP_HASHVAL,pbHash,&dwHashLen,0)) { // Print the hash value char tmp[32]; char buf[128]; RtlZeroMemory(tmp,32); RtlZeroMemory(buf,128); // Bytes to string for(int i=0; i<dwHashLen; i++) { //_itoa_s(pbHash,tmp,32,10); wsprintfA(tmp,"%2.2x",pbHash); lstrcatA(buf,tmp); //lstrcatA(buf,","); } //MessageBoxA(0,buf,"Hash",MB_OK); SetWindowTextA((GetDlgItem(IDC_EDIT2))->m_hWnd,(LPCSTR)buf); } else { MessageBox(L"Error during reading hash value."); return; } free(pbHash); if(!CryptDestroyHash(hHash)) { MessageBox(L"ERROR - CryptDestroyHash()"); } }
Код (Text): /* md5.h - header file for md5.c */ /* RSA Data Security, Inc., MD5 Message-Digest Algorithm */ /* NOTE: Numerous changes have been made; the following notice is included to satisfy legal requirements. Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ #pragma once #ifndef H__MD5 #define H__MD5 typedef unsigned long UINT4; typedef struct { UINT4 state[4]; UINT4 count[2]; unsigned char buffer[64]; } MD5; void MD5Open(MD5 *); void MD5Digest(MD5 *, const void *, unsigned int); void MD5Close(MD5 *, unsigned char[16]); #endif /* md5.c - RSA Data Security, Inc., MD5 Message-Digest Algorithm */ /* NOTE: Numerous changes have been made; the following notice is included to satisfy legal requirements. Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ //#include <memory.h> #include "stdafx.h" #include "md5.h" #define LITTLE_ENDIAN 1 void MD5Open(MD5 *md5) { md5->count[0] = md5->count[1] = 0; /* Load magic initialization constants.*/ md5->state[0] = 0x67452301; md5->state[1] = 0xefcdab89; md5->state[2] = 0x98badcfe; md5->state[3] = 0x10325476; } /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 /* F, G, H and I are basic MD5 functions. */ #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))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform(UINT4 state[4], const unsigned char block[64]) { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; /* Move contents of block to x, putting bytes in little-endian order. */ #ifdef LITTLE_ENDIAN memcpy(x, block, 64); #else { unsigned int i, j; for (i = j = 0; i < 16; i++, j+= 4) { x[i] = (UINT4) block[j] | (UINT4) block[j+1] << 8 | (UINT4) block[j+2] << 16 | (UINT4) block[j+3] << 24; } } #endif /* Round 1 */ FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ memset(x, 0, sizeof(x)); } void MD5Digest(MD5 *md5, const void *input, unsigned int inputLen) { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((md5->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((md5->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) md5->count[1]++; md5->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible.*/ if (inputLen >= partLen) { memcpy(&md5->buffer[index], input, partLen); MD5Transform(md5->state, md5->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform(md5->state, (const unsigned char *) input + i); index = 0; } else i = 0; /* Buffer remaining input */ memcpy(&md5->buffer[index], (char *) input + i, inputLen-i); } /* ENCODE packs a 32-bit unsigned integer into 4 bytes in little-endian order. */ #ifdef LITTLE_ENDIAN #define ENCODE(p,n) *(UINT4 *)(p) = n #else //#define ENCODE(p,n) (p)[0]=n,(p)[1]=n>>8,(p)[2]=n>>16,(p)[3]=n>>24 #endif void MD5Close(MD5 *md5, unsigned char digest[16]) { unsigned char bits[8]; unsigned int index, padLen; static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* Save number of bits */ ENCODE(bits, md5->count[0]); ENCODE(bits+4, md5->count[1]); /* Pad out to 56 mod 64. */ index = (unsigned int)((md5->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Digest(md5, PADDING, padLen); /* Append length (before padding) */ MD5Digest(md5, bits, 8); /* Store state in digest */ ENCODE(digest, md5->state[0]); ENCODE(digest+4, md5->state[1]); ENCODE(digest+8, md5->state[2]); ENCODE(digest+12, md5->state[3]); /* Zeroize sensitive information. */ memset(md5, 0, sizeof(MD5)); } void Cmd5_hashDlg::OnBnClickedButton1() { MD5 *pmd5 = new MD5; unsigned buflen; // number of bytes in block unsigned char digest[16]; // digest // UpdateData(); buflen = InputStr.GetLength(); MD5Open(pmd5); MD5Digest(pmd5, InputStr.GetBuffer(), buflen); MD5Close(pmd5, digest); if(pmd5) delete pmd5; // char tmp[5]; char buf[100]; RtlZeroMemory(tmp,5); RtlZeroMemory(buf,100); // Bytes to string for(int i=0; i<16; i++) { _itoa_s(digest[i],tmp,4,10); lstrcatA(buf,tmp); lstrcatA(buf,","); } SetWindowTextA((GetDlgItem(IDC_EDIT2))->m_hWnd,(LPCSTR)buf); UpdateData(); //Msg(InputStr); }
все, разобрался: Код (Text): UpdateData(); // текст из Edit1 в m_Str DWORD dwBufferLen; BYTE *pbBuffer = new BYTE[1024]; if(pbBuffer) { memset(pbBuffer,0,1024); dwBufferLen = m_Str.GetLength(); WideCharToMultiByte(CP_ACP,0,(WCHAR*)m_Str.GetBuffer(),dwBufferLen, (char*)pbBuffer,dwBufferLen,0,0); //MessageBoxA(0,(char*)pbBuffer,"you enter:",0);