Encrypt and Decrypt some string in C++ And Delphi - c++

I have the following code in Delphi XE2 to Encrypt and Decrypt a String.
What is wrong is that I get different encrypt Results ? I need to read and write some string in both languages Delphi and C++, and I do not want use a DLL writing in Delphi to do It in C++
function CryptString(Const Input: string; password : AnsiString; Encrypt: Boolean) : string;
const
BufferSize=1024*1024;
var
StreamSource : TStringStream;
StreamDest : TStringStream;
CRYPTPROV : HCRYPTPROV;
CRYPTHASH : HCRYPTHASH;
CRYPTKEY : HCRYPTKEY;
Buffer : LPBYTE;
BytesIn : DWORD;
Final : Boolean;
Encoder : TIdEncoderMIME;
Decoder : TIdDecoderMIME;
DestStream : TStringStream;
begin
CryptAcquireContext(CRYPTPROV, nil, MS_DEF_DH_SCHANNEL_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
try
//create a valid key based in the password
if not CryptCreateHash(CRYPTPROV, CALG_SHA1, 0, 0, CRYPTHASH) then RaiseLastOSError;
try
if not CryptHashData(CRYPTHASH, #Password[1], Length(Password), 0) then RaiseLastOSError;
if not CryptDeriveKey(CRYPTPROV, CALG_RC4, CRYPTHASH, 0, CRYPTKEY) then RaiseLastOSError;
finally
CryptDestroyHash(CRYPTHASH);
end;
StreamSource := TStringStream.Create(Input);
StreamSource.Position := 0;
StreamDest := TStringStream.Create;
try
GetMem(Buffer, BufferSize);
try
if not Encrypt then
begin
//decode the string using base64
Decoder := TIdDecoderMIME.Create(nil);
try
DestStream := TStringStream.Create;
try
StreamDest.Position:=0;
Decoder.DecodeBegin(DestStream);
Decoder.Decode(StreamSource);
Decoder.DecodeEnd;
StreamSource.Clear;
DestStream.Position:=0;
StreamSource.CopyFrom(DestStream,DestStream.Size);
StreamSource.Position:=0;
finally
FreeAndNil( DestStream);
end;
finally
FreeAndNil( Decoder);
end;
end;
repeat
BytesIn := StreamSource.Read(Buffer^, BufferSize);
Final := (StreamSource.Position >= StreamSource.Size);
if Encrypt then begin
if not CryptEncrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn, BytesIn) then
RaiseLastOSError;
end
else if not CryptDecrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn) then
RaiseLastOSError;
StreamDest.Write(Buffer^, BytesIn);
until Final;
//encode the string using base64
if Encrypt then
begin
Encoder := TIdEncoderMIME.Create(nil);
try
DestStream:=TStringStream.Create;
try
StreamDest.Position:=0;
Encoder.Encode(StreamDest,DestStream);
Result := DestStream.DataString;
finally
FreeAndNil( DestStream);
end;
finally
FreeAndNil(Encoder);
end;
end
else
Result:= StreamDest.DataString;
finally
FreeMem(Buffer, BufferSize);
end;
finally
FreeAndNil( StreamSource);
FreeAndNil( StreamDest);
end;
finally
CryptReleaseContext(CRYPTPROV, 0);
end;
end;
I found the following code in C++ to make the same thing, but the encryption results are different.
int main()
{
const char* passw = "teste";
const char* toencrypt = "sa";
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(toencrypt);
PBYTE pBuffer;
CryptAcquireContext(&hProv, NULL, NULL , PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
CryptCreateHash(hProv, CALG_SHA1 , 0, 0, &hHash);
CryptHashData(hHash, (BYTE*)passw, strlen(passw), 0);
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);
CryptDestroyHash(hHash);
//--------------------------------------------------------------------
pBuffer = (BYTE *)malloc(todwSize);
strcpy((char*)pBuffer, toencrypt);
CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, todwSize);
PBYTE pBreturn = pBuffer;
const char* message = (const char*)pBreturn;
printf("%s", message);
system("pause");
//--------------------------------------------------------------------
DWORD dwSize = (DWORD)strlen(message);
PBYTE depBuffer;
depBuffer = (BYTE *)malloc(1460);
strcpy((char*)depBuffer, message);
CryptDecrypt(hKey, 0, TRUE, 0, depBuffer, &dwSize);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
if (GetLastError() != 0)
{
printf("%d", GetLastError());
}
PBYTE depBreturn = depBuffer;
printf("%s", (const char*)depBreturn);
printf("\n%d", strlen(message));
return 0;
}

This code bellow Show how Encrypt string, decrypt string, and encrypt string and decrypt string convert to base64 like Delphi code above do. in Vc++
Part of this code is based on CryptEncrypt does not encrypt whole text
#include "stdafx.h"
#include <atlenc.h>
#include <atlstr.h>
#include <locale.h>
static const unsigned char pr2six[256] =
{
/* ASCII table */
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
int Base64decode_len(const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
return nbytesdecoded + 1;
}
int Base64decode(char *bufplain, const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register unsigned char *bufout;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
bufout = (unsigned char *)bufplain;
bufin = (const unsigned char *)bufcoded;
while (nprbytes > 4) {
*(bufout++) =
(unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) =
(unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1) {
*(bufout++) =
(unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2) {
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3) {
*(bufout++) =
(unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
*(bufout++) = '\0';
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
}
static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int Base64encode_len(int len)
{
return ((len + 2) / 3 * 4) + 1;
}
int Base64encode(char *encoded, const char *string, int len)
{
int i;
char *p;
p = encoded;
for (i = 0; i < len - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((int)(string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1)) {
*p++ = basis_64[((string[i] & 0x3) << 4)];
*p++ = '=';
}
else {
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
*p++ = '\0';
return p - encoded;
}
bool encryptStr(const char *pSourceTxt,const char* pKey, int length, char * pEncryptTxt)
{
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(pSourceTxt), needSize;
PBYTE pBuffer;
char *txtBuf = (char *)_alloca(todwSize + 1);
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
{
memcpy(pBuffer = (BYTE *)_alloca(needSize), pSourceTxt, todwSize);
if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
{
txtBuf[todwSize] = NULL;
memcpy(txtBuf, pBuffer, todwSize);
memcpy(pEncryptTxt, txtBuf, todwSize + 1);
}
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return true;
}
bool encryptStrBase64(const char *pSourceTxt, const char* pKey, int length, char * pEncryptTxt)
{
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(pSourceTxt), needSize;
PBYTE pBuffer;
char *txtBuf = (char *)_alloca(todwSize + 1);
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
{
memcpy(pBuffer = (BYTE *)_alloca(needSize), pSourceTxt, todwSize);
if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
{
txtBuf[todwSize] = NULL;
memcpy(txtBuf, pBuffer, todwSize);
char *txtEncode64 = (char *)_alloca(strlen(pEncryptTxt));
Base64encode(txtEncode64, txtBuf, todwSize);
memcpy(pEncryptTxt, txtEncode64, todwSize +100);
}
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return true;
}
bool decryptStr(const char *pEncryptTxt, const char* pKey, int length, char * pDecryptTxt)
{
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD todwSize = (DWORD)strlen(pEncryptTxt);
PBYTE pBuffer = (BYTE *)_alloca(todwSize);
char *txtBuf = (char *)_alloca(todwSize + 1);
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
memcpy(pBuffer, pEncryptTxt, todwSize);
if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
{
txtBuf[todwSize] = NULL;
memcpy(txtBuf, pBuffer, todwSize);
memcpy(pDecryptTxt, txtBuf, todwSize + 1);
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return true;
}
bool decryptStrBase64(const char *pEncryptTxt, const char* pKey, int length, char * pDecryptTxt)
{
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
char *sourceTxt = (char *)_alloca(2048);
Base64decode(sourceTxt, pEncryptTxt);
DWORD todwSize = (DWORD)strlen(sourceTxt);
PBYTE pBuffer = (BYTE *)_alloca(todwSize);
char *txtBuf = (char *)_alloca(todwSize + 1);
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
{
memcpy(pBuffer, sourceTxt, todwSize);
if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
{
txtBuf[todwSize] = NULL;
memcpy(txtBuf, pBuffer, todwSize);
memcpy(pDecryptTxt, txtBuf, todwSize + 1);
}
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return true;
}
int main()
{
char* encryptWord = "test word";
char *encryptKey = "cryptkey";
int encryptLen = strlen(encryptWord);
char * txtEncrypt = (char *)_alloca(encryptLen+1);
//simple Encrypt TXT
encryptStr(encryptWord, encryptKey, encryptLen,txtEncrypt);
printf("Simple Encrypt %s \n", txtEncrypt);
//Decrypt string
char* decryptTxt = (char *)_alloca(encryptLen + 1);
decryptStr(txtEncrypt, encryptKey, encryptLen, decryptTxt);
printf("Txt decrypted %s \n", decryptTxt);
//Encrypt and Convert to Base64 like delphi Routine
char* base64TxtEncrypt = (char*)_alloca(encryptLen + 100);//need aloc more size due base64 routine
encryptStrBase64(encryptWord, encryptKey, encryptLen, base64TxtEncrypt);
printf("Base64 txt encrypted %s \n", base64TxtEncrypt);
//decrypt and Convert to original String like delphi Routine
char* base64TxtDecrypt = (char*)_alloca(encryptLen + 100);
decryptStrBase64( base64TxtEncrypt, encryptKey, strlen(base64TxtEncrypt) , base64TxtDecrypt);
printf("Base64 txt Decrypted %s \n", base64TxtDecrypt);
system("pause");
return 0;
}
And finally the conversion of this code to c#, and mission end
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace CryptCsharpNativo
{
class Program
{
public const uint PROV_RSA_FULL = 1;
public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
public const uint CRYPT_NEWKEYSET = 0x00000008;
public enum ALG_ID
{
CALG_MD5 = 0x00008003,
CALG_RC4 = 0x00006801,
CALG_SHA1 = 0x00008004
}
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptCreateHash(IntPtr hProv, ALG_ID Algid, IntPtr hKey, uint dwFlags, out IntPtr phHash);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDeriveKey(IntPtr hProv, ALG_ID Algid, IntPtr hBaseData, uint dwFlags, ref IntPtr phKey);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
const uint NTE_BAD_KEYSET = 0x80090016;
public static string decryptStr(string pSourceTxt, string pKey)
{
IntPtr hCryptProv;
IntPtr hKey = IntPtr.Zero;
IntPtr hHash;
int dwCount = 0;
byte[] key = Encoding.ASCII.GetBytes(pKey);
int datalen = pSourceTxt.Length;
// Get a handle to the default provider.
if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
return "";
}
// Decrypt the file with a session key derived from a password.
// Create a hash object.
if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_SHA1, IntPtr.Zero, 0, out hHash))
return "";
// Hash in the password data.
if (!CryptHashData(hHash, key, key.Length, 0))
return "";
// Derive a session key from the hash object.
if (!CryptDeriveKey(hCryptProv, ALG_ID.CALG_RC4, hHash, 0, ref hKey))
return "";
// Destroy the hash object.
if (!(CryptDestroyHash(hHash)))
return "";
hHash = IntPtr.Zero;
byte[] originalCrypt = Convert.FromBase64String(pSourceTxt);
if (!CryptDecrypt(hKey, IntPtr.Zero, true, 0, originalCrypt, ref datalen))
return "";
datalen = dwCount;
// Destroy session key.
if (hKey != IntPtr.Zero)
{
if (!(CryptDestroyKey(hKey)))
return "";
}
// Release provider handle.
if (hCryptProv != IntPtr.Zero)
{
if (!(CryptReleaseContext(hCryptProv, 0)))
return "";
}
return Encoding.ASCII.GetString(originalCrypt);
} // end Decryptfile
public static string encryptStr(string pSourceTxt, string pKey)
{
IntPtr hCryptProv;
IntPtr hKey = IntPtr.Zero;
IntPtr hHash;
int dwCount = 0;
byte[] sourceTxt = Encoding.ASCII.GetBytes(pSourceTxt);
byte[] key = Encoding.ASCII.GetBytes(pKey);
int datalen = pSourceTxt.Length;
// Get a handle to the default provider.
if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
return "";
}
// Decrypt the file with a session key derived from a password.
// Create a hash object.
if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_SHA1, IntPtr.Zero, 0, out hHash))
return "";
// Hash in the password data.
if (!CryptHashData(hHash, key, key.Length, 0))
return "";
// Derive a session key from the hash object.
if (!CryptDeriveKey(hCryptProv, ALG_ID.CALG_RC4 , hHash, 0, ref hKey))
return "";
// Destroy the hash object.
if (!(CryptDestroyHash(hHash)))
return "";
hHash = IntPtr.Zero;
if (!CryptEncrypt(hKey, IntPtr.Zero, true, 0, null, ref datalen))
return "";
if (!CryptEncrypt(hKey, IntPtr.Zero, true, 0, sourceTxt, ref datalen))
return "";
string base64 = Convert.ToBase64String(sourceTxt);
datalen = dwCount;
// Destroy session key.
if (hKey != IntPtr.Zero)
{
if (!(CryptDestroyKey(hKey)))
return "";
}
// Release provider handle.
if (hCryptProv != IntPtr.Zero)
{
if (!(CryptReleaseContext(hCryptProv, 0)))
return "";
}
return base64;
} // end encryptfile
static void Main(string[] args)
{
string encryptTxt = "Teste Crypt";
string key = "teste123";
string encryptStr = Program.encryptStr(encryptTxt, key);
string decryptStr = Program.decryptStr(encryptStr, key);
Console.Write("Encrypt String with Base64 = {0} \n" , encryptStr);
Console.Write("Decrypted String with base64 = {0}", decryptStr);
Console.ReadLine();
}
}
}

Related

0xC0000005: Access violation reading location 0x005EF9E4

I am having issues with Handles. I have Bytebeat (music in bytes) playing inside of a DWORD WINAPI function. When I try to terminate and close the thread, it straight up gives me the error in the title. This is my code:
#include <windows.h>
#pragma comment(lib, "Winmm.lib")
DWORD WINAPI bytebeat1(LPVOID) {
while (1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 11000, 11000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[11000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t & t + t / 256) - t * (t >> 15) & 64;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
}
DWORD WINAPI bytebeat2(LPVOID) {
while (1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[8000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t, t / 5) >> t / 25 & t / 55 ^ t & 255 ^ (t / 150) ^ 2508025 * 24240835810 & (t / 100) * t / 6000 ^ 5000 * t / 2500 ^ 25 * t / 24;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
}
int main() {
HANDLE beat1 = CreateThread(0, 0, bytebeat1, 0, 0, 0);
Sleep(6000);
TerminateThread(beat1, 0); CloseHandle(beat1);
Sleep(1000);
HANDLE beat2 = CreateThread(0, 0, bytebeat2, 0, 0, 0);
Sleep(6000);
TerminateThread(beat2, 0); CloseHandle(beat2);
}
I do not know why this is happening. The only fix is compiling it with G++ but I want it so I could just build it. Any help is appreciated. Thanks!
As the documentation makes clear, you can't use TerminateThread this way. Instead, replace the calls to Sleep with an interruptible sleep function that will terminate the thread cleanly and safely if requested to do so.
When you call TerminateThread, you are basically force-crashing your threads. They still have their own stack allocated and handles to Windows resources. They aren't cleaned up properly, causing your crash.
Here's a simple example of how to close your threads without any error. In a real-world scenario this is an unprofessional solution, but it shows the bare minimum that you need to do.
#include <windows.h>
#pragma comment(lib, "Winmm.lib")
volatile bool quit1 = false;
volatile bool quit2 = false;
DWORD WINAPI bytebeat1(LPVOID) {
while (!quit1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 11000, 11000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[11000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t & t + t / 256) - t * (t >> 15) & 64;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
return 0;
}
DWORD WINAPI bytebeat2(LPVOID) {
while (!quit2) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[8000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t, t / 5) >> t / 25 & t / 55 ^ t & 255 ^ (t / 150) ^ 2508025 * 24240835810 & (t / 100) * t / 6000 ^ 5000 * t / 2500 ^ 25 * t / 24;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
return 0;
}
int main() {
HANDLE beat1 = CreateThread(0, 0, bytebeat1, 0, 0, 0);
Sleep(6000);
quit1 = true;
WaitForSingleObject(beat1, INFINITE);
CloseHandle(beat1);
Sleep(1000);
HANDLE beat2 = CreateThread(0, 0, bytebeat2, 0, 0, 0);
Sleep(6000);
quit2 = true;
WaitForSingleObject(beat2, INFINITE);
CloseHandle(beat2);
}

Windows CAPI CryptDecrypt error key not working

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.

odbc binding to datetime column fails on Linux but works on Windows

Our C++ code on Windows uses ODBC to talk to SQL Server.
We are in the process of porting to Linux and
getting this ODBC error for a datetime Stored Procedure argument.
Datetime field overflow. Fractional second precision exceeds the scale specified in the parameter binding.
Googling that error says to set scale to 3 on the ODBC bind.
We do that and it works on Windows but not Linux.
Here is a semi small code sample that reproduces the problem.
The sample is 330 lines of C++ and 100 lines of SQL.
(The original is 1000 times bigger.)
It seems to be related to a blob SP argument.
datetime before the blob work, and those after the blob fail.
I tried making a 3 column test table with (datetime, blob, datetime)
but the problem did not happen.
On Windows this test inserts 820 rows while
on Linux it inserts 700 because 120 fail.
Windows has "ODBC Driver 17 for SQL Server".
Linux is Ubuntu 20.04, unixODBC 2.3.7, ODBC 17.7
Create a database name bgb_test2.
Create a DSN named bgb8_sql2016 pointing to DB server.
Add SQL user 'bgb' with password 'Abc-123'.
Or change the code as you like.
SQL code
USE [bgb_test2]
GO
/****** Object: StoredProcedure [dbo].[sp_TTemporalAccounts_ins] Script Date: 5/28/2021 11:46:19 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TTemporalAccounts](
[acctId] [int] NOT NULL,
[rowClassifier] [char](16) NULL,
[grpClassifier] [char](16) NULL,
[LAD] [datetime] NULL,
[LAPD] [datetime] NULL,
[NAD] [datetime] NULL,
[AccountBlob] [text] NULL,
[StatementDate] [datetime] NULL,
[postBalance] [money] NULL,
[Balance] [money] NULL,
[CountDe] [int] NULL,
[bucketMTD1] [money] NULL,
[bucketMTD2] [money] NULL,
[bucketMTD3] [money] NULL,
[bucketCTD1] [money] NULL,
[bucketCTD2] [money] NULL,
[bucketCTD3] [money] NULL,
[parent01ATID] [int] NULL,
[parent01AID] [int] NULL,
[parent02ATID] [int] NULL,
[parent02AID] [int] NULL,
[parent03ATID] [int] NULL,
[parent03AID] [int] NULL,
[VisaInterestRate] [money] NULL,
[VisaLateCharge] [money] NULL,
[VisaParam1] [money] NULL,
[VisaParam2] [money] NULL,
[VisaParam3] [money] NULL,
[VisaParam4] [money] NULL,
[VisaParam5] [money] NULL,
[VisaParam6] [money] NULL,
[VisaParam7] [money] NULL,
[VisaParam8] [money] NULL,
[tpyNAD] [datetime] NULL,
[tpyLAD] [datetime] NULL,
[tpyBlob] [text] NULL,
[param_sig] [int] NULL,
[param_state] [varchar](171) NULL,
[param_lcd] [datetime] NULL,
[param_fvt] [datetime] NULL,
[_paramlvt] [datetime] NULL,
CONSTRAINT [csPk_TTemporalAccounts] PRIMARY KEY CLUSTERED
(
[acctId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE PROCEDURE [dbo].[sp_TTemporalAccounts_ins] (
#acctId int, #rowClassifier char (16), #grpClassifier char (16),
#LAD datetime, #LAPD datetime, #NAD datetime,
#AccountBlob text, #StatementDate datetime, #postBalance money,
#Balance money, #CountDe int,
#bucketMTD1 money, #bucketMTD2 money, #bucketMTD3 money,
#bucketCTD1 money, #bucketCTD2 money, #bucketCTD3 money,
#parent01ATID int, #parent01AID int,
#parent02ATID int, #parent02AID int,
#parent03ATID int, #parent03AID int,
#VisaInterestRate money, #VisaLateCharge money,
#VisaParam1 money, #VisaParam2 money, #VisaParam3 money,
#VisaParam4 money, #VisaParam5 money, #VisaParam6 money,
#VisaParam7 money, #VisaParam8 money,
#tpyNAD datetime, #tpyLAD datetime, #tpyBlob text,
#param_sig int, #param_state varchar (171),
#param_lcd datetime, #param_fvt datetime, #_paramlvt datetime
) AS SET NOCOUNT ON; SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; SET ARITHABORT ON; SET QUOTED_IDENTIFIER ON; SET CONCAT_NULL_YIELDS_NULL ON; SET NUMERIC_ROUNDABORT OFF;
INSERT INTO TTemporalAccounts ( [acctId], [rowClassifier], [grpClassifier], [LAD], [LAPD], [NAD],
[AccountBlob], [StatementDate], [postBalance], [Balance], [CountDe], [bucketMTD1], [bucketMTD2], [bucketMTD3],
[bucketCTD1], [bucketCTD2], [bucketCTD3], [parent01ATID], [parent01AID], [parent02ATID], [parent02AID],
[parent03ATID], [parent03AID], [VisaInterestRate], [VisaLateCharge],
[VisaParam1], [VisaParam2], [VisaParam3], [VisaParam4], [VisaParam5], [VisaParam6], [VisaParam7], [VisaParam8],
[tpyNAD], [tpyLAD], [tpyBlob],
[param_sig], [param_state], [param_lcd], [param_fvt], [_paramlvt])
VALUES ( #acctId, #rowClassifier, #grpClassifier, #LAD, #LAPD, #NAD, #AccountBlob, #StatementDate,
#postBalance, #Balance, #CountDe, #bucketMTD1, #bucketMTD2, #bucketMTD3, #bucketCTD1, #bucketCTD2, #bucketCTD3,
#parent01ATID, #parent01AID, #parent02ATID, #parent02AID, #parent03ATID, #parent03AID,
#VisaInterestRate, #VisaLateCharge,
#VisaParam1, #VisaParam2, #VisaParam3, #VisaParam4, #VisaParam5, #VisaParam6, #VisaParam7, #VisaParam8,
#tpyNAD, #tpyLAD, #tpyBlob,
#param_sig, #param_state, #param_lcd, #param_fvt, #_paramlvt)
GO
C++ code
#ifdef WIN32
#ifdef _DEBUG
#define _ITERATOR_DEBUG_LEVEL 1
#endif
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <sal.h>
#endif
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <string>
// Binding to datetime column is failing on Linux
RETCODE
BBCheckForInfo(SQLSMALLINT HandleType, SQLHANDLE h, RETCODE rc, const char* api, const char* name = 0)
{
SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN rc2;
long cpu_time = 0;
long elapsed_time = 0;
// Support growing these if needed
SQLCHAR* pMsg = Msg;
size_t MsgAlloc = sizeof(Msg);
if (name == 0) name = "";
// Print any errors or warnings.
if (rc != SQL_SUCCESS) {
// Get the status records.
i = 1;
while ((rc2 = SQLGetDiagRec(HandleType, h, i, SqlState, &NativeError, pMsg, MsgAlloc, &MsgLen)) == SQL_SUCCESS || rc2 == SQL_SUCCESS_WITH_INFO) {
if (rc2 == SQL_SUCCESS_WITH_INFO) {
printf("Msg[] too small, need %d bytes (have %d)\n", MsgLen, MsgAlloc);
if (pMsg != Msg) delete[] pMsg;
MsgAlloc = MsgLen + 100;
pMsg = new SQLCHAR[MsgAlloc + 10];
// Do not increment i so we retry getting the last error message
continue;
}
i++;
printf("Query %s API %s() Name %s State %s Native %d Msg %s\n",
name,
api,
name,
SqlState, NativeError, Msg);
} // while
if (rc2 != SQL_NO_DATA) {
printf("SQLGetDiagRec(%s) name %s returned %d\n", api, name, rc2);
}
} // if
if (pMsg != Msg) delete[] pMsg;
pMsg = 0;
if (rc == SQL_SUCCESS_WITH_INFO) rc = SQL_SUCCESS;
return rc;
}
enum class CI_type {
CI_int,
CI_char16,
CI_datetime,
CI_text,
CI_money,
CI_varchar171,
// CI_end
};
#define N_COL 41
struct ColInfo {
const char* name;
enum CI_type type;
} g_ColInfoArray[N_COL] = {
"acctId", CI_type::CI_int,
"rowClassifier", CI_type::CI_char16,
"grpClassifier", CI_type::CI_char16,
"LAD", CI_type::CI_datetime,
"LAPD", CI_type::CI_datetime,
"NAD", CI_type::CI_datetime,
"AccountBlob", CI_type::CI_text,
"StatementDate", CI_type::CI_datetime,
"postBalance", CI_type::CI_money,
"Balance", CI_type::CI_money,
"CountDe", CI_type::CI_int,
"bucketMTD1", CI_type::CI_money,
"bucketMTD2", CI_type::CI_money,
"bucketMTD3", CI_type::CI_money,
"bucketCTD1", CI_type::CI_money,
"bucketCTD2", CI_type::CI_money,
"bucketCTD3", CI_type::CI_money,
"parent01ATID", CI_type::CI_int,
"parent01AID", CI_type::CI_int,
"parent02ATID", CI_type::CI_int,
"parent02AID", CI_type::CI_int,
"parent03ATID", CI_type::CI_int,
"parent03AID", CI_type::CI_int,
"VisaInterestRate", CI_type::CI_money,
"VisaLateCharge", CI_type::CI_money,
"VisaParam1", CI_type::CI_money,
"VisaParam2", CI_type::CI_money,
"VisaParam3", CI_type::CI_money,
"VisaParam4", CI_type::CI_money,
"VisaParam5", CI_type::CI_money,
"VisaParam6", CI_type::CI_money,
"VisaParam7", CI_type::CI_money,
"VisaParam8", CI_type::CI_money,
"tpyNAD", CI_type::CI_datetime,
"tpyLAD", CI_type::CI_datetime,
"tpyBlob", CI_type::CI_text,
"param_sig", CI_type::CI_int,
"param_state", CI_type::CI_varchar171,
"param_lcd", CI_type::CI_datetime,
"param_fvt", CI_type::CI_datetime,
"_paramlvt", CI_type::CI_datetime,
// { 0, CI_type::CI_end }
};
void
main()
{
std::string ConStr;
ConStr += ";DSN=bgb8_sql2016"; // change
ConStr += ";DATABASE=bgb_test2";
ConStr += ";UID=bgb;PWD=Abc-123"; // change
ConStr += ";APP=DBB";
// const char* computername = dbbGetenv("COMPUTERNAME");
ConStr += ";WSID=host";
// ConStr += computername;
ConStr += ";AutoTranslate=no";
SQLHENV hEnv;
int rc;
rc = SQLAllocEnv(&hEnv);
rc = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
rc = BBCheckForInfo(SQL_HANDLE_ENV, hEnv, rc, "SQLSetEnvAttr", "SQL_ATTR_ODBC_VERSION");
SQLHDBC hDbc;
rc = SQLAllocConnect(hEnv, &hDbc);
rc = BBCheckForInfo(SQL_HANDLE_ENV, hEnv, rc, "SQLAllocConnect()");
// rc = SQLSetConnectAttr(hDbc, SQL_COPT_SS_BCP, (void*)SQL_BCP_ON, SQL_IS_INTEGER);
// BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLSetConnectAttr", "SQL_COPT_SS_BCP");
short outlen = 0;
UCHAR outbuf[2048];
rc = SQLDriverConnect(hDbc, NULL, (UCHAR*)ConStr.c_str(), ConStr.length(), outbuf, sizeof(outbuf), &outlen, SQL_DRIVER_NOPROMPT);
rc = BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLDriverConnect()");
SQLHSTMT hstmt;
SQLAllocStmt(hDbc, &hstmt);
rc = BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLAllocStmt()");
int skey = 0;
for (int rows = 0; rows < 20; rows++) {
// for x in 0 .. 2^N_COL-1
// (c in x) means set col, else NULL
// Inserting 2^41 rows may hit practical limitations (BOOM)
for (int nn = 0; nn < N_COL; nn++) {
void* mem[N_COL];
for (int c = 0; c < N_COL; c++) {
// Set PK and column nn to values, rest are NULL
SQLHSTMT StatementHandle = hstmt;
SQLUSMALLINT ParameterNumber = c + 1;
SQLSMALLINT InputOutputType = SQL_PARAM_INPUT;
SQLSMALLINT ValueType = -1;
SQLSMALLINT ParameterType = -1;
SQLULEN ColumnSize = 0;
SQLSMALLINT DecimalDigits = 0;
SQLPOINTER ParameterValuePtr = 0;
SQLLEN BufferLength = 0;
SQLLEN* StrLen_or_IndPtr = 0;
switch (g_ColInfoArray[c].type) {
case CI_type::CI_int:
ValueType = SQL_C_DEFAULT;
ParameterType = SQL_INTEGER;
break;
case CI_type::CI_char16:
ValueType = SQL_C_CHAR;
ParameterType = SQL_CHAR;
ColumnSize = 16;
break;
case CI_type::CI_datetime:
ValueType = SQL_C_TYPE_TIMESTAMP;
ParameterType = SQL_TYPE_TIMESTAMP;
ColumnSize = 23;
DecimalDigits = 3;
break;
case CI_type::CI_text:
ValueType = SQL_C_CHAR;
ParameterType = SQL_LONGVARCHAR;
ColumnSize = 100;
break;
case CI_type::CI_money:
ValueType = SQL_C_CHAR;
ParameterType = SQL_VARCHAR;
break;
case CI_type::CI_varchar171:
ValueType = SQL_C_CHAR;
ParameterType = SQL_CHAR;
ColumnSize = 171;
break;
}
// (c == 0) is Primary Key
int value = 5;
if (c == 0) value = skey++;
if (c == 0 || c == nn) {
switch (g_ColInfoArray[c].type) {
case CI_type::CI_int:
{
SQLINTEGER* p = new SQLINTEGER;
mem[c] = p;
*p = value;
}
break;
case CI_type::CI_char16:
{
BufferLength = 16;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
case CI_type::CI_datetime:
{
SQL_TIMESTAMP_STRUCT* p = new SQL_TIMESTAMP_STRUCT;
mem[c] = p;
p->year = 2021;
p->month = 5;
p->day = 27;
p->hour = 20;
p->minute = 21;
p->second = 0;
p->fraction = 0;
}
break;
case CI_type::CI_text:
{
BufferLength = 100;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
case CI_type::CI_money:
{
BufferLength = 10;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "555.55");
}
break;
case CI_type::CI_varchar171:
{
BufferLength = 171;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
}
ParameterValuePtr = mem[c];
}
else {
SQLLEN* p = new SQLLEN;
mem[c] = p;
*p = SQL_NULL_DATA;
StrLen_or_IndPtr = p;
}
rc = SQLBindParameter(StatementHandle, ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_or_IndPtr);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter");
} // for
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
for (int c = 0; c < N_COL; c++) {
delete mem[c];
}
} // for
} // for
#if 0
// Table has (int, datetime, text, datetime)
// Did not fail like expected
SQLINTEGER null = SQL_NULL_DATA;
// rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
// rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
// rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?)}", SQL_NTS);
// rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
// SQLcancel
SQL_TIMESTAMP_STRUCT ts;
ts.year = 2021;
ts.month = 5;
ts.day = 27;
ts.hour = 20;
ts.minute = 21;
ts.second = 0;
ts.fraction = 0;
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, &ts, 0, 0);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, &ts, 0, 0);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
// Bindings remain in effect until the application calls SQLBindParameter again,
// calls SQLFreeStmt with the SQL_RESET_PARAMS option,
// or calls SQLSetDescField to set the SQL_DESC_COUNT header field of the APD to 0
#endif
}

Model class fails to initialize in DirectX 10

My project uses DirectX 10 and some of its boilerplate to render a scene, however, it crashes with an error message "Could not initialize the model object." As far as I understand, making it up to this point means that, at the very least, the model has been successfully created, so the error must be in one of the files below, which is fortunate as the most difficult tasks are handled by the FallBodyClass.cpp that hosts OpenCL API interactions. If needed, I can try attaching parts of it in a later edit.
During debug, my IDE shows that all components of m_Model (m_vertexBuffer, m_indexBuffer etc) are shown as with _vfptr . I do not know what to make of it, but it does seem to confirm that modelclass.cpp is the point of failure.
graphicsclass.cpp
GraphicsClass::GraphicsClass()
{
m_Direct3D = 0;
m_Model = 0;
m_ColorShader = 0;
m_bodies = BODIES;
}
GraphicsClass::GraphicsClass(const GraphicsClass& other)
{}
GraphicsClass::~GraphicsClass()
{}
bool GraphicsClass::Initialize(int screenWidth, int screenHeight, HWND hwnd)
{
bool result;
// Create the Direct3D object.
m_Direct3D = new D3DClass;
if (!m_Direct3D)
{
return false;
}
// Initialize the Direct3D object.
result = m_Direct3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
if (!result)
{
MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK);
return false;
}
// Create the model object.
m_Model = new ModelClass(m_bodies);
if (!m_Model)
{
return false;
}
// Initialize the model object.
result = m_Model->Initialize(m_Direct3D->GetDevice());
if (!result)
{
MessageBox(hwnd, L"Could not initialize the model object.", L"Error", MB_OK);
return false;
}
modelclass.cpp
ModelClass::ModelClass(int bodies)
{
m_vertexBuffer = 0;
m_indexBuffer = 0;
m_positions = 0;
m_velocities = 0;
m_bodySystem = 0;
m_bodies = bodies;
}
ModelClass::ModelClass(const ModelClass& other)
{}
ModelClass::~ModelClass()
{}
bool ModelClass::Initialize(ID3D10Device* device)
{
bool result;
TwoLines twoLinesConstants = CalculateLinesConstants(M_PI_4);
m_positions = new float[COORD_DIM * m_bodies];
m_velocities = new float[VEL_DIM * m_bodies];
m_bodySystem = new class FallBodyClass(m_bodies, &m_positions, &m_velocities, twoLinesConstants, result);
if (!result) {
return false;
}
// Initialize the vertex and index buffer that hold the geometry for the triangle.
result = InitializeBuffers(device, twoLinesConstants);
if(!result)
{
return false;
}
return true;
}
FallBodyclass.cpp
FallBodyClass::FallBodyClass(int bodies, float ** positionsCPU, float ** velocitiesCPU, TwoLines twoLines, bool & success)
:bodies(bodies)
{
cl_int ret;
// getting the first available platform
cl_platform_id clPlatformID[2];
cl_platform_id GPUplatform;
cl_uint num_platforms;
//char str[1024];
ret = clGetPlatformIDs(2, clPlatformID, &num_platforms);
GPUplatform = clPlatformID[0]; //choose GPU platform
//error |= clGetPlatformInfo(GPUplatform, CL_PLATFORM_NAME, 0, NULL, NULL);
//clGetPlatformInfo(GPUplatform, CL_PLATFORM_VENDOR, sizeof(str), str, NULL);
// getting the first GPU device
ret |= clGetDeviceIDs(GPUplatform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
if (ret != CL_SUCCESS)
{
success = false;
return;
}
//clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(str), str, NULL);
// creating the context
context = clCreateContext(0, 1, &device, NULL, NULL, &ret);
if (ret != CL_SUCCESS)
{
success = false;
return;
}
cl_queue_properties props[] = {
CL_QUEUE_PROFILING_ENABLE
};
// creating the command queue
queue = clCreateCommandQueueWithProperties(context, device, props, &ret);
if (ret != CL_SUCCESS)
{
success = false;
return;
}
// setting the local variables
// (at the same time one of them supposed to be 0 and another to be 1)
read = 0;
write = 1;
// reading the kernel
FILE * f = NULL;
char fileName[18] = "kernel.cl";
f = fopen(fileName, "rb");
if(f == NULL)
{
success = false;
return;
}
// getting the length of the source code for the kernel
fseek(f, 0, SEEK_END);
size_t codeLength = ftell(f);
rewind(f);
char * code = (char *)malloc(codeLength + 1);
if (fread(code, codeLength, 1, f) != 1)
{
fclose(f);
free(code);
success = false;
return;
}
// closing the file and 0-terminating the source code
fclose(f);
code[codeLength] = '\0';
// creating the program
program = clCreateProgramWithSource(context, 1, (const char **)&code, &codeLength, &ret);
if (ret != CL_SUCCESS)
{
success = false;
return;
}
// clearing the memory
free(code);
// building the program
ret |= clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
// creating the kernel
kernel = clCreateKernel(program, "impactManager", &ret);
// setting the local size of the group the largest possible in order to load all computational units
int numGroups;
ret |= clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(numGroups), &numGroups, NULL);
localSize = bodies / numGroups;
// allocating pinned buffers for velocities and positions, and stuck
positionsCPUBuffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, COORD_DIM * bodies * sizeof(float) , NULL, NULL);
velocitiesCPUBuffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, VEL_DIM * bodies * sizeof(float) , NULL, NULL);
linesCPUBuffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, 8 * sizeof(float), NULL, NULL);
// get pointers to arrays to operate with the buffers (array map buffers here (to program) as float-arrays)
*positionsCPU = (float *)clEnqueueMapBuffer(queue, positionsCPUBuffer, CL_TRUE, CL_MAP_WRITE, 0, COORD_DIM * bodies * sizeof(float), 0, NULL, NULL, NULL);
*velocitiesCPU = (float *)clEnqueueMapBuffer(queue, velocitiesCPUBuffer, CL_TRUE, CL_MAP_WRITE, 0, VEL_DIM * bodies * sizeof(float), 0, NULL, NULL, NULL);
float * linesCPU = (float *)clEnqueueMapBuffer(queue, linesCPUBuffer, CL_TRUE, CL_MAP_WRITE, 0, 8 * sizeof(float), 0, NULL, NULL, NULL);
// initialization of the bodies' positions and velocities, and stuck
initBodies(*positionsCPU, *velocitiesCPU);
initLines(twoLines, linesCPU);
// unmapping the pointers to arrays (invalidates array pointers)
clEnqueueUnmapMemObject(queue, positionsCPUBuffer, *positionsCPU, 0, NULL, NULL);
clEnqueueUnmapMemObject(queue, velocitiesCPUBuffer, *velocitiesCPU, 0, NULL, NULL);
clEnqueueUnmapMemObject(queue, linesCPUBuffer, linesCPU, 0, NULL, NULL);
// allocate two arrays on GPU for positions and velocities
for (int i = 0; i < 2; ++i) {
positionsGPU[i] = clCreateBuffer(context, CL_MEM_READ_WRITE, COORD_DIM * bodies * sizeof(float), NULL, NULL);
ret |= clEnqueueWriteBuffer(queue, positionsGPU[i], CL_TRUE, 0, COORD_DIM * bodies * sizeof(float), *positionsCPU, 0, NULL, NULL);
velocitiesGPU[i] = clCreateBuffer(context, CL_MEM_READ_WRITE, VEL_DIM * bodies * sizeof(float), NULL, NULL);
ret |= clEnqueueWriteBuffer(queue, velocitiesGPU[i], CL_TRUE, 0, VEL_DIM * bodies * sizeof(float), *velocitiesCPU, 0, NULL, NULL);
}
linesGPU = clCreateBuffer(context, CL_MEM_READ_WRITE, 8 * sizeof(float), NULL, NULL);
ret |= clEnqueueWriteBuffer(queue, linesGPU, CL_TRUE, 0, 8 * sizeof(float), linesCPU, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
success = false;
return;
}
}
void FallBodyClass::initLines(IN TwoLines l, OUT float *linesCPU)
{
linesCPU[0] = l.a1;
linesCPU[1] = l.b1;
linesCPU[2] = l.R1.x;
linesCPU[3] = l.R1.y;
linesCPU[4] = l.a2;
linesCPU[5] = l.b2;
linesCPU[6] = l.R2.x;
linesCPU[7] = l.R2.y;
}
// initialization of the bodies' positions and velocities
void FallBodyClass::initBodies(float * positionsCPU, float * velocitiesCPU)
{
float scale = 0.20f;
// initialization of the memory
memset(positionsCPU, 0, COORD_DIM * bodies * sizeof(float));
memset(velocitiesCPU, 0, VEL_DIM * bodies * sizeof(float));
// for the randomization
srand((unsigned int)time(NULL));
for (int i = 0; i < bodies; i++)
{
positionsCPU[COORD_DIM * i] = 1.8*((rand() / (float)RAND_MAX) - 0.5); //x axis
positionsCPU[COORD_DIM * i + 1] = 0.9; //y axis
positionsCPU[COORD_DIM * i + 2] = 0.0f; //z axis
positionsCPU[COORD_DIM * i + 3] = 0.0f; // stuck variable
// velocities are zeros
velocitiesCPU[VEL_DIM* i] = 0.0;
velocitiesCPU[VEL_DIM* i + 1] = -2 * (rand() / (float)RAND_MAX);
velocitiesCPU[VEL_DIM* i + 2] = 0.0;
}
}
// updating the bodies' positions and velocities. Stuck is updated inside too
void FallBodyClass::update(float dt, float * positionsCPU, float * velocitiesCPU, bool & success)
{
cl_int error = CL_SUCCESS;
size_t global_work_size;
size_t local_work_size;
success = true;
if (localSize > bodies)
localSize = bodies;
local_work_size = localSize;
global_work_size = bodies;
// passing the arguments
// we write the new positions and velocities and read the previous ones
error |= clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&positionsGPU[write]);
error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&velocitiesGPU[write]);
error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&positionsGPU[read]);
error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&velocitiesGPU[read]);
error |= clSetKernelArg(kernel, 4, sizeof(cl_float), (void *)&dt);
error |= clSetKernelArg(kernel, 5, sizeof(cl_mem), (void *)&linesGPU);
// just swap read and write in order not to copy the arrays
int temp;
temp = write;
write = read;
read = temp;
// executing the kernel
error |= clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &global_work_size, &local_work_size, 0, NULL, NULL);
// synchronization
clFinish(queue);
// asynchronously reading the updated values
error |= clEnqueueReadBuffer(queue, positionsGPU[read], CL_FALSE, 0, COORD_DIM * bodies * sizeof(float), positionsCPU, 0, NULL, NULL);
if (error != CL_SUCCESS)
{
success = false;
}
error |= clEnqueueReadBuffer(queue, velocitiesGPU[read], CL_FALSE, 0, VEL_DIM * bodies * sizeof(float), velocitiesCPU, 0, NULL, NULL);
if (error != CL_SUCCESS)
{
success = false;
}
///////////
bool toReboot = positionsCPU[3]; //fourth index of the [0] first element
//bool toReboot = false;
////////////
if (toReboot) {
positionsCPU = (float *)clEnqueueMapBuffer(queue, positionsCPUBuffer, CL_TRUE, CL_MAP_WRITE, 0, COORD_DIM * bodies * sizeof(float), 0, NULL, NULL, NULL);
velocitiesCPU = (float *)clEnqueueMapBuffer(queue, velocitiesCPUBuffer, CL_TRUE, CL_MAP_WRITE, 0, VEL_DIM * bodies * sizeof(float), 0, NULL, NULL, NULL);
initBodies(positionsCPU, velocitiesCPU);
// unmapping the pointers
clEnqueueUnmapMemObject(queue, positionsCPUBuffer, positionsCPU, 0, NULL, NULL);
clEnqueueUnmapMemObject(queue, velocitiesCPUBuffer, velocitiesCPU, 0, NULL, NULL);
//update values on GPU side
error |= clEnqueueWriteBuffer(queue, positionsGPU[read], CL_TRUE, 0, COORD_DIM * bodies * sizeof(float), positionsCPU, 0, NULL, NULL);
error |= clEnqueueWriteBuffer(queue, velocitiesGPU[read], CL_TRUE, 0, VEL_DIM * bodies * sizeof(float), velocitiesCPU, 0, NULL, NULL);
}
return;
}
FallBodyClass::~FallBodyClass(void)
{
// synchronization (if something has to be done)
clFinish(queue);
// releasing all objects
clReleaseMemObject(linesGPU);
clReleaseMemObject(linesCPUBuffer);
clReleaseMemObject(velocitiesGPU[0]);
clReleaseMemObject(velocitiesGPU[1]);
clReleaseMemObject(positionsGPU[0]);
clReleaseMemObject(positionsGPU[1]);
clReleaseMemObject(positionsCPUBuffer);
clReleaseMemObject(velocitiesCPUBuffer);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(queue);
clReleaseContext(context);
}

How to create a public/private key pair to use with OpenSSL

i am trying to create a windows application which creates a public and private key and export this so that i can use this with OpenSSL.
I took same examples provided by MSDN but there is something wrong... I think its a problem of the sizes for allocating memory.
The result i need is a base64 encoded public and private key like this:
const char* szPemPrivKey =
"-----BEGIN RSA PRIVATE KEY-----"
"MIICXAIBAAKBgQCf6YAJOSBYPve1jpYDzq+w++8YVoATI/YCi/RKZaQk+l2ZfoUQ"
"g0qrYrfkzeoOa/qd5VLjTTvHEgwXnlDXMfo+vSgxosUxDOZXMTBqJGOViv5K2QBv"
"k8A1wi4k8tuo/7OWya29HvcfavUk3YXaV2YFe8V6ssaZjNcVWmDdjqNkXwIDAQAB"
"AoGALrd+ijNAOcebglT3ioE1XpUbUpbir7TPyAqvAZUUESF7er41jY9tnwgmBRgL"
"Cs+M1dgLERCdKBkjozrDDzswifFQmq6PrmYrBkFFqCoLJwepSYdWnK1gbZ/d43rR"
"2sXzSGZngscx0CxO7KZ7xUkwENGd3+lKXV7J6/vgzJ4XnkECQQDTP6zWKT7YDckk"
"We04hbhHyBuNOW068NgUUvoZdBewerR74MJx6nz28Tp+DeNvc0EveiQxsEnbV8u+"
"NRkX5y0xAkEAwcnEAGBn5kJd6SpU0ALA9XEpUv7tHTAGQYgCRbfTT59hhOq6I22A"
"ivjOCNG9c6E7EB2kcPVGuCpYUhy7XBIGjwJAK5lavKCqncDKoLwGn8HJdNcyCIWv"
"q5iFoDw37gTt1ricg2yx9PzmabkDz3xiUmBBNeFJkw/FToXiQRGIakyGIQJAJIem"
"PPPvYgZssYFbT4LVYO8d/Rk1FWVyKHQ9CWtnmADRXz7oK7l+m7PfEuaGsf9YpOcR"
"koGJ/TluQLxNzUNQnQJBAImwr/yYFenIx3HQ6UX/fCt6qpGDv0VfOLyR64MNeegx"
"o7DhNxHbFkIGzk4lKhMKcHKDrawZbdJtS9ie2geSwVQ="
"-----END RSA PRIVATE KEY-----";
const char* szPemPubKey =
"-----BEGIN RSA PUBLIC KEY-----"
"MIGJAoGBAJ/pgAk5IFg+97WOlgPOr7D77xhWgBMj9gKL9EplpCT6XZl+hRCDSqti"
"t+TN6g5r+p3lUuNNO8cSDBeeUNcx+j69KDGixTEM5lcxMGokY5WK/krZAG+TwDXC"
"LiTy26j/s5bJrb0e9x9q9STdhdpXZgV7xXqyxpmM1xVaYN2Oo2RfAgMBAAE="
"-----END RSA PUBLIC KEY-----";
https://www.idrix.fr/Root/Samples/capi_pem.cpp
Can someone correct my code or give me a hint what i do wrong?
int CreateKeys(DWORD keyLength)
{
/* variables */
HCRYPTPROV hCryptProv = NULL;
DWORD flags = keyLength /*key length*/ << 16;
flags |= CRYPT_EXPORTABLE;
DWORD size = 0;
HCRYPTKEY hKey = NULL;
/* variables public key */
HCRYPTKEY hPublicKey = NULL;
DWORD dwPublicKeyLen = 0;
BYTE* pbPublicKey = NULL;
HANDLE hPublicKeyFile = NULL;
LPBYTE pPublicBLOB = (LPBYTE)LocalAlloc(0, size);
/* variables private key */
HCRYPTKEY hPrivateKey = NULL;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPrivateKey = NULL;
HANDLE hPrivateKeyFile = NULL;
LPBYTE pPrivateKeyBLOB = (LPBYTE)LocalAlloc(0, size);
/* get provider */
DWORD rc = CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
// 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("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("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;
}
/*
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, 0, &size);
LPBYTE pPrivKeyBLOB = (LPBYTE)LocalAlloc(0, size);
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, pPrivKeyBLOB, &size);
*/
/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, NULL, &dwPrivateKeyLen);
LPBYTE pPrivateDER = (LPBYTE)LocalAlloc(0, dwPrivateKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, pPrivateDER, &dwPrivateKeyLen);
/* PEM */
DWORD pemPrivateSize = 0;
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPrivateSize);
LPSTR pPrivatePEM = (LPSTR)LocalAlloc(0, pemPrivateSize);
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPrivateSize);
/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbPublicKey, 0, NULL, NULL, &dwPublicKeyLen);
LPBYTE pPublicDER = (LPBYTE)LocalAlloc(0, dwPublicKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbPublicKey, 0, NULL, pPublicDER, &dwPublicKeyLen);
/* PEM */
DWORD pemPublicSize = 0;
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPublicSize);
LPSTR pPublicPEM = (LPSTR)LocalAlloc(0, pemPublicSize);
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPublicSize);
printf("%s", pPrivatePEM);
printf("%s", pPublicPEM);
return 0;
}
it seem like you provided wrong format to the CryptEncodeObjectEx Function to get public keys
I used CryptExportPublicKeyInfo to get the right key info.
Try this code:
int CreateKeys(DWORD keyLength)
{
/* variables */
HCRYPTPROV hCryptProv = NULL;
DWORD flags = keyLength /*key length*/ << 16;
flags |= CRYPT_EXPORTABLE;
DWORD size = 0;
HCRYPTKEY hKey = NULL;
/* variables public key */
HCRYPTKEY hPublicKey = NULL;
DWORD dwPublicKeyLen = 0;
BYTE* pbPublicKey = NULL;
HANDLE hPublicKeyFile = NULL;
LPBYTE pPublicBLOB = (LPBYTE)LocalAlloc(0, size);
/* variables private key */
HCRYPTKEY hPrivateKey = NULL;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPrivateKey = NULL;
HANDLE hPrivateKeyFile = NULL;
LPBYTE pPrivateKeyBLOB = (LPBYTE)LocalAlloc(0, size);
/* get provider */
DWORD rc = CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
// 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("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("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;
}
/*
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, 0, &size);
LPBYTE pPrivKeyBLOB = (LPBYTE)LocalAlloc(0, size);
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, pPrivKeyBLOB, &size);
*/
/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, NULL, &dwPrivateKeyLen);
LPBYTE pPrivateDER = (LPBYTE)LocalAlloc(0, dwPrivateKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, pPrivateDER, &dwPrivateKeyLen);
/* PEM */
DWORD pemPrivateSize = 0;
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPrivateSize);
LPSTR pPrivatePEM = (LPSTR)LocalAlloc(0, pemPrivateSize);
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPrivateSize);
DWORD pkiLen = 0;
LPVOID pki = nullptr;
rc = CryptExportPublicKeyInfo(hCryptProv, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &pkiLen);
// allocate memory
pki = (LPBYTE)LocalAlloc(0, pkiLen);
rc = CryptExportPublicKeyInfo(hCryptProv, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (PCERT_PUBLIC_KEY_INFO)pki, &pkiLen);
/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pki, 0, NULL, NULL, &pkiLen);
LPBYTE pPublicDER = (LPBYTE)LocalAlloc(0, dwPublicKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pki, 0, NULL, pPublicDER, &dwPublicKeyLen);
/* PEM */
DWORD pemPublicSize = 0;
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPublicSize);
LPSTR pPublicPEM = (LPSTR)LocalAlloc(0, pemPublicSize);
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, pPublicPEM, &pemPublicSize);
printf("%s", pPrivatePEM);
printf("%s", pPublicPEM);
return 0;
}