1

I have a AES/CBC encryption code written in C. I have to convert this code in C#

C Code:

EVP_CIPHER_CTX_init(&e_ctx);
err = EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, NULL);   
err = EVP_CIPHER_CTX_set_padding(&e_ctx,EVP_CIPH_NO_PADDING);    
err = EVP_EncryptUpdate(&e_ctx,cipher,&cipher_len,plain,plain_len); 
err = EVP_EncryptFinal_ex(&e_ctx, cipher+cipher_len, &f_len);

C# code:

  using (Aes aesAlg = Aes.Create())
                {
                    aesAlg.Key = key; 
                    //aesAlg.IV = IV; 
                    // Create an encryptor to perform the stream transform.
                     ICryptoTransform encryptor = aesAlg.CreateEncryptor(); 
                    // Create the streams used for encryption.
                    using (MemoryStream msEncrypt = new MemoryStream()) 
                    { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
                        { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) 
                            { 
                                //Write all data to the stream.
                                swEncrypt.Write(data); 
                            } 
                            byte[] encrypted = msEncrypt.ToArray(); 
                        } 
                    } 
                }

But in both the case I am getting different ciphertext. While the key was the same. While IV is not used in C code. So not using in c# code as well. But I doubt there is some default IV used by the OpenSSL and .net API.

jiten
  • 5,128
  • 4
  • 44
  • 73
  • Does this answer your question? [AES-256-CBC in .NET Core (C#)](https://stackoverflow.com/questions/63555145/aes-256-cbc-in-net-core-c) – Eldar May 26 '21 at 12:35
  • You need to set the mode to CBC and padding to None as the C code does. – Eldar May 26 '21 at 12:37
  • none padding will not work. will return error like input data must be in block size – jiten May 26 '21 at 12:40
  • There is a public and private key. The public key is sent with data. If you are sending serial data the public key is sometimes the beginning of the message. – jdweng May 26 '21 at 12:49
  • 1
    @jdweng This is about AES, AES only has a single secret key. Please don't confuse matters. – Maarten Bodewes May 26 '21 at 12:52
  • How about proving a full sample dataset (plaintext, key, initialization vector [maybe it's internally generated by C-code...] and resulting ciphertext? That may help us in finding a solution. Btw: the C-code is "EVP_CIPH_NO_PADDING" which means "no padding". It would the best to show a full running (even with errors) c#-example where we can see your input. – Michael Fehr May 28 '21 at 14:04

1 Answers1

2

The C and C# code differ only in the IV. In the C code, EVP_EncryptInit_ex() passes a NULL as 5th parameter, which results in a zero IV, i.e. an IV consisting only of 0x00 values. In contrast, the C# code uses a random IV created when Aes.Create() is called.

The C# code is therefore functionally identical to the C code if a zero vector is applied in the C# code. To do this, add below the line aesAlg.Key = key:

aesAlg.IV = new byte[16];

Apart from that, both codes use the same mode and the same padding:

  • Mode: In the C code, EVP_aes_256_cbc() explicitly sets the CBC mode, which is the default mode in the C# code.
  • Padding: In the C code, padding is only ostensibly disabled. EVP_CIPHER_CTX_set_padding() disables the default PKCS7 padding only if the 2nd parameter is 0. But the latter is not the case, because EVP_CIPH_NO_PADDING is defined as 0x100. So the C code uses the default PKCS7 padding, which is the default padding in the C# code.
    It is possible that the padding not being disabled in the C code is an oversight caused by the accidental use of EVP_CIPH_NO_PADDING in the context of EVP_CIPHER_CTX_set_padding(). According to the documentation, EVP_CIPH_NO_PADDING is applied in the context of EVP_CIPHER_meth_set_flags().

If the above line is added so that a zero vector is used in the C# code, the C and C# code produce the same ciphertext for identical input data on my machine.

Note, however, that a static IV, like a zero IV, is insecure. Usually a random IV is generated for each encryption, which, since it is not secret, is sent along with the ciphertext (typically concatenated).

Topaco
  • 40,594
  • 4
  • 35
  • 62