Reputation: 142
I want Encryption with C++ and WinCrypt (RSA Algorithm) Library and Decryption with C#
I do Encryption and decryption with C++ successfully, but when i want decryption, encryption text with C# Exception throw : "Error occurred while decoding OAEP padding."
following code for C++ :
void main()
{
Acqired();
Generate2048BitKeys();
ExportPrivateKey(L"privateKey.txt");
ExportPublicKey(L"publicKey.txt");
// Encrypt
ImportKey(L"publicKey.txt");
EncryptDataWriteToFile(L"New Text For Encryption...", L"encryptedData.txt");
DestroyKeys();
// Decrypt
Acqired();
ImportKey(L"privateKey.txt");
LPBYTE lpDecryptedData = NULL;
DWORD dwDataLen = 0;
DecryptDataFromFile(&lpDecryptedData, L"encryptedData.txt", &dwDataLen);
WriteBytesFile(L"decryptedData.txt", lpDecryptedData, dwDataLen);
}
void DestroyKeys()
{
if (hKey != NULL)
{
CryptDestroyKey(hKey);
hKey = NULL;
}
if (hProvider != NULL)
{
CryptReleaseContext(hProvider, 0);
hProvider = NULL;
}
}
void Acqired()
{
BOOL res = CryptAcquireContext(&hProvider, NULL, MS_ENHANCED_PROV,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
if (!res)
{
std::printf("Error Acquiring Key Context\n");
return;
}
std::printf("Key Context Acquired\n");
}
void Generate2048BitKeys()
{
const DWORD RSA2048BIT_KEY = 0x8000000;
DWORD dwParams;
dwParams = RSA2048BIT_KEY | CRYPT_EXPORTABLE | CRYPT_NO_SALT; //set the
key length to 2048 bits, allow the keys to be exported, no salt
bool res = CryptGenKey(hProvider, AT_KEYEXCHANGE, dwParams, &hKey);
if (!res)
{
printf("SERVER: Unable to generate exchange keys\n");
return;
}
printf("SERVER: Exchange keys generated\n");
}
void ExportPrivateKey(LPTSTR lpFileName)
{
if (hKey == NULL)
{
printf("Error in function 'ExportPrivateKey', hKey is NULL\n");
return;
}
DWORD dwDataLen = 0;
bool exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwDataLen);
LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen);
exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, lpKeyBlob, &dwDataLen);
WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen);
free(lpKeyBlob);
}
void ExportPublicKey(LPTSTR lpFileName)
{
if (hKey == NULL)
{
printf("Error in function 'ExportPublicKey', hKey is NULL\n");
return;
}
DWORD dwDataLen = 0;
bool exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwDataLen);
LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen);
exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, lpKeyBlob, &dwDataLen);
WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen);
free(lpKeyBlob);
}
void ImportKey(LPTSTR lpFileName)
{
if (hProvider == NULL)
{
printf("Error in function ImportKey, hProvider is NULL\n");
return;
}
if (hKey != NULL)
CryptDestroyKey(hKey);
LPBYTE lpKeyContent = NULL;
DWORD dwDataLen = 0;
ReadBytesFile(lpFileName, &lpKeyContent, &dwDataLen);
bool importResult = CryptImportKey(hProvider, lpKeyContent, dwDataLen, 0, CRYPT_OAEP, &hKey);
if (!importResult)
{
printf("Error in function ImportKey, CryptImportKey is failed\n");
return;
}
delete[] lpKeyContent;
}
void EncryptDataWriteToFile(LPTSTR lpSimpleDataToEncrypt, LPTSTR lpFileName)
{
DWORD SimpleDataToEncryptLength = _tcslen(lpSimpleDataToEncrypt) * sizeof(TCHAR);
DWORD BufferLength = SimpleDataToEncryptLength * 10;
BYTE *EncryptedBuffer = new BYTE[BufferLength];
SecureZeroMemory(EncryptedBuffer, BufferLength);
CopyMemory(EncryptedBuffer, lpSimpleDataToEncrypt,
SimpleDataToEncryptLength);
bool cryptResult = CryptEncrypt(hKey, NULL, TRUE, CRYPT_OAEP, EncryptedBuffer, &SimpleDataToEncryptLength, BufferLength);
if (!cryptResult)
{
printf("Error in function EncryptDataWriteToFile, CryptEncrypt is failed\n");
return;
}
WriteBytesFile(lpFileName, EncryptedBuffer, SimpleDataToEncryptLength);
delete[] EncryptedBuffer;
printf("Encrypt Data Successfully\n");
}
void DecryptDataFromFile(LPBYTE *lpDecryptedData, LPTSTR lpFileName, DWORD *dwDecryptedLen)
{
if (hKey == NULL)
{
printf("Error in function 'DecryptDataFromFile', hKey is NULL.\n");
return;
}
LPBYTE lpEncryptedData = NULL;
DWORD dwDataLen = 0;
ReadBytesFile(lpFileName, &lpEncryptedData, &dwDataLen);
bool decryptResult = CryptDecrypt(hKey, NULL, TRUE, CRYPT_OAEP, lpEncryptedData, &dwDataLen);
if (!decryptResult)
{
printf("Error in function 'DecryptDataFromFile', CryptDecrypt cann't be decrypted data.\n");
return;
}
printf("decrypted Successfully ... \n");
*dwDecryptedLen = dwDataLen;
*lpDecryptedData = new BYTE[dwDataLen + 1];
SecureZeroMemory(*lpDecryptedData, dwDataLen + 1);
CopyMemory(*lpDecryptedData, lpEncryptedData, dwDataLen);
delete[]lpEncryptedData;
}
void WriteBytesFile(LPTSTR lpFileName, BYTE* content, DWORD dwDataLen)
{
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0x7, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesWritten = 0;
bool result = WriteFile(hFile, content, dwDataLen, &dwBytesWritten, NULL);
CloseHandle(hFile);
}
void ReadBytesFile(LPTSTR lpFileName, BYTE **content, DWORD *dwDataLen)
{
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0x7, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileLength = 0;
DWORD dwBytesToRead = GetFileSize(hFile, NULL);
DWORD dwBytesRead = 0;
*content = new BYTE[dwBytesToRead + 1];
SecureZeroMemory(*content, dwBytesToRead + 1);
ReadFile(hFile, *content, dwBytesToRead, &dwBytesRead, NULL);
*dwDataLen = dwBytesRead;
CloseHandle(hFile);
}
and C# code is :
const int PROVIDER_RSA_FULL = 1;
const string SERVICE_PROVIDER = "Microsoft Enhanced Cryptographic Provider v1.0"; //128 bit encryption
static void Main(string[] args)
{
//var publicKey = File.ReadAllBytes("D:\\RSA\\pubkey.afp");
var privateKey = File.ReadAllBytes("D:\\RSA\\privateKey.txt");
var Data = File.ReadAllBytes("D:\\RSA\\encryptedData.txt");
RSACryptoServiceProvider rsa;
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = SERVICE_PROVIDER;
using (rsa = new RSACryptoServiceProvider(2048,cspParams))
{
rsa.ImportCspBlob(privateKey);
// ----------------------------------------------------------------------
byte[] result = rsa.Decrypt(Data, true);
Console.WriteLine(Convert.ToString(result));
}
}
Who can help me?
Upvotes: 3
Views: 2022
Reputation: 259
best way for this problems use the managed C++
create lib C++, use the lib in managed C++, and then you can use the managed file in C#
Upvotes: 2