Ok, So my code is listed below. I'm not sure where to put the iv value
for the C++ portion:
I'm trying to encrypt a piece of information (a string of text from an
..INI file) on the server side (C# .net) and pass that information to
the client side app which has to decrypt it. I'm trying to use (in c#)
the System.Security.Cryptography and in c++ the wincrypt.h file. I'm
not sure if this is possible (although I believe it is); so I was
wondering if anybody had any ideas?
The C# Server Code:
// -----------------------------------------------------------
// ENCRYPT (C# SERVER SIDE)
// -----------------------------------------------------------
using System.Security.Cryptography;
private string Encrypt_Try2(string strKey, string strText)
{
PasswordDeriveBytes cdk = new PasswordDeriveBytes(strKey, null);
// generate an RC2 key
byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] key = cdk.CryptDeriveKey("RC2", "MD5", 128, iv);
Console.WriteLine(key.Length * 8);
// setup an RC2 object to encrypt with the derived key
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = key;
rc2.IV = new byte[] { 21, 22, 23, 24, 25, 26, 27, 28};
// now encrypt with it
byte[] plaintext = Encoding.UTF8.GetBytes(strText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, rc2.CreateEncryptor(),
CryptoStreamMode.Write);
cs.Write(plaintext, 0, plaintext.Length);
cs.Close();
byte[] encrypted = ms.ToArray();
// Convert to Base64
string txtOut = Convert.ToBase64String(encrypted);
// THIS IS THE ENCRYPTED TEXT
return txtOut;
}
// -----------------------------------------------------------
// DECRYPT (FOR VERIFICATION - (C# SERVER SIDE))
// -----------------------------------------------------------
private string Decrypt_Try2(string strKey, string strText)
{
PasswordDeriveBytes cdk = new PasswordDeriveBytes(strKey, null);
// generate an RC2 key
byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] key = cdk.CryptDeriveKey("RC2", "MD5", 128, iv);
Console.WriteLine(key.Length * 8);
// setup an RC2 object to encrypt with the derived key
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = key;
rc2.IV = new byte[] { 21, 22, 23, 24, 25, 26, 27, 28};
// now encrypt with it
//byte[] plaintext = Encoding.UTF8.GetBytes(strText);
byte[] plaintext = Convert.FromBase64String(strText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, rc2.CreateDecryptor(),
CryptoStreamMode.Write);
cs.Write(plaintext, 0, plaintext.Length);
cs.Close();
byte[] encrypted = ms.ToArray();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
// THIS IS THE DECRYPTED TEXT
return encoding.GetString(encrypted);
//this.txtOut.Text = txtOut;
}
// -----------------------------------------------------------
// DECRYPT (C++ CLIENT SIDE)
// -----------------------------------------------------------
CString CJCrypt:
ecrypt(char *key, char *txtOut)
{
char *szPassword = key;
CBase64Utils bu;
int iTxtOutLen = strlen(txtOut);
char *result = bu.Decode(txtOut, &iTxtOutLen);
DWORD dwBufLen = 1+strlen(result);
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTHASH hHashKey;
DWORD sts=0;
DWORD errc = 0;
sts = CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV,
PROV_RSA_FULL, 0);
if(sts == 0) errc=GetLastError();
sts = CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHashKey);
if(sts == 0) errc=GetLastError();
sts = CryptHashData(hHashKey, (BYTE *)szPassword,
strlen(szPassword), 0);
if(sts == 0) errc=GetLastError();
//sts = CryptDeriveKey(hCryptProv, CALG_DES, hHashKey, (56)<<16,
&hKey);
sts = CryptDeriveKey(hCryptProv, CALG_RC2, hHashKey, 128, &hKey);
//sts = CryptDeriveKey(hCryptProv, CALG_3DES, hHashKey, (168)<<16,
&hKey);
//sts = CryptDeriveKey(hCryptProv, CALG_RC4, hHashKey, (56)<<16,
&hKey);
if(sts == 0) errc=GetLastError();
DWORD dwCryptBuffLen = dwBufLen;
sts = CryptEncrypt(hKey,0,TRUE,0,NULL,&dwCryptBuffLen,0);
BYTE *bCryptoBuffer = new BYTE[dwCryptBuffLen];
memset(bCryptoBuffer,0,dwCryptBuffLen);
memcpy(bCryptoBuffer,result,dwBufLen + 3);
sts = CryptDecrypt(hKey, 0, TRUE,0,(BYTE *)result,
&dwCryptBuffLen);
if(sts == 0) errc=GetLastError();
// else do something with the dwBufLen bytes of encrypted data in
bCryptoBuffer
sts = CryptDestroyKey(hKey);
sts = CryptDestroyHash(hHashKey);
sts = CryptReleaseContext(hCryptProv, 0);
CString strOut;
strOut.Format("%s", result);
return strOut;
}
// -----------------------------------------------------------
// ENCRYPT (FOR VERFICATION - (C++ CLIENT SIDE))
// -----------------------------------------------------------
CString CJCrypt::Encrypt(char *key, char *txtIn)
{
char *szPassword = key;
DWORD dwBufLen = 1+strlen(txtIn);
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTHASH hHashKey;
DWORD sts=0;
DWORD errc = 0;
sts = CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV,
PROV_RSA_FULL, 0);
if(sts == 0) errc=GetLastError();
sts = CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHashKey);
if(sts == 0) errc=GetLastError();
sts = CryptHashData(hHashKey, (BYTE *)szPassword,
strlen(szPassword), 0);
if(sts == 0) errc=GetLastError();
//sts = CryptDeriveKey(hCryptProv, CALG_DES, hHashKey, (56)<<16,
&hKey);
sts = CryptDeriveKey(hCryptProv, CALG_RC2, hHashKey, 128, &hKey);
//sts = CryptDeriveKey(hCryptProv, CALG_3DES, hHashKey, (168)<<16,
&hKey);
//sts = CryptDeriveKey(hCryptProv, CALG_RC4, hHashKey, (56)<<16,
&hKey);
if(sts == 0) errc=GetLastError();
DWORD dwCryptBuffLen = dwBufLen;
sts = CryptEncrypt(hKey,0,TRUE,0,NULL,&dwCryptBuffLen,0);
BYTE *bCryptoBuffer = new BYTE[dwCryptBuffLen];
memset(bCryptoBuffer,0,dwCryptBuffLen);
memcpy(bCryptoBuffer,txtIn,dwBufLen);
sts = CryptEncrypt(hKey, 0, TRUE, 0, bCryptoBuffer, &dwBufLen,
dwCryptBuffLen);
// Convert To Base64
CBase64Utils bu;
char *result = bu.Encode((char *)bCryptoBuffer, dwBufLen + 1);
if(sts == 0) errc=GetLastError();
// else do something with the dwBufLen bytes of encrypted data in
bCryptoBuffer
sts = CryptDestroyKey(hKey);
sts = CryptDestroyHash(hHashKey);
sts = CryptReleaseContext(hCryptProv, 0);
CString strOut;
strOut.Format("%s", result);
return strOut;
}
Both the c# and c++ encrypt/decrypt work with them selves (i.e. I can
encrypt and decrypt things using only the c++ OR the C#, but I cannot
encrypt with C# and decrypt with C++). I'm not sure this is possible
and I just don't have the parameters set up correctly; or if they use
completely separate algorythms and will not work.
Does anybody have any idea?
Thank you very much
J,
Sure you can. The classes in the System.Security.Cryptography namespace
use well established algorithms to encrypt/decrypt information. You just
have to use the same algorithms in your C++ code (which are supported, by
the way), along with the same key and iv values for encryption/decryption.
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)
I need to encode some information on the server side using ASP.NET with
C#; sending via HTTP to a client side application, that needs to be
decoded in an MFC C++ application.
I'm not sure if I can encode something using:
C#: System.Security.Cryptography (to encode)
and
C++: wincrypt.h (to decode)
Does anybody have any idea about this? Thank you in advance; it is
greatly appreciated.
J