- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个从文件生成散列键的程序。例如,程序的结果是 "hash of file c:\Users\Jax\Desktop\files\file.txt is: 4db5a10d2ea73e3f76"
。
我有一个变量,它具有此 file.txt 的预期哈希值:
char hashExpected = "4db5a10d2ea73e3f76";
在代码的特定部分,我正在验证程序的结果哈希值是否等于存储在 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");
}
完整程序:
#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[] = "0123456789abcdef";
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;
}
最佳答案
char hashExpected[] = "4db5a10d2ea73e3f76";
上面的MD5值是错误的。 MD5 值的长度为 16 个字节。但这只是字节数。我们不能在屏幕上打印字节,因此我们经常将字节转换为十六进制值。例如,如果我们有 unsinged char bytes[3] = {0x01,0x01,0xFF}
,我们将字节转换为十六进制字符串,它变成 "0102FF"
。
请注意,字符串表示形式加了一个空终止符两倍长。 MD5 散列的例子是:
"C4CA4238A0B923820DCC509A6F75849B"
字符串的缓冲区大小应为 33
(16 x 2 + 1)
要找到正确的 hashExpected
,请搜索 “在线 MD5 计算器”。您可以使用http://onlinemd5.com/之类的网站来计算文件的MD5。
或者使用内容为1
的文件。 MD5("1")
是 "C4CA4238A0B923820DCC509A6F75849B"
,将其用作预期的哈希值。
char hashResult[] = "";
上面一行是一个编程错误,正如@melpomene 在评论中提到的
hashResult[i] = rgbDigits[rgbHash[i] >> 4];
hashResult[i] += rgbDigits[rgbHash[i] & 0xf];
上面的代码是错误的,你需要这个:
char hashResult[MD5LEN * 2 + 1] = "";
...
hashResult[i * 2] = rgbDigits[rgbHash[i] >> 4];
hashResult[i * 2 + 1] = rgbDigits[rgbHash[i] & 0xf];
verify
函数也存在问题,因为它比较错误的字节表示形式的 MD5 和错误的字符串表示形式的 MD5。
您可以使用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[] = "0123456789abcdef";
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;
}
关于c - hashResult 变量没有存储正确的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40963069/
我有一个从文件生成散列键的程序。例如,程序的结果是 "hash of file c:\Users\Jax\Desktop\files\file.txt is: 4db5a10d2ea73e3f76"。
我是一名优秀的程序员,十分优秀!