2016-12-04 2 views
1

파일에서 해시 키를 생성하는 프로그램이 있습니다. 예 : 프로그램의 결과는 "hash of file c:\Users\Jax\Desktop\files\file.txt is: 4db5a10d2ea73e3f76"입니다. 프로그램의 결과 해시가 동일한 경우hashResult 변수가 올바른 값을 저장하지 않습니다.

char hashExpected = "4db5a10d2ea73e3f76"; 

내가 확인하고있어 코드의을 구체적으로 부분 :

그리고 나는이 file.txt를위한 예상 해시를 가지고있는 변수가 해시는 hashExpected 변수에 저장됩니다. 나는 이것을 아래와 같이 가지고있다. 나는 hashResult 결과 해시를 저장하는 변수를 가지고 있으므로 비교할 수 있습니다. 하지만 동등한 경우에도 항상 Hash is different을 표시하기 때문에 제대로 작동하지 않습니다. hashResult 변수가 올바른 값을 저장하지 않는 것으로 보입니다.

 for (i = 0; i < cbHash; i++) 
     { 
      printf("%c%c", 
        rgbDigits[rgbHash[i] >> 4], 
        rgbDigits[rgbHash[i] & 0xf]); 
      hashResult[i] = rgbDigits[rgbHash[i] >> 4]; 
      hashResult[i] += rgbDigits[rgbHash[i] & 0xf]; 
     } 
     if (verify(hashResult, hashExpected)) 
     { 
      printf("Hash is the same\n"); 
     } 
     else 
     { 
      printf("Hash is different\n"); 
     } 

전체 프로그램은 : MD5 값 위

#include <stdio.h> 
#include <windows.h> 
#include <Wincrypt.h> 
#include <stdbool.h> 
#define BUFSIZE 1024 
#define MD5LEN 16 

bool verify(char array1[], char array2[]) 
{ 
    int i; 
    for (i = 0; array1[i] && array2[i]; ++i) 
    { 
     if (array1[i] != array2[i]) 
     { 
      return false; 
     } 
    } 
    return true; 
} 
DWORD main() 
{ 
    DWORD dwStatus = 0; 
    BOOL bResult = FALSE; 
    HCRYPTPROV hProv = 0; 
    HCRYPTHASH hHash = 0; 
    HANDLE hFile = NULL; 
    BYTE rgbFile[BUFSIZE]; 
    DWORD cbRead = 0; 
    BYTE rgbHash[MD5LEN]; 
    DWORD cbHash = 0; 
    CHAR rgbDigits[] = "abcdef"; 
    PCSTR filename = "c:\\Users\\Jax\\Desktop\\files\\file.txt"; 
    char hashActual[] = "4db5a10d2ea73e3f76"; 
    char hashExpected[] = "4db5a10d2ea73e3f76"; 
    char hashWrong[] = "0a0a0a0a0a0a0a"; 
    char hashResult[] = ""; 
    hFile = CreateFile(filename, 
         GENERIC_READ, 
         FILE_SHARE_READ, 
         NULL, 
         OPEN_EXISTING, 
         FILE_FLAG_SEQUENTIAL_SCAN, 
         NULL); 


    if (INVALID_HANDLE_VALUE == hFile) 
    { 
     dwStatus = GetLastError(); 
     printf("Error opening file %s\nError: %d\n", filename, 
       dwStatus); 
     return dwStatus; 
    } 


    // Get handle to the crypto provider 
    if (!CryptAcquireContext(&hProv, 
          NULL, 
          NULL, 
          PROV_RSA_FULL, 
          CRYPT_VERIFYCONTEXT)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptAcquireContext failed: %d\n", dwStatus); 
     CloseHandle(hFile); 
     return dwStatus; 
    } 


    if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptAcquireContext failed: %d\n", dwStatus); 
     CloseHandle(hFile); 
     CryptReleaseContext(hProv, 0); 
     return dwStatus; 
    } 


    while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, 
           &cbRead, NULL)) 
    { 
     if (0 == cbRead) 
     { 
      break; 
     } 


     if (!CryptHashData(hHash, rgbFile, cbRead, 0)) 
     { 
      dwStatus = GetLastError(); 
      printf("CryptHashData failed: %d\n", dwStatus); 
      CryptReleaseContext(hProv, 0); 
      CryptDestroyHash(hHash); 
      CloseHandle(hFile); 
      return dwStatus; 
     } 
    } 


    if (!bResult) 
    { 
     dwStatus = GetLastError(); 
     printf("ReadFile failed: %d\n", dwStatus); 
     CryptReleaseContext(hProv, 0); 
     CryptDestroyHash(hHash); 
     CloseHandle(hFile); 
     return dwStatus; 
    } 


    cbHash = MD5LEN; 


    if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) 
    { 
     DWORD i; 

     printf("MD5 hash of file %s is: ", filename); 
     for (i = 0; i < cbHash; i++) 
     { 
      printf("%c%c", 
        rgbDigits[rgbHash[i] >> 4], 
        rgbDigits[rgbHash[i] & 0xf]); 
      hashResult[i] = rgbDigits[rgbHash[i] >> 4]; 
      hashResult[i] += rgbDigits[rgbHash[i] & 0xf]; 


     } 
     if (verify(hashResult, hashExpected)) 
     { 
      printf("Hash is the same\n"); 
     } 
     else 
     { 
      printf("Hash is different\n"); 
     } 
    } 
    else 
    { 
     dwStatus = GetLastError(); 
     printf("CryptGetHashParam failed: %d\n", dwStatus); 
    } 


    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    CloseHandle(hFile); 


    return dwStatus; 
} 
+1

버퍼 오버 플로우 : 귀하의'hashResult' 배열이 하나 개의 요소가 있습니다. 범위를 벗어나는'hashResult [i] = ...'를 사용하여 액세스합니다. – melpomene

답변

0
char hashExpected[] = "4db5a10d2ea73e3f76"; 

은 잘못된 것입니다. MD5 값은 16 바이트입니다. 그러나 그것은 단지 바이트를위한 것입니다. 화면에 바이트를 인쇄 할 수 없으므로 종종 바이트를 16 진수 값으로 변환합니다. 예를 들어, unsinged char bytes[3] = {0x01,0x01,0xFF}이있는 경우 바이트를 16 진수 문자열로 변환하면 "0102FF"이됩니다.

문자열 표현은 두 배 길고 널 종료자를 더한 것입니다. MD5 해시의 예는 다음과 같습니다 문자열에 대한

"C4CA4238A0B923820DCC509A6F75849B" 

버퍼 크기가 올바른 hashExpected을 찾을 "온라인 MD5 계산기"를 검색하려면

33 (16 × 2 + 1)이어야한다. http://onlinemd5.com/과 같은 웹 사이트를 사용하여 파일의 MD5를 계산할 수 있습니다.

또는 내용이 1 인 파일을 사용하십시오. MD5("1")"C4CA4238A0B923820DCC509A6F75849B" 인 경우이를 예상 해시 값으로 사용하십시오.

hashResult[i] = rgbDigits[rgbHash[i] >> 4]; 
hashResult[i] += rgbDigits[rgbHash[i] & 0xf]; 

코드가 잘못 위 @melpomene에 의해 주석에 언급 한 바와 같이 라인 위

char hashResult[] = ""; 

는 프로그래밍 오류, 당신이 대신 원하는 :

char hashResult[MD5LEN * 2 + 1] = ""; 
... 
hashResult[i * 2] = rgbDigits[rgbHash[i] >> 4]; 
hashResult[i * 2 + 1] = rgbDigits[rgbHash[i] & 0xf]; 

이 또한 문제가있는 것입니다 문자열 표현의 잘못된 MD5와 바이트 표현의 잘못된 MD5를 비교하기 때문에 함수 verify이 있습니다.

strcmp 또는 _stricmp을 사용하여 문자열 표현의 MD5 값을 비교할 수 있습니다. 또는 바이트를 직접 비교하려면 memcmp(data1, data2, 16)을 사용하십시오.

전체 예 :

#define BUFSIZE 1024 
#define MD5LEN 16 

int main() 
{ 
    DWORD dwStatus = 0; 
    HCRYPTPROV hProv = 0; 
    HCRYPTHASH hHash = 0; 
    HANDLE hFile = NULL; 
    BYTE rgbFile[BUFSIZE]; 
    DWORD cbRead = 0; 
    BYTE rgbHash[MD5LEN]; 
    DWORD cbHash = 0; 
    CHAR rgbDigits[] = "abcdef"; 
    PCSTR filename = "c:\\Users\\Jax\\Desktop\\files\\file.txt"; 

    //assuming content of file.txt is '1' 
    char hashExpected[] = "C4CA4238A0B923820DCC509A6F75849B"; 

    char hashResult[MD5LEN * 2 + 1] = ""; 
    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 
     NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

    if(INVALID_HANDLE_VALUE == hFile) 
    { 
     dwStatus = GetLastError(); 
     printf("Error opening file %s\nError: %d\n", filename, dwStatus); 
     return (int)dwStatus; 
    } 

    // Get handle to the crypto provider 
    if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptAcquireContext failed: %d\n", dwStatus); 
     CloseHandle(hFile); 
     return (int)dwStatus; 
    } 

    if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptAcquireContext failed: %d\n", dwStatus); 
     CloseHandle(hFile); 
     CryptReleaseContext(hProv, 0); 
     return (int)dwStatus; 
    } 

    while(ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL)) 
    { 
     if(0 == cbRead) 
      break; 

     if(!CryptHashData(hHash, rgbFile, cbRead, 0)) 
     { 
      dwStatus = GetLastError(); 
      printf("CryptHashData failed: %d\n", dwStatus); 
      CryptReleaseContext(hProv, 0); 
      CryptDestroyHash(hHash); 
      CloseHandle(hFile); 
      return (int)dwStatus; 
     } 
    } 

    cbHash = MD5LEN; 

    if(CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) 
    { 
     DWORD i; 

     printf("MD5 expected, versus MD5 of file %s is:\n", filename); 
     printf("%s\n", hashExpected); 
     for(i = 0; i < cbHash; i++) 
     { 
      printf("%c%c", 
       rgbDigits[rgbHash[i] >> 4], 
       rgbDigits[rgbHash[i] & 0xf]); 
      hashResult[i * 2] = rgbDigits[rgbHash[i] >> 4]; 
      hashResult[i * 2 + 1] = rgbDigits[rgbHash[i] & 0xf]; 
     } 
     printf("\n"); 

     if(_strcmpi(hashResult, hashExpected) == 0) 
      printf("Hash is the same\n"); 
     else 
      printf("Hash is different\n"); 
    } 
    else 
    { 
     dwStatus = GetLastError(); 
     printf("CryptGetHashParam failed: %d\n", dwStatus); 
    } 

    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    CloseHandle(hFile); 

    return (int)dwStatus; 
} 
+0

정말 자세한 설명을 해주셔서 감사합니다. 이제 그 문제를 이해합니다.지금 당신의 솔루션을 기쁘게하려고 노력했지만 이상한 오류를 보여줍니다. "오류 : ':: main'은 'int'를 반환해야합니다." 왜 그렇게 될 수 있는지 알고 있습니까? – Jax

+0

고맙습니다. 솔루션이 작동합니다! 자세한 설명을 주셔서 다시 한 번 감사드립니다. – Jax

관련 문제