CryptDecrypt fails with NT_BAD_DATA (0x80090005) - c

The following code by Alejandro Magencio generate key pairs, encrypts and decrypts files with the Microsoft CryptoAPI works well, but only for files smaller than the key:
http://blogs.msdn.com/b/alejacma/archive/2008/01/28/how-to-generate-key-pairs-encrypt-and-decrypt-data-with-cryptoapi.aspx
I am trying to extend this code in order to encrypt and decrypt larger files.
Here is the complete listing as far as I got. It encrypts but on the second time in the decrypt loop I get a bad data error.
Any help will be greatly appreciated and I promise to post the full working code.
Thanks in advance!
/*
EncryptDecrypt.c
This program was compiled on Windows 7 64-bit with Visual Studio 2013 Desktop Express. To run:
EncryptDecrypt.exe k C:\temp\myprivate.key C:\temp\mypublic.key
EncryptDecrypt.exe e C:\temp\myprivate.key C:\temp\todo.txt C:\temp\done.txt
EncryptDecrypt.exe d C:\temp\mypublic.key C:\temp\done.txt C:\temp\redone.txt
*/
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "wincrypt.h"
#include "tchar.h"
#define ENCRYPTEDLENGTH (128)
#define MAXSIZE (128 - 11) // size of chunk we can use for this program
// FUNCTIONS
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile);
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile);
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile);
// Main
int _tmain(int argc, _TCHAR* argv[])
{
int iResult = 0;
if ((argc == 4) && (_tcscmp(argv[1], _T("k")) == 0))
{
// Generate a new key pair
iResult = Keys(argv[2], argv[3]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("e")) == 0))
{
// Encrypt
iResult = Encrypt(argv[2], argv[3], argv[4]);
}
else if ((argc == 5) && (_tcscmp(argv[1], _T("d")) == 0))
{
// Decrypt
iResult = Decrypt(argv[2], argv[3], argv[4]);
}
else
{
// Show usage
_tprintf(_T("Usage:\n"));
_tprintf(_T(" - New key pair: EncryptDecrypt k public_key_file private_key_file\n"));
_tprintf(_T(" - Encrypt: EncryptDecrypt e public_key_file plain_file encrypted_file\n"));
_tprintf(_T(" - Decrypt: EncryptDecrypt d private_key_file encrypted_file plain_file\n"));
iResult = 1;
}
_tprintf(_T("\n<< Press any key to continue >>\n"));
_getch();
return iResult;
}
// End of Main
// Keys
int Keys(_TCHAR* strPublicKeyFile, _TCHAR* strPrivateKeyFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPublicKey = NULL;
BYTE* pbPrivateKey = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hPrivateKeyFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("(ref 12) CryptAcquireContext error 0x%x\n"), GetLastError());
// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("(ref 13) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}
// Generate new key pair
_tprintf(_T("CryptGenKey...\n"));
if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hKey))
{
// Error
_tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
return 1;
}
// Get public key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("(ref 29) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Get public key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Get private key size
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("(ref 30) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Get private key
_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen))
{
// Error
_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the public key
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 21) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPublicKeyFile,
(LPCVOID)pbPublicKey,
dwPublicKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 51) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the private key
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 22) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the private key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPrivateKeyFile,
(LPCVOID)pbPrivateKey,
dwPrivateKeyLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 52) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Keys
// Encrypt
int Encrypt(_TCHAR* strPublicKeyFile, _TCHAR* strPlainFile, _TCHAR* strEncryptedFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwDataLen = 0;
DWORD dwEncryptedLen = 0;
DWORD myloopcount = 0;
DWORD mymodulus = 0;
DWORD i = 0;
DWORD myencryptedlength = 0;
DWORD mymaxsize = MAXSIZE;
BYTE* pbPublicKey = NULL;
BYTE* pbData = NULL;
BYTE* pbEncData = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
// Error
_tprintf(_T("(ref 9) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
// Open public key file
_tprintf(_T("CreateFile...\n"));
if ((hPublicKeyFile = CreateFile(
strPublicKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 14) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPublicKeyLen = GetFileSize(hPublicKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 43) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the public key
_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
// Error
_tprintf(_T("(ref 22) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read public key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPublicKeyFile, pbPublicKey, dwPublicKeyLen, &dwPublicKeyLen, NULL))
{
// Error
_tprintf(_T("(ref 31) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Import public key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPublicKey, dwPublicKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("(ref 38) CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}
// Open plain text file
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 15) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hPlainFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 40) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
_tprintf(_T("my data length is %d\n"), dwDataLen);
_tprintf(_T("my max size is %d\n"), MAXSIZE);
// Get length for encrypted data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, NULL, &dwEncryptedLen, 0))
{
// Error
_tprintf(_T("(ref 1) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
if (dwDataLen < MAXSIZE)
{
// as before... Just one run through.
// BEGIN OLD BLOCK
// Create a buffer for the plain text
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("(ref 23) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read plain text
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("(ref 32) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Next line: dwEncryptedLen is the length of key! Ergo, when decrypting
// use 128 instead of MAXSIZE:
_tprintf(_T("My encrypted length is %d\n"), dwEncryptedLen);
// Create a buffer for encrypted data
_tprintf(_T("realloc...\n"));
if (!(pbData = (BYTE *)realloc(pbData, dwEncryptedLen)))
{
// Error
_tprintf(_T("(ref 24) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 2) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the encrypted data
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS, // will truncate if already existing
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 16) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the public key to the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 47) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
// END OLD BLOCK
return 0;
}
else
{
// File is bigger than key.
// Figure out how many times we will need to loop.
myloopcount = (DWORD)(dwDataLen / MAXSIZE);
_tprintf(_T("Loop counter is %d\n"), myloopcount);
mymodulus = dwDataLen % MAXSIZE;
_tprintf(_T("Remainder is %d\n"), mymodulus);
if (mymodulus == 0) // no remainder
{
myloopcount -= 1; // decrement by one
}
// Create a file to save the encrypted data with append flag.
// The parameter for appending data to a file is FILE_APPEND_DATA in the CreateFile function.
// Ref: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363778(v=vs.85).aspx
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile, // if you hardcode a filename here, use syntax: _T("C:\\temp\\append.txt"),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_APPEND_DATA,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 17) CreateFile error saving the encrypted data 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the plain text
_tprintf(_T("malloc...\n"));
pbData = NULL;
if (!(pbData = (BYTE *)malloc(MAXSIZE)))
{
// Error
_tprintf(_T("(ref 25) malloc error 0x%x\n"), GetLastError());
return 1;
}
_tprintf(_T("malloc...\n"));
pbEncData = NULL;
if (!(pbEncData = (BYTE *)malloc(ENCRYPTEDLENGTH)))
{
// Error
_tprintf(_T("(ref 53) malloc error 0x%x\n"), GetLastError());
return 1;
}
for (i = 0; i < myloopcount; i++)
{
// ref https://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx
if (i > 0)
{
SetFilePointer(
hPlainFile, // HANDLE hFile,
MAXSIZE, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
}
mymaxsize = MAXSIZE;
// Read plain text
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymaxsize, &mymaxsize, NULL))
{
// Error
_tprintf(_T("(ref 33) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, FALSE, 0, pbEncData, &mymaxsize, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 4) CryptEncrypt error in loop number %i 0x%x\n"),i, GetLastError());
return 1;
}
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbEncData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 48) WriteFile error, i is %d 0x%x\n"), i, GetLastError());
return 1;
}
} // end for loop
SetFilePointer(
hPlainFile, // HANDLE hFile,
MAXSIZE, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
mymaxsize = MAXSIZE;
if (mymodulus == 0)
{
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymaxsize, &mymaxsize, NULL))
{
// Error
_tprintf(_T("(ref 34) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data; last chunk must have TRUE flag when encrypting.
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbEncData, &dwDataLen, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 6) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
}
else
{
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPlainFile, pbData, mymodulus, &mymodulus, NULL))
{
// Error
_tprintf(_T("(ref 35) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbEncData, &mymodulus, dwEncryptedLen))
{
// Error
_tprintf(_T("(ref 8) CryptEncrypt error 0x%x\n"), GetLastError());
return 1;
}
}
// Finish writing.
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hEncryptedFile,
(LPCVOID)pbEncData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 49) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
return 0;
}
__finally
{
// Clean up
if (!pbPublicKey) {
_tprintf(_T("free...\n"));
free(pbPublicKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPublicKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPublicKeyFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Encrypt
// Decrypt
int Decrypt(_TCHAR* strPrivateKeyFile, _TCHAR* strEncryptedFile, _TCHAR* strPlainFile)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPrivateKeyLen = 0;
DWORD dwDataLen = 0;
DWORD myloopcount = 0;
DWORD mymodulus = 0;
DWORD i = 0;
DWORD mysize = 0;
BYTE* pbPrivateKey = NULL;
BYTE* pbData = NULL;
BYTE* pbEncData = NULL;
HANDLE hPrivateKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
__try
{
// Acquire access to key container
_tprintf(_T("CryptAcquireContext...\n"));
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, 0))
{
// Error
_tprintf(_T("(ref 10) CryptAcquireContext error 0x%x\n"), GetLastError());
// Try to create a new key container
if (!CryptAcquireContext(&hCryptProv, _T("ACMEENCRYPT.EncryptDecrypt"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// Error
_tprintf(_T("(ref 11) CryptAcquireContext error 0x%x\n"), GetLastError());
return 1;
}
}
// Open private key file
_tprintf(_T("CreateFile...\n"));
if ((hPrivateKeyFile = CreateFile(
strPrivateKeyFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 18) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwPrivateKeyLen = GetFileSize(hPrivateKeyFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 41) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the private key
_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
// Error
_tprintf(_T("(ref 27) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read private key
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hPrivateKeyFile, pbPrivateKey, dwPrivateKeyLen, &dwPrivateKeyLen, NULL))
{
// Error
_tprintf(_T("(ref 36) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
// Import private key
_tprintf(_T("CryptImportKey...\n"));
if (!CryptImportKey(hCryptProv, pbPrivateKey, dwPrivateKeyLen, 0, 0, &hKey))
{
// Error
_tprintf(_T("(ref 39) CryptImportKey error 0x%x\n"), GetLastError());
return 1;
}
// Open encrypted file
_tprintf(_T("CreateFile...\n"));
if ((hEncryptedFile = CreateFile(
strEncryptedFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 19) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Get file size
_tprintf(_T("GetFileSize...\n"));
if ((dwDataLen = GetFileSize(hEncryptedFile, NULL)) == INVALID_FILE_SIZE)
{
// Error
_tprintf(_T("(ref 42) GetFileSize error 0x%x\n"), GetLastError());
return 1;
}
if (dwDataLen == ENCRYPTEDLENGTH)
{
// Create a buffer for the encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(dwDataLen)))
{
// Error
_tprintf(_T("(ref 28) malloc error 0x%x\n"), GetLastError());
return 1;
}
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, dwDataLen, &dwDataLen, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &dwDataLen))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error 0x%x\n"), GetLastError());
return 1;
}
// Create a file to save the plain text
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 20) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
else
{
// encrypted file is bigger than 128 bytes
// Figure out how many times we will need to loop.
myloopcount = (DWORD)(dwDataLen / ENCRYPTEDLENGTH);
_tprintf(_T("Loop counter is %d\n"), myloopcount);
mymodulus = dwDataLen % ENCRYPTEDLENGTH;
_tprintf(_T("Remainder is %d\n"), mymodulus);
if (mymodulus == 0) // no remainder
{
myloopcount -= 1; // decrement by one
}
// Create a file to save the plain text
_tprintf(_T("CreateFile...\n"));
if ((hPlainFile = CreateFile(
strPlainFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_APPEND_DATA,
NULL
)) == INVALID_HANDLE_VALUE)
{
// Error
_tprintf(_T("(ref 55) CreateFile error 0x%x\n"), GetLastError());
return 1;
}
// Create a buffer for the encrypted data
_tprintf(_T("malloc...\n"));
if (!(pbData = (BYTE *)malloc(ENCRYPTEDLENGTH)))
{
// Error
_tprintf(_T("(ref 56) malloc error 0x%x\n"), GetLastError());
return 1;
}
for (i = 0; i < myloopcount; i++)
{
// ref https://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx
if (i > 0)
{
SetFilePointer(
hEncryptedFile, // HANDLE hFile,
ENCRYPTEDLENGTH, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT
);
}
mysize = ENCRYPTEDLENGTH;
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, mysize, &mysize, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, FALSE, 0, pbData, &mysize))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error in loop number %d 0x%x\n"),i, GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
} // end for loop
SetFilePointer(
hEncryptedFile, // HANDLE hFile,
ENCRYPTEDLENGTH, // LONG lDistanceToMove,
NULL, // PLONG lpDistanceToMoveHigh,
FILE_CURRENT // DWORD dwMoveMethod, with FILE_CURRENT it's more efficient, not forced
// to do (i * MAXSIZE) for second parameter size
);
mysize = ENCRYPTEDLENGTH;
// Read encrypted data
_tprintf(_T("ReadFile...\n"));
if (!ReadFile(hEncryptedFile, pbData, mysize, &mysize, NULL))
{
// Error
_tprintf(_T("(ref 37) ReadFile error 0x%x\n"), GetLastError());
return 1;
}
if (!CryptDecrypt(hKey, NULL, TRUE, 0, pbData, &mysize))
{
// Error
_tprintf(_T("(ref 54) CryptDecrypt error 0x%x\n"), GetLastError());
return 1;
}
// Write the plain text the file
_tprintf(_T("WriteFile...\n"));
if (!WriteFile(
hPlainFile,
(LPCVOID)pbData,
dwDataLen,
&lpNumberOfBytesWritten,
NULL
))
{
// Error
_tprintf(_T("(ref 50) WriteFile error 0x%x\n"), GetLastError());
return 1;
}
}
return 0;
}
__finally
{
// Clean up
if (!pbPrivateKey) {
_tprintf(_T("free...\n"));
free(pbPrivateKey);
}
if (!pbData) {
_tprintf(_T("free...\n"));
free(pbData);
}
if (hPrivateKeyFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPrivateKeyFile);
}
if (hEncryptedFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hEncryptedFile);
}
if (hPlainFile) {
_tprintf(_T("CloseHandle...\n"));
CloseHandle(hPlainFile);
}
if (hKey) {
_tprintf(_T("CryptDestroyKey...\n"));
CryptDestroyKey(hKey);
}
if (hCryptProv) {
_tprintf(_T("CryptReleaseContext...\n"));
CryptReleaseContext(hCryptProv, 0);
}
}
}
// End of Decrypt

Yes; in general you cannot use RSA to encrypt data larger than the key size in a single pass, the limit is infact slightly shorter than the key size, depending on padding.
To encrypt larger amounts of data you would typically use a hybrid approach whereby you generate a symmetric key (say AES) and use that to encrypt your data.
You can then use your RSA public key to encrypt the AES key, combine it with the ciphertext and you have a blob that requires the private key to decrypt.

Related

strtok_s return incorrect data inside windbg

(Hello Everyone) I have some problem with strtok_s. I wrote this code(x64).
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
BOOL TestMD5(CONST WCHAR* MD5_DATABASE_FILE)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD FileSize = 0;
DWORD dwReaded = 0;
PBYTE pData = NULL;
BOOL bRead = FALSE;
PCHAR token_string = NULL;
PCHAR context = NULL;
CONST PCHAR delimeter = "\r\n";
hFile = CreateFileW(
MD5_DATABASE_FILE,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Can't open md5 database file: ");
return FALSE;
}
FileSize = GetFileSize(hFile, NULL);
if (FileSize == 0 || FileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
return FALSE;
}
pData = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)FileSize);
if (pData == NULL)
{
CloseHandle(hFile);
return FALSE;
}
bRead = ReadFile(hFile, pData, FileSize, &dwReaded, NULL);
if (bRead != TRUE || dwReaded != FileSize)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
token_string = (PCHAR)strtok_s(pData, delimeter, &context);
if (token_string == NULL)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
do {
printf("%s\n", token_string);
} while (token_string = (PCHAR)strtok_s(NULL, delimeter, &context));
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return TRUE;
}
int main(void)
{
WCHAR* MD5_DATABASE_FILE = L"c:\\md5.txt";
TestMD5(MD5_DATABASE_FILE);
}
When I run exe this gives me a incorrect data. Content of md5.txt (DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG + (\r\n)
output:
D:\repos\TestWindbg\x64\Debug>TestWindbg.exe
DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG
áááááááááááááááá
I open exe in windbg and I saw while(token_string) is not NULL after first time. But is must?
WinDbg image : "https://i.ibb.co/60nHk5S/Untitled.png"
What is problem? Thanks for reading
Jeffrey Shao - MSFT :Thank you for reply but this is not solution(but I changed my code PBYTE TO PCHAR). The problem is that strtok_s is a string function for this reason you must add NULL byte after buff. Like HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(SIZE_T)FileSize + 1) #1 for NULL character . HeapAlloc alloc buff size:FileSize and +1 For Null...
Thanks for blabb and Daniel Sęk:
I just change some types of pData and token_string.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
BOOL TestMD5(CONST WCHAR* MD5_DATABASE_FILE)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD FileSize = 0;
DWORD dwReaded = 0;
char* pData = NULL;
BOOL bRead = FALSE;
char* token_string = NULL;
PCHAR context = NULL;
CONST PCHAR delimeter = "\r\n";
hFile = CreateFileW(
MD5_DATABASE_FILE,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"Can't open md5 database file: ");
return FALSE;
}
FileSize = GetFileSize(hFile, NULL);
if (FileSize == 0 || FileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
return FALSE;
}
pData = (char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(SIZE_T)FileSize + 1);
if (pData == NULL)
{
CloseHandle(hFile);
return FALSE;
}
bRead = ReadFile(hFile, pData, FileSize, &dwReaded, NULL);
if (bRead != TRUE || dwReaded != FileSize)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
token_string = strtok_s(pData, delimeter, &context);
if (token_string == NULL)
{
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return FALSE;
}
do {
printf("%s\n", token_string);
} while (token_string = strtok_s(NULL, delimeter, &context));
HeapFree(GetProcessHeap(), 0, pData);
CloseHandle(hFile);
return TRUE;
}
int main(void)
{
WCHAR* MD5_DATABASE_FILE = L"c:\\md5.txt";
TestMD5(MD5_DATABASE_FILE);
}
Output:
DC288E0B39EA16B4E9455F82FF265A67:1213:TestDBG + (\r\n)

Set the correct path to a file

Im trying to compile the code below, it is a code free available and Im trying to understand it. And I was trying to test it but Im getting an issue. I got a message error "Error opening file filename.txt. Error 2".
I think that should be because the file is not located in the appropriated folder. I have the file in the desktop, do you know how to set the path to the file in c as th the desktop?
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
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";
LPCSTR filename = "filename.txt";
// Logic to check usage goes here.
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]);
}
printf("\n");
}
else
{
dwStatus = GetLastError();
printf("CryptGetHashParam failed: %d\n", dwStatus);
}
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
CloseHandle(hFile);
return dwStatus;
}
Or copy the file to where .exe resides.

Openssl EVP encryption/decryption not working

The purpose of the application is to pull the $MFT, ecnrypt it and save it on the disk. The second part of the code is decrypting it and saving it in clear form.
For some reason the decryption process is not working, I get only gibberish and apparently the same 4096 bytes repeat over and over.
I know the code is dirty, I tried to minimize it as much as possible, but if anyone spots any clear problem, please do let me know.
Thanks
char publicKey[]="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
rsa_pkey = createRSA(publicKey,1);
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
printf("EVP_PKEY_assign_RSA: failed.\n");
return 1;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
{
printf("EVP_SealInit: failed.\n");
}
eklen_n = htonl(eklen);
DWORD BytesWritten2;
if(WriteFile(outputMFTfile, &eklen_n, sizeof(eklen_n), &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [EK LEN]\n",BytesWritten2);
}
if(WriteFile(outputMFTfile, ek, eklen, &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [EK]\n",BytesWritten2);
}
if(WriteFile(outputMFTfile, iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), &BytesWritten2, NULL))
{
printf("Written %d bytes to the file header [IV]\n",BytesWritten2);
}
while (ReadFile(hRawDisk, FINAL_MFT_BUFFER, 4096, &bytesRead, NULL))
{
bytesCounter = bytesCounter+(unsigned long long)bytesRead;
if (bytesCounter<final_length)
{
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, FINAL_MFT_BUFFER, bytesRead))
{
printf("FAILED SEAL UPDATE \n");
}
WriteFile(outputMFTfile, buffer_out, len_out, &BytesWritten, NULL);
}
else
{
break;
}
}
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
{
printf("FINAL SEAL FAILED\n");
}
else
{
DWORD BytesWritten;
WriteFile(outputMFTfile, buffer_out, len_out, &BytesWritten, NULL);
}
EVP_CIPHER_CTX_cleanup(&ctx);
The following code is used for decryption(I removed the part where I provide the private key and initialize EVP):
HANDLE decryptedMFTfile=CreateFile("MFT_decrypted.dat",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD BytesWritten2;
while(bytesRead>0)
{
ReadFile(encryptedMFT,buffer,sizeof(buffer),&bytesRead,NULL);
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
printf("EVP OPEN FAILED \n");
}
WriteFile(decryptedMFTfile, &buffer_out, sizeof(buffer_out), &BytesWritten2, NULL);
}
CreateRsa code on request:
RSA * createRSA(unsigned char * key,int public)
{
RSA *rsa= NULL;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1);
if (keybio==NULL)
{
printf( "Failed to create key BIO");
return 0;
}
if(public)
{
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
}
else
{
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
}
if(rsa == NULL)
{
printf( "Failed to create RSA");
}
return rsa;
}

How to CopyMemory to copy struct using FileMapping?

I have following code, after CopyMemory my pBuf is empty, it contains no data from newCommand, or when I want to add something in that struct it doesnt work... What am I doing wrong?
struct StCommand
{
TCHAR sourcePath[MAX_PATH];
TCHAR sourceFile[MAX_PATH];
TCHAR fileName[MAX_PATH];
bool endThread;
};
handlesInstance.mapFileHandle = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
sizeof(StCommand), // maximum object size (low-order DWORD)
handlesInstance.valueBuffer); // name of mapping object
if (handlesInstance.mapFileHandle == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 0;
}
handlesInstance.pBuf = (StCommand*) MapViewOfFile(
handlesInstance.mapFileHandle, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
sizeof(StCommand));
if (handlesInstance.pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
return 0;
}
StCommand newCommand = { NULL, NULL, NULL, false };
CopyMemory(handlesInstance.pBuf, &newCommand, sizeof(StCommand));
CopyFiles(*handlesInstance.pBuf);
Here is CopyFiles function, where I send (*handlesInstance.pBuf) and I want to set values of pBuf here, to create path, to copy file later
void CopyFiles(StCommand stCommand)
{
while (!stCommand.endThread)
{
DWORD dwWaitEventResult;
dwWaitEventResult = WaitForSingleObject(handlesInstance.dataInEvent, INFINITE);
switch (dwWaitEventResult)
{
// Event object was signaled
case WAIT_OBJECT_0:
{
//Command processing
if (!stCommand.endThread)
{
GetSzSetting(pathValueName, REPOSITORY_PATH);
TCHAR newFile[MAX_PATH];
_tcscpy_s(newFile, handlesInstance.valueBuffer);
_tcscat_s(newFile, _T("/"));
TCHAR buffer[MAX_PATH];
swprintf_s(buffer, _T("%d"), GetDwordSetting(indexValueName, 0));
_tcscat_s(newFile, buffer);
_tcscat_s(newFile, _T("."));
_tcscat_s(newFile, stCommand.fileName);
TCHAR oldFile[MAX_PATH];
_tcscpy_s(oldFile, stCommand.sourcePath);
_tcscat_s(oldFile, _T("/"));
_tcscat_s(oldFile, stCommand.fileName);
if (CopyFile(oldFile, newFile, FALSE))
{
_tprintf(_T("File %s copied successfully into repository.\n"), stCommand.fileName);
SetDwordSetting(indexValueName, GetDwordSetting(indexValueName, 0) + 1);
}
else
{
_tprintf(_T("Could not copy file %s.\n"), stCommand.fileName);
_tprintf(_T("Failed with error code: %d\n"), GetLastError());
}
}
ResetEvent(handlesInstance.dataInEvent);
if (!SetEvent(handlesInstance.dataOutEvent))
{
printf("SetEvent OutEvent failed (%d)\n", GetLastError());
}
break;
}
// An error occurred
default:
printf("Wait error (%d)\n", GetLastError());
break;
}
}
}

Windows crypto API

I'm having trouble with a function I made to create a sha1 hash of some strings. The function generates a valid hash for strings longer than 4 chars, but for chars less than that the hash is wrong. I've been looking all over for a solution but I can't see whats wrong.
int create_hash(char *plaintext, char *digest) {
char digest_buff[3];
DWORD buf_size = SHA1_HASH_LEN;
HCRYPTPROV prov;
HCRYPTHASH hash;
BYTE rgbHash[SHA1_HASH_LEN];
CHAR rgbDigits[] = "0123456789abcdef";
int i;
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if(DEBUG) {
printf("CryptAcquireContext failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptCreateHash(prov, CALG_SHA, NULL, NULL, &hash)) {
if(DEBUG) {
printf("CryptCreateHash failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptHashData(hash, (BYTE *)plaintext, sizeof(hash), NULL)) {
if(DEBUG) {
printf("CryptHashData failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptGetHashParam(hash, HP_HASHVAL, rgbHash, &buf_size, NULL)) {
if(DEBUG) {
printf("CryptGetHashParam failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
for(i=0; i < buf_size; i++) {
sprintf(digest_buff, "%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]);
strcat(digest, digest_buff);
}
if(!CryptDestroyHash(hash)) {
if(DEBUG) {
printf("CryptDestroyHash failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(!CryptReleaseContext(prov, NULL)) {
if(DEBUG) {
printf("CryptReleaseContext failed: %d\n", GetLastError());
}
return SHA1_FAILED;
}
if(DEBUG) {
printf("digest: %s\n", digest);
}
return 0;
}
CryptHashData accepts the length of the data as third parameter, and you pass size of the hash buffer there. You need to pass smth like strlen(plaintext) there.

Resources