RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- From: Dave Herrmann <DaveHerrmann@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Tue, 30 Jun 2009 16:13:01 -0700
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.
- Follow-Ups:
- RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- From: Clayton Williams
- RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- Prev by Date: Re: Problem about "csptestsuite.exe" result for "CPAcquireContext" fun
- Next by Date: Managed CSP or Smart Card mini-driver
- Previous by thread: Re: Problem about "csptestsuite.exe" result for "CPAcquireContext" fun
- Next by thread: RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- Index(es):
Relevant Pages
|