我想使用CryptVerifySignature实现数字签名应用。我已经编写了这段代码(在MSDN示例的帮助下):
#define Check(condition, message) if (!(condition)) { fprintf(stderr, "%s\n", message); goto Exit; };
void DigSign(const char* inputFileName, const char* signFileName)
{
HCRYPTPROV hProv;
BYTE *pbBuffer= NULL;
DWORD dwBufferLen = 0;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
FILE* inputFile = NULL;
Check((inputFile = fopen(inputFileName, "r")) != NULL, "File does not exists");
dwBufferLen = GetFileSize(inputFile);
Check(pbBuffer = (BYTE*)malloc(dwBufferLen + 1), "cannot allocate memory");
fread(pbBuffer, 1, dwBufferLen, inputFile);
pbBuffer[dwBufferLen] = '\0';
fclose(inputFile);
//-------------------------------------------------------------------
// Acquire a cryptographic provider context handle.
Check(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0), "Error during CryptAcquireContext.");
if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
if(NTE_NO_KEY == GetLastError())
{
Check(CryptGenKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey), "Could not create a user public key.\n");
}
else
{
goto Exit;
}
}
Check(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwBlobLen), "Error computing BLOB length.");
Check(pbKeyBlob = (BYTE*)malloc(dwBlobLen), "Out of memory. \n");
Check(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen), "Error during CryptExportKey.");
//-------------------------------------------------------------------
// Create the hash object.
Check(CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash), "Error during CryptCreateHash.");
//-------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.
Check(CryptHashData(hHash, pbBuffer, dwBufferLen, 0), "Error during CryptHashData.");
//-------------------------------------------------------------------
// Determine the size of the signature and allocate memory.
dwSigLen= 0;
Check(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen), "Error during CryptSignHash.");
//-------------------------------------------------------------------
// Allocate memory for the signature buffer.
Check(pbSignature = (BYTE *)malloc(dwSigLen), "Out of memory.");
//-------------------------------------------------------------------
// Sign the hash object.
Check(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen), "Error during CryptSignHash.");
FILE* f = fopen(signFileName, "w");
fwrite(pbSignature, dwSigLen, 1, f);
printf("W: %.128s\n", pbSignature);
fwrite(pbKeyBlob, dwBlobLen, 1, f);
printf("W: %.148s\n", pbKeyBlob);
fclose(f);
//-------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
free(pbSignature);
free(pbKeyBlob);
if(hProv)
CryptReleaseContext(hProv, 0);
Exit:;
}
bool CheckDigSign(const char* inputFileName, const char* signFileName, const char* userName)
{
bool result = false;
HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
FILE* inputFile = NULL;
Check((inputFile = fopen(inputFileName, "r")) != NULL, "File does not exists");
dwBufferLen = GetFileSize(inputFile);
Check(pbBuffer = (BYTE*)malloc(dwBufferLen + 1), "cannot allocate memory");
fread(pbBuffer, 1, dwBufferLen, inputFile);
pbBuffer[dwBufferLen] = '\0';
fclose(inputFile);
FILE* signFile = NULL;
Check((signFile = fopen(signFileName, "r")) != NULL, "File does not exists");
DWORD dwSignFileLen = GetFileSize(signFile);
dwSigLen = 128;
pbSignature = (BYTE*)malloc(dwSigLen);
dwBlobLen = dwSignFileLen - dwSigLen;
pbKeyBlob = (BYTE*)malloc(dwBlobLen);
fread(pbSignature, 1, dwSigLen, signFile);
fread(pbKeyBlob, 1, dwBlobLen, signFile);
fclose(signFile);
printf("R: %.128s\n", pbSignature);
printf("R: %.148s\n", pbKeyBlob);
Check(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0), "Error during CryptAcquireContext.");
Check(CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey), "Public key import failed.");
//-------------------------------------------------------------------
// Create a new hash object.
Check(CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash), "Error during CryptCreateHash.");
//-------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.
Check(CryptHashData(hHash, pbBuffer, dwBufferLen, 0), "Error during CryptHashData.");
//-------------------------------------------------------------------
// Validate the digital signature.
result = CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, NULL, 0);
printf("%u %x", GetLastError(), GetLastError());
//-------------------------------------------------------------------
// Free memory to be used to store signature.
if(pbSignature)
free(pbSignature);
//-------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
//-------------------------------------------------------------------
// Release the provider handle.
if(hProv)
CryptReleaseContext(hProv, 0);
Exit:
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
DigSign("test3.txt", "test.sig");
printf("TEST: %u\n", CheckDigSign("test3.txt", "test.sig", ""));
}
DigSign功能必须签署文件内容并将签名和公钥写入另一个文件。如果符号正确,CheckSign必须返回true。但我不明白为什么我的代码不起作用。 _tmain中的CheckDigSign必须返回true,但返回false。有人可以帮我吗?
答案 0 :(得分:4)
我拿了你的整个代码示例,将其破解了一点,并对所有文件I / O使用了CreateFile,ReadFile和WriteFile。有用。对源文件检查附加公钥的签名文件就好了。
因此我怀疑这是读取/写入文件的方法,特别是“w”和“r”与“wb”和“rb”之间的字节。尝试改变它们,看看你想出了什么。
作为参考,修改后的代码如下,并且我所做的更改没有错误检查,所以不要将它用于任何特殊的东西,因为它实际上比它打印的纸张价值低(即没有)。
#define Check(condition, message) if (!(condition)) { fprintf(stderr, "%s\n", message); goto Exit; };
void DigSign(const char* inputFileName, const char* signFileName)
{
HCRYPTPROV hProv;
BYTE *pbBuffer= NULL;
DWORD dwBufferLen = 0;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
FILE* inputFile = NULL;
HANDLE hFileInput = CreateFile(inputFileName, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
dwBufferLen = GetFileSize(hFileInput, NULL);
Check(pbBuffer = (BYTE*)malloc(dwBufferLen + 1), "cannot allocate memory");
DWORD dwBytesRead = 0L;
ReadFile(hFileInput, pbBuffer, dwBufferLen, &dwBytesRead, NULL);
pbBuffer[dwBufferLen] = 0;
CloseHandle(hFileInput);
//-------------------------------------------------------------------
// Acquire a cryptographic provider context handle.
Check(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0), "Error during CryptAcquireContext.");
if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
if(NTE_NO_KEY == GetLastError())
{
Check(CryptGenKey(hProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey), "Could not create a user public key.\n");
}
else
{
goto Exit;
}
}
Check(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwBlobLen), "Error computing BLOB length.");
Check(pbKeyBlob = (BYTE*)malloc(dwBlobLen), "Out of memory. \n");
Check(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen), "Error during CryptExportKey.");
//-------------------------------------------------------------------
// Create the hash object.
Check(CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash), "Error during CryptCreateHash.");
//-------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.
Check(CryptHashData(hHash, pbBuffer, dwBufferLen, 0), "Error during CryptHashData.");
//-------------------------------------------------------------------
// Determine the size of the signature and allocate memory.
dwSigLen= 0;
Check(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen), "Error during CryptSignHash.");
//-------------------------------------------------------------------
// Allocate memory for the signature buffer.
Check(pbSignature = (BYTE *)malloc(dwSigLen), "Out of memory.");
//-------------------------------------------------------------------
// Sign the hash object.
Check(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen), "Error during CryptSignHash.");
HANDLE hFileSign = CreateFile(signFileName, // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
DWORD dwBytesWritten = 0;
WriteFile(hFileSign, pbSignature, dwSigLen, &dwBytesWritten, NULL);
WriteFile(hFileSign, pbKeyBlob, dwBlobLen, &dwBytesWritten, NULL);
CloseHandle(hFileSign);
printf("W: %.128s\n", pbSignature);
printf("W: %.148s\n", pbKeyBlob);
//-------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
free(pbSignature);
free(pbKeyBlob);
if(hProv)
CryptReleaseContext(hProv, 0);
Exit:;
}
bool CheckDigSign(const char* inputFileName, const char* signFileName, const char* userName)
{
BOOL result = false;
HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
HCRYPTHASH hHash;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
HANDLE hFileInput = CreateFile(inputFileName, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
dwBufferLen = GetFileSize(hFileInput, NULL);
Check(pbBuffer = (BYTE*)malloc(dwBufferLen + 1), "cannot allocate memory");
DWORD dwBytesRead = 0;
ReadFile(hFileInput, pbBuffer, dwBufferLen, &dwBytesRead, NULL);
pbBuffer[dwBufferLen] = 0;
CloseHandle(hFileInput);
HANDLE hFileSig = CreateFile(signFileName, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
DWORD dwSignFileLen = GetFileSize(hFileSig, NULL);
dwSigLen = 128;
pbSignature = (BYTE*)malloc(dwSigLen);
dwBlobLen = dwSignFileLen - dwSigLen;
pbKeyBlob = (BYTE*)malloc(dwBlobLen);
ReadFile(hFileSig, pbSignature, dwSigLen, &dwBytesRead, NULL);
ReadFile(hFileSig, pbKeyBlob, dwBlobLen, &dwBytesRead, NULL);
CloseHandle(hFileSig);
printf("R: %.128s\n", pbSignature);
printf("R: %.148s\n", pbKeyBlob);
Check(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0), "Error during CryptAcquireContext.");
Check(CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey), "Public key import failed.");
//-------------------------------------------------------------------
// Create a new hash object.
Check(CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash), "Error during CryptCreateHash.");
//-------------------------------------------------------------------
// Compute the cryptographic hash of the buffer.
Check(CryptHashData(hHash, pbBuffer, dwBufferLen, 0), "Error during CryptHashData.");
//-------------------------------------------------------------------
// Validate the digital signature.
result = CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, NULL, 0);
printf("%u %x", GetLastError(), GetLastError());
//-------------------------------------------------------------------
// Free memory to be used to store signature.
if(pbSignature)
free(pbSignature);
//-------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
//-------------------------------------------------------------------
// Release the provider handle.
if(hProv)
CryptReleaseContext(hProv, 0);
Exit:
return !!result;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc == 3)
{
DigSign(argv[1], argv[2]);
printf("TEST: %u\n", CheckDigSign(argv[1], argv[2],""));
return 0;
}
return 1;
}