//-------------------------------------------------------------------- // SHA1 hash a string as ASCII and UNICODE, or hash a file // based on MSDN sample. // If a file is hashed, calculate the hash value for cat file entry. // 10/2005 ; updated 03/2006 // JavaScience Consulting //-------------------------------------------------------------------- #include #include #include #include void HandleError(char *s); BYTE *ReadFileBlob(LPCSTR filename, DWORD *cbBlob); void CalcDumpHash(DWORD bytes, BYTE *pbData); void DumpHex(DWORD bytes, BYTE *data); void DumpB64(DWORD bytes, BYTE *data); void Wait(char *s); #define MAXSTRLEN 128 void main(void) { //------------------------------------------------------------- // Declare and initialize variables. BYTE *pbBuffer; DWORD dwBufferLen; DWORD i; DWORD dwCount = sizeof(DWORD); DWORD dwB64len = sizeof(DWORD); PCHAR szSource; PWCHAR swzSource; HANDLE hFile = NULL; BOOL hashFile = FALSE; BYTE *pbCatHash; // hash for cat file DWORD cbCatHash; if(!(szSource=(char *)malloc(MAXSTRLEN))) HandleError("Memory allocation failed."); printf("Enter filename or string to hash: "); while( strlen(fgets(szSource, MAXSTRLEN, stdin)) > 1) //if at least one character { hashFile = FALSE; if(szSource[strlen(szSource)-1] == '\n') //remove terminal \n character if present szSource[strlen(szSource)-1] = '\0'; hFile=CreateFileA(szSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile==INVALID_HANDLE_VALUE){ if (GetLastError()==ERROR_FILE_NOT_FOUND){ //printf("File doesn't exist\n"); } else { // Other errors } } else { hashFile = TRUE; cbCatHash = 0; if(CryptCATAdminCalcHashFromFileHandle(hFile, &cbCatHash, NULL, 0)) { if(!(pbCatHash = (BYTE *)malloc(cbCatHash))) HandleError("Memory allocation failed.\n"); if(!CryptCATAdminCalcHashFromFileHandle(hFile, &cbCatHash, pbCatHash, 0)) HandleError("Failed to get cat hash\n"); } CloseHandle(hFile); if( (pbBuffer = ReadFileBlob(szSource, &dwBufferLen)) == NULL) { HandleError("Couldn't read file. "); } else { //printf("\nRead file into buffer: %d bytes.\n", dwBufferLen); printf("File to be hashed: %s\n", szSource); printf("\nSHA1 hash for file '%s' (%d bytes) is:\n", szSource, dwBufferLen); } } if(!hashFile) //if we are hashing the string entered .. { printf("String to be hashed: %s\n", szSource) ; //--- Byte buffer for ascii string (excluding string terminal null) ---- pbBuffer= (BYTE *)szSource; dwBufferLen = (DWORD) strlen(szSource); // excluding terminal null printf("\nSHA1 hash for string '%s' (%d bytes, excluding terminal null):\n", szSource, dwBufferLen); DumpHex(dwBufferLen, pbBuffer); printf("\n") ; } CalcDumpHash(dwBufferLen, pbBuffer) ; if(hashFile){ //only hash raw bytes for a file; also display hash for cat file printf("\nCat SHA1 hash for file '%s' (%d bytes) is:\n", szSource, dwBufferLen); DumpHex(cbCatHash, pbCatHash) ; printf("\n") ; DumpB64(cbCatHash, pbCatHash); printf("\n"); if(pbBuffer) free(pbBuffer); if(pbCatHash) free(pbCatHash); } else { //if a string to hash, do UNICODE version too // ---------------------------------------------------------------- // If we had a string to hash, compute hash for UNICODE string --- i = MultiByteToWideChar(0, 0, szSource, -1, NULL, 0) ; if (i == 0) HandleError("MultiByteToWideChar failed\n"); //printf("Required widechars (including terminal null) count: %d\n", i); swzSource = (PWCHAR) calloc(i, sizeof(WCHAR)); i = MultiByteToWideChar(0, 0, szSource, -1, swzSource, i) ; if (i == 0) HandleError("MultiByteToWideChar failed\n"); pbBuffer= (BYTE *)swzSource; dwBufferLen = (DWORD) wcslen(swzSource)*sizeof(WCHAR); // excluding terminal null printf("\nSHA1 hash for UNICODE string '%s' (%d bytes, excluding terminal null):\n", szSource, dwBufferLen); DumpHex(dwBufferLen, pbBuffer); printf("\n") ; CalcDumpHash(dwBufferLen, pbBuffer); } //end else } // end strlen(fgets ... if(szSource) free(szSource); if(swzSource) free(swzSource); Wait("\nPress any key to continue"); } // End of main void CalcDumpHash(DWORD dwBufferLen, BYTE *pbBuffer) { HCRYPTPROV hProv; HCRYPTHASH hHash; BYTE *pbHash; BYTE *pbHashSize; DWORD dwHashLen = sizeof(DWORD); //-------------------------------------------------------------------- // Acquire a cryptographic provider context handle. if(CryptAcquireContext( &hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT )) { //printf("CSP context acquired.\n"); } else { HandleError("Error during CryptAcquireContext."); } // Create the hash object. if(CryptCreateHash( hProv, CALG_SHA1, 0, 0, &hHash)) { // printf("Hash object created. \n"); } else { HandleError("Error during CryptCreateHash."); } //-------------------------------------------------------------------- // Compute the cryptographic hash of the buffer. if(CryptHashData( hHash, pbBuffer, dwBufferLen, 0)) { //printf("The data buffer has been hashed.\n"); } else { HandleError("Error during CryptHashData."); } // ------- Make sure we allocate correct hash-size ----- if(CryptGetHashParam( hHash, HP_HASHSIZE, NULL, &dwHashLen, 0)) { // Do nothing } else { printf("CryptGetHashParam failed to get size.\n"); exit(1); } if(pbHashSize = (BYTE*)malloc(dwHashLen)) { // It worked. Do nothing. } else { printf("Allocation failed.\n"); exit(1); } if(CryptGetHashParam( hHash, HP_HASHSIZE, pbHashSize, &dwHashLen, 0)) { // It worked. Do nothing. } else { printf("CryptGetHashParam failed to get size.\n"); exit(1); } if(CryptGetHashParam( hHash, HP_HASHVAL, NULL, &dwHashLen, 0)) { // It worked. Do nothing. } else { printf("CryptGetHashParam failed to get length.\n"); exit(1); } if(pbHash = (BYTE*)malloc(dwHashLen)) { // It worked. Do nothing. } else { printf("Allocation failed.\n"); exit(1); } if(CryptGetHashParam( hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) { // Print the hash value in hex and then B64 DumpHex(dwHashLen, pbHash); printf("\n"); DumpB64(dwHashLen, pbHash); } else { printf("Error during reading hash value.\n"); exit(1); } if(hHash) CryptDestroyHash(hHash); if(pbHash) free(pbHash); if(pbHashSize) free(pbHashSize); // Release the provider handle. if(hProv) CryptReleaseContext(hProv, 0); } //-------------------------------------------------------------------- // This example uses the function HandleError, a simple error // handling function, to print an error message to the standard error // (stderr) file and exit the program. // For most applications, replace this function with one // that does more extensive error reporting. void HandleError(char *s) { DWORD dw = GetLastError(); CHAR szBuf[128]; LPVOID lpMsgBuf; FormatMessage( // get the error message text FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. // ... sprintf_s(szBuf, 128, "%s\n%xh: %s\n", s, dw, lpMsgBuf); //build info string // Free the buffer. LocalFree( lpMsgBuf ); fprintf(stderr,"%s\n",szBuf); exit(1); } // End of HandleError BYTE *ReadFileBlob(LPCSTR fname, DWORD *cbBlob) { FILE *hInputFile; BYTE *pbBlob; DWORD dwFSize; long save; errno_t err; if( (err = fopen_s( &hInputFile, fname, "rb" )) !=0 ) HandleError("Input file was not opened.\n"); save = ftell(hInputFile); fseek(hInputFile, 0, SEEK_END); dwFSize = ftell(hInputFile); fseek(hInputFile, save, SEEK_SET); if(!(pbBlob = (BYTE *) malloc(dwFSize))) { HandleError("Memory allocation failed."); } *cbBlob = (DWORD)fread(pbBlob, sizeof(BYTE), dwFSize, hInputFile); if(ferror(hInputFile)) { HandleError("The bytes of the BLOB were not read.\n"); } fclose(hInputFile); return pbBlob; } // End of ReadBlob void DumpB64(DWORD bytes, BYTE *data){ DWORD dwB64len = sizeof(DWORD); PCHAR szB64str; if(CryptBinaryToString(data, bytes, CRYPT_STRING_BASE64, NULL, &dwB64len)) { //printf("Need %d characters for b64 string", dwB64len); } else { printf("Couldn't b64 decode.\n"); return; } szB64str=(char *)malloc(dwB64len) ; if(CryptBinaryToStringA(data, bytes, CRYPT_STRING_BASE64, szB64str, &dwB64len)) { //printf("Got %d characters in b64 string:\n%s\n", dwB64len, szB64str); printf("B64: %s\n", szB64str); } else { printf("Couldn't b64 decode.\n"); } if(szB64str) free(szB64str); } void DumpHex(DWORD bytes, BYTE *data) { DWORD count; printf("Hex: "); for(count = 0 ; count