jiten
jiten

Reputation: 5264

Equivalent AES encryption code in c# .net core

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.

Upvotes: 1

Views: 1744

Answers (1)

Topaco
Topaco

Reputation: 49121

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).

Upvotes: 3

Related Questions