https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata
How can I save the output key to the windows registry or a file? I've been trying to do this for two days now but no progress. One of the problems is that I am using Unreal Engine and they have their own string type "FString" which does not easily convert to std::string or const char*
This is the code I'm using to save to the registry, but I'm not sure if it's valid:
void SUGH1LoginWidget::SecureSaveJWTToken(FString JWT_Token)
{
#ifdef _WIN32
DATA_BLOB DataIn;
DATA_BLOB DataOut; // Key to decrypt the data. Store in windows registry.
DATA_BLOB EncryptionKey; // Uses define in ShooterGame.h to encrypt the data so that only the UGH1 application can access the token.
DWORD cbDataInput = lstrlenA((char*)TCHAR_TO_ANSI(*JWT_Token)) + 1;
DataIn.pbData = (BYTE*)ConvertFStringToCString(JWT_Token).get();
DataIn.cbData = cbDataInput;
BYTE* pbDataEncryptionKey = (BYTE*)TOKEN_ENCRYPTION_KEY;
DWORD cbDataEncryptionKey = strlen((char*)pbDataEncryptionKey) + 1;
EncryptionKey.pbData = pbDataEncryptionKey;
EncryptionKey.cbData = cbDataEncryptionKey;
// Finally save the data
CryptProtectData(&DataIn, NULL, &EncryptionKey, NULL, NULL, NULL, &DataOut);
SaveJWTDecryptionKeyToRegistry(DataOut);
#endif
}
void SUGH1LoginWidget::SaveJWTDecryptionKeyToRegistry(DATA_BLOB DecryptionKey)
{
FString Base64EncryptionKey = FBase64::Encode(DecryptionKey.pbData, DecryptionKey.cbData);
HKEY CurrentUserKey;
LSTATUS Error;
Error = RegOpenCurrentUser(KEY_ALL_ACCESS, &CurrentUserKey);
if (Error == ERROR_SUCCESS)
{
HKEY SoftwareKey;
Error = RegOpenKeyExA(CurrentUserKey, "SOFTWARE", NULL, KEY_WRITE, &SoftwareKey);
if (Error == ERROR_SUCCESS)
{
HKEY UGHStudiosSubKey;
Error = RegCreateKeyExA(SoftwareKey, "UGH Studios LLC", NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &UGHStudiosSubKey, NULL);
if (Error == ERROR_SUCCESS)
{
Error = RegSetValueExA(UGHStudiosSubKey, "LoginTokenDecryptionKey", NULL, REG_SZ, (BYTE*)TCHAR_TO_ANSI(*Base64EncryptionKey), Base64EncryptionKey.Len());
RegCloseKey(UGHStudiosSubKey);
RegCloseKey(SoftwareKey);
if (Error != ERROR_SUCCESS)
{
UE_LOG(LogLoginWidget, Error, TEXT("The game was unable to save the login token to the registry."));
}
}
}
}
else
{
UE_LOG(LogLoginWidget, Error, TEXT("The game was unable to access the windows registry on this machine. "));
}
RegCloseKey(CurrentUserKey);
}
This is my code for loading from the registry back into an FString but it's not working properly:
std::shared_ptr<char[]> SUGH1LoginWidget::ConvertFStringToCString(const FString InputString)
{
std::shared_ptr<char[]> ptr(new char[InputString.Len()]);
TArray<TCHAR> CharArray = InputString.GetCharArray();
for (int i = 0; i < InputString.Len(); i++)
{
ptr[i] = CharArray[i];
}
return ptr;
}
PRAGMA_DISABLE_OPTIMIZATION
FReply SUGH1LoginWidget::GetJWTTokenFromRegistry()
{
TArray<uint8> DecryptionKeyBytes;
// load base64 string from registry
LSTATUS Error;
HKEY UGHStudiosSubKey;
Error = RegOpenKeyExA(HKEY_CURRENT_USER, "SOFTWARE\\UGH Studios LLC", NULL, KEY_READ, &UGHStudiosSubKey);
if (Error == ERROR_SUCCESS)
{
char buffer[8193] = { 0 };
DWORD dwLen = 8192;
DWORD dwType = 0;
Error = RegQueryValueExA(UGHStudiosSubKey, "LoginTokenDecryptionKey", 0, &dwType, (BYTE*)buffer, &dwLen);
if (Error == ERROR_SUCCESS)
{
std::string outValue = buffer;
FString decoded_string;
//FString reg_value_as_fstring = FString(outValue.length(), outValue.c_str());
uint8* decoded = malloc();
FBase64::Decode(outValue.c_str(), outValue.size(), decoded);
//:Decode(const FString & Source, TArray<uint8>&OutDest
//::Decode(const CharType* Source, uint32 Length, uint8* Dest)
//UE_LOG(LogLoginWidget, Error, TEXT("Out value: %s"), *decoded_string);
}
//Error = RegQueryValueExA(UGHStudiosSubKey, "LoginTokenDecryptionKey", NULL, NULL, buffer, size);
return FReply::Handled();
//return decoded_string;
//std::string outvalue = (char*)buffer;
}
//FBase64::Decode(, DecryptionKeyBytes)
//return FString("");
return FReply::Handled();
}
PRAGMA_ENABLE_OPTIMIZATION
What's the standard way of saving the struct data? I was tying to Base64 encrypt it and save it as a registry key. But this doesn't work.
I am trying to decrypt data from openssl generated private key. I have converted the public key from PEM to DER format, but when i use CryptDecrypt it throws error key does not exist. I have previously used the same method to encrypt data and decrypt using openssl, i am also aware regarding the Endianess difference in openssl and wincrypto. Here is the code if someone can point out where i am going wrong.
#include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
#pragma comment(lib, "Crypt32.lib")
char default_pub_key[] =
"-----BEGIN PUBLIC KEY-----"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVTOXB/Ti8SFvP42Z1XFB6GQ+R"
"jnqs42XiTFRXWpsSTlSPMRHi8aXpf1KYzzKHMC+4hU3rrgdbOu8bl7FekDoy38No"
"PX8ACoEmRhdn8mXs+ftmIRCuEE44mtgWUme65A1nTyT8nRmAVF6roo/rry+Xkbe9"
"iC6vRBRbVzprmCv7jwIDAQAB"
"-----END PUBLIC KEY-----";
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwKeySize = 0;
void SwapBytes(char* pv, size_t n) {
char* p = pv;
size_t lo, hi;
for (lo = 0, hi = n - 1; hi > lo; lo++, hi--)
{
char tmp = p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
int init_crypto()
{
LPBYTE pbBuffer;
DWORD dwKeyBlob, dw_pub_key_len = 0;
unsigned int offset = 22; // 22 = 1024, 24 = 2048 and so on
DWORD dwParamSize = sizeof(DWORD);
CERT_PUBLIC_KEY_INFO* publicKeyInfo;
CryptStringToBinaryA(default_pub_key, 0, CRYPT_STRING_ANY, NULL, &dw_pub_key_len, NULL, NULL);
pbBuffer = (LPBYTE)GlobalAlloc(GPTR, dw_pub_key_len);
CryptStringToBinaryA(default_pub_key, 0, CRYPT_STRING_ANY, pbBuffer, &dw_pub_key_len, NULL, NULL);
dwKeyBlob = 0;
CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbBuffer, dw_pub_key_len, 0, NULL, NULL, &dwKeyBlob);
publicKeyInfo = (CERT_PUBLIC_KEY_INFO*)GlobalAlloc(GPTR, dwKeyBlob);
CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbBuffer, dw_pub_key_len, 0, NULL, publicKeyInfo, &dwKeyBlob);
CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey);
CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeySize, &dwParamSize, 0);
char da[16];
memset(da, 0, sizeof(da));
wsprintfA(da, "%d", dwKeySize);
MessageBoxA(NULL, da, NULL, MB_OK);
dwKeySize /= 8;
return 0;
}
int main(int argc, char** argv)
{
// start rsa crypto key
init_crypto();
// Read encrypted data
DWORD junk;
HANDLE hEncFile = CreateFile(L"test_enc.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD EncFileSize = GetFileSize(hEncFile, 0);
char* EncFileBuf = (char*)GlobalAlloc(GPTR, EncFileSize + 1);
ReadFile(hEncFile, EncFileBuf, EncFileSize, &junk, NULL);
CloseHandle(hEncFile);
// convert for win32
SwapBytes((char*)EncFileBuf, EncFileSize);
CryptDecrypt(hKey, 0, TRUE, 0,(PBYTE)EncFileBuf, &EncFileSize);
hEncFile = CreateFile(L"test_dec.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hEncFile, EncFileBuf, EncFileSize, &junk, NULL);
CloseHandle(hEncFile);
GlobalFree(EncFileBuf);
// Do proper cleanup
return 0;
}
CryptDecrypt
[in] hKey
A handle to the key to use for the decryption. An application obtains this handle by using either the CryptGenKey or CryptImportKey function.
You pass a wrong hKey to CryptDecrypt. Use CryptImportKey after CryptImportPublicKeyInfo for getting an expected hKey and pass it to CryptDecrypt.
I am writing a program to send data to an HID device. I followed the following page from Microsoft's documentation: Finding and Opening a HID Collection and I get the file handle successfully, but when I try to write using WriteFile, I get an INVALID_FUNCTION error (1). I have sent the same data to the device through a Hyperterminal and it worked, so I'm sure that the information I am sending is correct.
Here is my code:
HANDLE m_hCommPort;
GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
HDEVINFO hinfo;
DWORD index = 0;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
SP_DEVINFO_DATA deviceInfoData;
BOOL result;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
DWORD requiredSize;
DWORD deviceIndex = 0;
hinfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
result = SetupDiEnumDeviceInterfaces(hinfo, NULL, &guid, deviceIndex, &deviceInterfaceData);
while (result == TRUE) {
deviceInfoData.cbSize = sizeof(deviceInfoData);
SetupDiGetDeviceInterfaceDetail(hinfo, &deviceInterfaceData, NULL, 0, &requiredSize, &deviceInfoData);
deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(hinfo, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, &deviceInfoData);
Trace(TEXT(deviceInterfaceDetailData->DevicePath));
if (_tcsstr(deviceInterfaceDetailData->DevicePath, "vid_0c2e&pid_0be7")) {
Trace(TEXT(deviceInterfaceDetailData->DevicePath));
break;
}
result = SetupDiEnumDeviceInterfaces(hinfo, NULL, &guid, ++deviceIndex, &deviceInterfaceData);
}
if (result == FALSE) {
ErrorExit("SetupDiEnumDeviceInterfaces ");
}
else if(deviceInterfaceDetailData != NULL){
m_hCommPort = CreateFile(deviceInterfaceDetailData->DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (m_hCommPort == INVALID_HANDLE_VALUE) {
ErrorExit("CreateFile");
}
else {
DWORD bytesWritten;
char scanCommand[] = { 22,77,13,'I','M','G','S','N','P','1','B' };
DWORD size = sizeof(scanCommand);
BOOL fileWritten = WriteFile(m_hCommPort, scanCommand, size, &bytesWritten, NULL);
if (fileWritten == TRUE) {
Trace(TEXT("Wrote %d files to device"), bytesWritten);
}
else {
ErrorExit("Error writing to file");
}
}
}
Can someone help me to understand why I am getting this error please?
I want to implement digital signature app using CryptVerifySignature. I've written this code(with help of MSDN example):
#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 function must sign content of file and write signature and public key to another file. CheckSign must return true if sign is right. But I don't understand why my code doesn't work. CheckDigSign in _tmain must return true, but it returns false. Can anybody help me pls?
I took your entire code sample, hacked it up a little, and used CreateFile, ReadFile, and WriteFile for all the file I/O. It works. The signature file with the appended public key checked against the source file just fine.
I therefore suspect it is the method of reading/writing your files, and specifically, the "w" and "r" vs. "wb" and "rb" that is horking over your bytes. Try changing those and see what you come up with.
For reference, the modified code is below, and there is NO error checking in the changes I made, so DON'T use this for anything special as it is literally worth less than the paper its printed on (i.e. nothing).
#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;
}
I have this function which gives the full file name(path) from the file handle. The only problem is CreateFileMapping fails for directory handles. Is there a workaround for it?
I get the handle using NtCreateFile()
ULONG status = NtCreatefile(&f, GENERIC_ALL, &oa, iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_OPEN_BY_FILE_ID , NULL, 0);
printf("status: %X, handle: %x\n", status, f);
AND
BOOL CHouseKeeper::GetFileNameFromHandle(HANDLE hFile)
{
BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH+1];
HANDLE hFileMap;
// Get the file size.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);
if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
{
_tprintf(TEXT("Cannot map a file with a length of zero.\n"));
return FALSE;
}
// Create a file mapping object.
//It fails here if a directory handle is passed, it returns 0
hFileMap = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0,
1,
NULL);
if (hFileMap)
{
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
if (GetMappedFileName (GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
{
// Translate path with device name to drive letters.
TCHAR szTemp[BUFSIZE];
szTemp[0] = '\0';
if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
BOOL bFound = FALSE;
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
size_t uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0
&& *(pszFilename + uNameLen) == _T('\\');
if (bFound)
{
// Reconstruct pszFilename using szTempFile
// Replace device path with DOS path
TCHAR szTempFile[MAX_PATH];
StringCchPrintf(szTempFile,
MAX_PATH,
TEXT("%s%s"),
szDrive,
pszFilename+uNameLen);
StringCchCopyN(pszFilename, MAX_PATH+1, szTempFile, _tcslen(szTempFile));
}
}
}
// Go to the next NULL character.
while (*p++);
} while (!bFound && *p); // end of string
}
}
bSuccess = TRUE;
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}else {
wcout<<GetLastError()<<endl;
}
_tprintf(TEXT("File name is %s\n"), pszFilename);
return(bSuccess);
}
You can use NtQueryInformationFile with FileNameInformation to retrieve the name associated with a file handle.