C# How SHA256Managed is working

T.Zacks 3,986 Reputation points
2022-01-21T17:42:19.34+00:00

please have a look at three routine which encrypt data. first this function OpenSSLEncrypt() is calling and from here DeriveKeyAndIV() & EncryptString() is getting called.

please tell me what is iv and what it does because code is encrypting with passphrase then why iv is required?

Array.Copy(key, 0, aesKey, 0, 32);
why two array provided in Copy() function ?
why 32 is used? it could 50 or 60 anything. how this Array.Copy(key, 0, aesKey, 0, 32); line is working?

please guide. thanks

        public static string OpenSSLEncrypt(string plainText, string passphrase, string ivStr)
        {
            byte[] key, iv;
            DeriveKeyAndIV(passphrase, ivStr, out key, out iv);
            return EncryptString(plainText, key, iv);
        }

        private static void DeriveKeyAndIV(string passphrase, string ivStr, out byte[] key, out byte[] iv)
        {
            key = new byte[32];
            var sha = new SHA256Managed();
            byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(passphrase));
            Array.Copy(hash, 0, key, 0, 32);
            iv = Encoding.ASCII.GetBytes(ivStr.Substring(0, 16));
        }


 private static string EncryptString(string plainText, byte[] key, byte[] iv)
        {
            // Instantiate a new Aes object to perform string symmetric encryption
            Aes encryptor = Aes.Create();

            encryptor.Mode = CipherMode.CBC;

            // Set key and IV
            byte[] aesKey = new byte[32];
            Array.Copy(key, 0, aesKey, 0, 32);
            encryptor.Key = aesKey;
            encryptor.IV = iv;

            // Instantiate a new MemoryStream object to contain the encrypted bytes
            MemoryStream memoryStream = new MemoryStream();

            // Instantiate a new encryptor from our Aes object
            ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();

            // Instantiate a new CryptoStream object to process the data and write it to the 
            // memory stream
            CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);

            // Convert the plainText string into a byte array
            byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);

            // Encrypt the input plaintext string
            cryptoStream.Write(plainBytes, 0, plainBytes.Length);

            // Complete the encryption process
            cryptoStream.FlushFinalBlock();

            // Convert the encrypted data from a MemoryStream to a byte array
            byte[] cipherBytes = memoryStream.ToArray();

            // Close both the MemoryStream and the CryptoStream
            memoryStream.Close();
            cryptoStream.Close();

            // Convert the encrypted byte array to a base64 encoded string
            string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);

            // Return the encrypted data as a string
            return cipherText;
        }
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. P a u l 10,496 Reputation points
    2022-01-21T18:09:42.823+00:00

    The IV (initialisation vector) is relevant when you're encrypting multiple blocks using a single symmetric algorithm instance. Without an IV if you encrypt two identical blocks using the same instance in theory you would end up with two identical outputs. This introduces the possibility of the deciphered text & even the key being derivable.
    When encrypting a block using one of the framework-provided symmetric encryption algorithms (derived from SymmetricAlgorithm) the previous block that was encrypted from that instance will become an input of the next blocks encrypted output, creating a chain of blocks all dependent on their previous blocks. The IV in that case is used to seed the first block.
    The IV parameter is mandatory and when you create an algorithm instance it'll generate one for you, so if you don't overwrite the value with your own IV then you'll want to record the generated one if your intention is to be able to decrypt the payload.
    This paragraph explains the details:
    https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.symmetricalgorithm.iv?view=net-6.0#remarks

    Edit: Sorry just saw your second question. The reason why the key is 32 in length is because you're generating a random hash to use as your key (using the SHA256 hashing algorithm.) SHA256 gives you a 256 bit hash value as a response, and 256 bits is 32 bytes.