RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- From: lelteto <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Tue, 30 Jun 2009 09:13:02 -0700
1. Did you check the output sizes? While CryptEncrypt generates the plain
output, .Net may add addition info to the output block.
2. Did you check the encryption output from BOTH CAPI and .Net using the
same data, key and IV? I guess you will find the CAPI output INSIDE
(somewhere) the .NET output.
Now you "just" have to figure out - or get definitive information from
Microsoft - what other data present in the .Net output and how to interpret
that.
Laszlo Elteto
Safenet, Inc.
"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.
- References:
- Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- From: Clayton Williams
- Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- Prev by Date: Re: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- Next by Date: Need help with sending S/MIME encrypted emails using CDO in C++
- Previous by thread: Re: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
- Next by thread: Need help with sending S/MIME encrypted emails using CDO in C++
- Index(es):
Relevant Pages
|