Click here to Skip to main content
15,892,809 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,

I want to encrypt file in c or c++ and decrypt it in c# by using Rijndael algorithm.

C# app decrypt the file but not showing correct output: it shows junk chars only.

c code :
C++
void main()
{
 CRijndael oRijndael;
  oRijndael.MakeKey("512345678901234561234567890123456", CRijndael::sm_chain0,32,16);
  char szDataIn1[49] = "sunil pol";
  char szDataIn[49];
  char szDataOut[49];
  memset(szDataIn, 0, 49);
  memset(szDataOut, 0, 49);

  //Test ECB
  strcpy(szDataIn, szDataIn1);
  memset(szDataOut, 0, 49);
  oRijndael.Encrypt(szDataIn, szDataOut, 48, CRijndael::ECB);
  cout << szDataOut << endl;
  FILE *fp =NULL ;
 fp = fopen("F:\\Encoding and Decoding\\CEncrypt.txt","ab+") ;
 fwrite(szDataOut,strlen(szDataOut),1,fp);
 fclose(fp) ;
  memset(szDataIn, 0, 49);
  oRijndael.Decrypt(szDataOut, szDataIn, 48, CRijndael::ECB);
  cout << szDataIn << endl;*/

}

.Net code :

C#
public static void Decrypt()
        {
            string password = @"512345678901234561234567890123456"; //Your Key Here

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c });

            FileStream fsCrypt = new FileStream(@"F:\Encoding and Decoding\CEncrypt.txt", FileMode.Open);

            RijndaelManaged RMCrypto = new RijndaelManaged();
            RMCrypto.Mode=CipherMode.ECB;
            RMCrypto.Padding = PaddingMode.None;
            RMCrypto.KeySize = 256;
            RMCrypto.BlockSize = 128;
            
            byte[] key = pdb.GetBytes(RMCrypto.KeySize / 8);
            byte[] iv = pdb.GetBytes(RMCrypto.BlockSize /8);         

            CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateDecryptor(key, iv), CryptoStreamMode.Read);
         //   CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateDecryptor(), CryptoStreamMode.Read);


            FileStream fsOut = new FileStream(@"F:\Encoding and Decoding\ReadMe_Decrypted.txt", FileMode.Create);

            int data;
            while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);

            fsOut.Close();
            cs.Close();
            fsCrypt.Close();
        }


Could you help me finding what is happening here?

Thank you in advance.
Posted
Updated 9-Aug-12 22:06pm
v2

Without knowing anything about the C# implementation of Rijndael, I see a couple things that caught my attention:

a) The writing of the encrypted text is done incorrectly:

fwrite(szDataOut,strlen(szDataOut),1,fp);


szDataOut is not a NUL-terminated character string, but binary data. Hence you cannot determine its length by strlen. You probably want to write the entire block in its full length.

b) The ouput file is opened with mode "ab+", hence you will be appending to the file each time you run your test application. You probably want "wb" instead.

c) The key generation operates on 8-bit per character string on the C++ side and on a Unicode string on the C# side. I am not sure, whether both algorithms will arrive at the same binary key value.

Hope that helps.
 
Share this answer
 
v2
Comments
sunil pol 10-Aug-12 5:18am    
I think key generated by both program may be different..If anybody knows another encryption algorithm which works on c & c# platform then please suggest...
nv3 10-Aug-12 5:27am    
Why switch the encryption algorithm when the problem is the key generation? Just make sure that you have the same key on either side. You probably can export the binary key from the C++ side and import it on the C# side.

If that isn't possible, then use a Unicode key on your C++ side as well. That might help. If you have the source code, look how the key generator produces the key on the C++ side and C# side. That will give you a clue as what to do.

Btw.: Other ciphers will have the same problem.

sunil pol 10-Aug-12 6:17am    
in c++ code i didn't find any variable in which key is stored....according to password & rounds it will create key ..

code :

//Encryption (m_Ke) round key
int m_Ke[MAX_ROUNDS+1][MAX_BC];
//Decryption (m_Kd) round key
int m_Kd[MAX_ROUNDS+1][MAX_BC];
void CRijndael::MakeKey(char const* key, char const* chain, int keylength, int blockSize)
{
if(NULL == key)
throw exception("Empty key");
if(!(16==keylength || 24==keylength || 32==keylength))
throw exception("Incorrect key length");
if(!(16==blockSize || 24==blockSize || 32==blockSize))
throw exception("Incorrect block length");
m_keylength = keylength;
m_blockSize = blockSize;
//Initialize the chain
memcpy(m_chain0, chain, m_blockSize);
memcpy(m_chain, chain, m_blockSize);
//Calculate Number of Rounds
switch(m_keylength)
{
case 16:
m_iROUNDS = (m_blockSize == 16) ? 10 : (m_blockSize == 24 ? 12 : 14);
break;

case 24:
m_iROUNDS = (m_blockSize != 32) ? 12 : 14;
break;

default: // 32 bytes = 256 bits
m_iROUNDS = 14;
}
int BC = m_blockSize / 4;
int i, j;
for(i=0; i<=m_iROUNDS; i++)
{
for(j=0; j> 16) & 0xFF] & 0xFF) << 24 ^
(sm_S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^
(sm_S[ tt & 0xFF] & 0xFF) << 8 ^
(sm_S[(tt >> 24) & 0xFF] & 0xFF) ^
(sm_rcon[rconpointer++] & 0xFF) << 24;
if(KC != 8)
for(i=1, j=0; i> 8) & 0xFF] & 0xFF) << 8 ^
(sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^
(sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24;
for(j = KC/2, i=j+1; i> 24) & 0xFF] ^
sm_U2[(tt >> 16) & 0xFF] ^
sm_U3[(tt >> 8) & 0xFF] ^
sm_U4[tt & 0xFF];
}
m_bKeyInit = true;
}
nv3 10-Aug-12 10:03am    
There are several issues. For one, the source code on the article page of George Anescu deviates from what you show here. You might have old code and actually the code shown in your post does not use the given key at all.

Then, the class implementation of CRijndael and its MakeKey function does not necessarly produce the same session key as the Rfc2898DeriveBytes function in your C# code.

Further, on the C++ side you are giving a salt of all 0 bytes, while on the C# you are specifying a different salt of 16 non-zero bytes. Hence, that can never produce the same session key.

And please look after the strcpy problem in your C++ code. That will not work either.

First try to get encyption and decryption working on your C++ side alone. Then try to decrypt on the C# side.
Here is my suggestions (not the solution):

1. dotNET operate with unicode strings by default, so in your C++ code try to encode not CHAR but WCHAR.

2. dotNET uses Crypt API wrapping inside their implementation of encoding/decoding (not only AES for for other algorithms too), so you can try using Crypt API in your C++ app, or make managed wrapper for few functions in Crypt API and use them in managed code too, so this way you will be sure that code is similar.

Regards,
Maxim.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900