RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged




We have the same situation as you. A .NET app and a C++ app that both need to
encrypt and decrypt the same data. One thing we found is that the encryption
seeds for the .NET app need to be 7-bit ASCII, whereas the seeds used by the
C++ app can be binary if you want. So, if you are using binary seed values
(8-bit bytes), then the .NET app may not be encrypting/decrypting the same
way. In our case, I don't remember if the .NET app would fail or just not
encrypt/decrypt to the same values.

-Dave

"Clayton Williams" wrote:

I have library that generates encrypted strings using 256-bit RijndaelManaged
in a .NET library.

I am trying to write a Win32 app that can decrypt that string using the
Crypto APIs.

I can get both to encrypt and decrypt successfully in their own projects,
but I have been unable to get the Win32 based CryptDecrypt algorithm to
successfully decrypt the RijndaelManaged encrypted string.

I am using the same Key and IV for each one, the same string, etc. As far
as I can tell, I am using the same Padding, bit size, algorithm.

This whole post boils down to 2 questions that someone may have already
resolved in a similar scenario:

1) Is it easier to write one unmanaged C++ library source that both
applications share, with a managed wrapper in the .NET assembly that all use
the Win32 Crypto library, or:
2) Is there some tweak that I am missing that will enable me to decrypt my
.NET encrypted strings in CryptDecrypt?

I have listed code from apps to illustrate where I am. The resultant byte
arrays from both encryptions are different, and plugging in the byte array
from one into the other will not decrypt - NTE_BAD_DATA

Here is my .NET code:

/////////////////////////////////////////////////
Byte[] key = { 0x74, 0x6c, 0x9b, 0xf2, 0x24, 0xce, 0xdd, 0x55, 0x23, 0xba,
0x64, 0xfb, 0xe9, 0xbe, 0x17, 0x32, 0xcf, 0xf5, 0xe3, 0xf6, 0x18, 0xc0, 0x1f,
0xd5, 0x64, 0x5d, 0x84, 0xc1, 0x1a, 0xc8, 0x71, 0x7c };

Byte[] IV = { 0x18, 0x13, 0xb1, 0xb3, 0x26, 0x2b, 0x80, 0xd1, 0xe, 0x80,
0x9f, 0x47, 0xa0, 0xd9, 0x6c, 0x1f, 0xcd, 0x42, 0x1f, 0x33, 0xa9, 0x8e, 0x2f,
0x66, 0x68, 0xcf, 0x7d, 0xd6, 0x58, 0x57, 0xf2, 0xaa };

System.Security.Cryptography.RijndaelManaged rm = new
System.Security.Cryptography.RijndaelManaged();

rm.KeySize = 256;
rm.BlockSize = 256;
rm.Padding = PaddingMode.PKCS7; // default
rm.Key = key;
rm.IV = IV;

string toEncrypt = "String To Encrypt";

byte []plainTextBytes = Encoding.UTF8.GetBytes(toEncrypt);
ICryptoTransform ict = rm.CreateEncryptor();

byte []encrBytes = ict.TransformFinalBlock(plainTextBytes, 0,
plainTextBytes.Length);

string result = Convert.ToBase64String(encrBytes);

byte []dBytes = Convert.FromBase64String(result);
ICryptoTransform ict2 = rm.CreateDecryptor();
byte[] decryptedBytes = ict2.TransformFinalBlock(encrBytes, 0,
encrBytes.Length);
string plainText = Encoding.UTF8.GetString(decryptedBytes);

///////////////////////////////////////////

Here is my C++ code:

struct CryptoBlob {
BLOBHEADER header;
DWORD cbKeySize;
BYTE rgbKeyData [32];
} keyBlob;

..... <skipping _tmain initialization>

keyBlob.header.bType = PLAINTEXTKEYBLOB;
keyBlob.header.bVersion = CUR_BLOB_VERSION;
keyBlob.header.reserved = 0;
keyBlob.header.aiKeyAlg = CALG_AES_256;
keyBlob.cbKeySize = 32; // has to be in bytes, not bits

BYTE keyData[32] = { 0x74, 0x6c, 0x9b, 0xf2, 0x24, 0xce, 0xdd, 0x55, 0x23,
0xba, 0x64, 0xfb, 0xe9, 0xbe, 0x17, 0x32, 0xcf, 0xf5, 0xe3, 0xf6, 0x18, 0xc0,
0x1f, 0xd5, 0x64, 0x5d, 0x84, 0xc1, 0x1a, 0xc8, 0x71, 0x7c };

BYTE ivData[32] = { 0x18, 0x13, 0xb1, 0xb3, 0x26, 0x2b, 0x80, 0xd1, 0xe,
0x80, 0x9f, 0x47, 0xa0, 0xd9, 0x6c, 0x1f, 0xcd, 0x42, 0x1f, 0x33, 0xa9, 0x8e,
0x2f, 0x66, 0x68, 0xcf, 0x7d, 0xd6, 0x58, 0x57, 0xf2, 0xaa };

for (int idx = 0; idx < 32; idx++)
{
keyBlob.rgbKeyData[idx] = keyData[idx];
}

HCRYPTKEY hPubKey;
HCRYPTPROV hProv;
DWORD dwBlobLen;
DWORD errVal;

if (!CryptAcquireContext(
&hProv,
NULL,
NULL,
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT))
{
errVal = GetLastError();
ErrLookup(errVal);
if (NTE_BAD_KEYSET == errVal)
{
if (!CryptAcquireContext(
&hProv,
_T("NVCryptoTestContainer"),
MS_ENHANCED_PROV,
PROV_RSA_AES,
CRYPT_NEWKEYSET |

CRYPT_VERIFYCONTEXT))
{
errVal = GetLastError();
ErrLookup(errVal);
printf("Error in AcquireContext 0x%08x \n", errVal);
return 1;
}

}
}
else
{
if (CryptImportKey(hProv, (const LPBYTE)&keyBlob, sizeof(keyBlob), 0, 0,
&hPubKey))
{
if (!CryptSetKeyParam(hPubKey, KP_IV, ivData, 0))
{
ErrLookup(GetLastError());
}
else
{
char szClearText[32];
strcpy(szClearText, "String To Encrypt");

DWORD dwDataLen = (DWORD)strlen(szClearText);
DWORD dwBufferSize = sizeof(szClearText);

if(!CryptEncrypt(hPubKey, 0, TRUE, 0, (LPBYTE)szClearText,
&dwDataLen, dwBufferSize))
{
ErrLookup(GetLastError());
}
else
{
printf("encrypted looks like: %s", szClearText);
dwBufferSize = sizeof(szClearText);
if(!CryptDecrypt(hPubKey, 0, TRUE, 0, (LPBYTE)zClearText, &dwBufferSize))
{
ErrLookup(GetLastError());
}
else
{
printf("decrypted looks like: %s", szClearText);
}
}
}

if(!CryptDestroyKey(hPubKey))
{
ErrLookup(GetLastError());
}
}
else
{
ErrLookup(GetLastError());
}
}


Any help is GREATLY appreciated.
.



Relevant Pages

  • RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
    ... I figured out how to use RijndaelManaged with AES in the C++ app. ... C++ crypto WILL successfully decrypt the .NET generated ... I am trying to write a Win32 app that can decrypt that string using the ... I can get both to encrypt and decrypt successfully in their own projects, ...
    (microsoft.public.platformsdk.security)
  • Re: Encrypt and Decrypt a file using .NET 2.0?
    ... public static string GenerateKey() ... DES des = DES.Create; ... // Distribute this key to the user who will decrypt this file. ... // Get the Key for the file to Encrypt. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: .NET Crypto Classes Interoperability with Win32 Crypto APIs
    ... >the hash of the string you are feeding in. ... when i encrypt a string using .NET classes and try ... >> decrypt it using Win32 APIs, ...
    (microsoft.public.dotnet.security)
  • Re: Encrypt and Decrypt a file using .NET 2.0?
    ... public static string GenerateKey() ... using (CryptoStream cryptoStream = new CryptoStream(outFile, ... // Distribute this key to the user who will decrypt this file. ... // Get the Key for the file to Encrypt. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Decryptionfailed to bring original text back....
    ... cryptography, but now using them on web.config, any idea, I like to ... There isn't really much reason to encrypt a .NET string with ... what happen when you decrypt the encrypted ...
    (microsoft.public.dotnet.security)