Kae Travis

Rijndael Encryption and Decryption in C# and Powershell

This is an example of how we can perform Rijndael encryption and decryption in C# and Powershell. It’s worth mentioning that:

– salt must be 8 bytes minimum
– initVector must be 16 bytes minimum

The examples below use Cipher Block Chaining (CBC), zero padding, 10000 key iterations and 32 byte (256/8) block cipher.

Powershell:

[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null

#salt must be 8 bytes minimum
#initVector must be 16 bytes minimum

function Encrypt-String($stringToEncrypt, $passPhrase, $salt, $initVector)
{
	# Create a COM Object for RijndaelManaged Cryptography
	$rm = new-Object System.Security.Cryptography.RijndaelManaged
	$rm.Mode = [System.Security.Cryptography.CipherMode]::CBC;
	$rm.Padding = [System.Security.Cryptography.PaddingMode]::zeros;
	
	$keyIterations = 10000;
	
	# Convert the Salt to UTF Bytes
	$saltBytes = [Text.Encoding]::UTF8.GetBytes($salt)
	
	# Get string to encrypt in byte format
	$plainTextBytes = [Text.Encoding]::UTF8.GetBytes($stringToEncrypt)
	
	# Get initialisation vector byte format
	$initVectorBytes = [Text.Encoding]::UTF8.GetBytes($initVector)
	
	# Hash the user passphrase with the salt provided to create a key
	$keyBytes = (new-Object Security.Cryptography.Rfc2898DeriveBytes $passPhrase, $saltBytes, $keyIterations).GetBytes(256 / 8);
			
	# Starts the Encryption using the Key and Initialisation Vector   
	$c = $rm.CreateEncryptor($keyBytes,$initVectorBytes);
	
	# Creates a MemoryStream to do the encryption in
	$ms = new-Object IO.MemoryStream
	
	# Creates the new Cryptology Stream --> Outputs to Memory Stream
	$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"	
	
	#Writes the string in the Cryptology Stream
    	$cs.Write($plainTextBytes, 0, $plainTextBytes.Length);
    	$cs.FlushFinalBlock();
    
	#Takes the MemoryStream and puts it to an array
    	[byte[]]$cipherTextBytes = $ms.ToArray();  
	
	# Stops the Cryptology Stream
	$cs.Close()
	
	# Stops writing to Memory
	$ms.Close()
	
	# Clears the IV and HASH from memory to prevent memory read attacks
	$rm.Clear()
	
	# Takes the MemoryStream and puts it to an array
	[byte[]]$rmesult = $ms.ToArray()
	
	# Converts the array from Base 64 to a string and returns
	return [Convert]::ToBase64String($rmesult)
}

function Decrypt-String($stringToDecrypt, $passPhrase, $salt, $initVector)
{

	# Create a COM Object for RijndaelManaged Cryptography
	$rm = new-Object System.Security.Cryptography.RijndaelManaged
	$rm.Mode = [System.Security.Cryptography.CipherMode]::CBC;
	$rm.Padding = [System.Security.Cryptography.PaddingMode]::zeros;
	
	$keyIterations = 10000;
	
	$cipherTextBytes = [Convert]::FromBase64String($stringToDecrypt)
		
	# Convert the Salt to UTF Bytes
	$saltBytes = [Text.Encoding]::UTF8.GetBytes($salt)
	
	# Get initialisation vector byte format
	$initVectorBytes = [Text.Encoding]::UTF8.GetBytes($initVector)
	
	# Hash the user passphrase with the salt provided
	$keyBytes = (new-Object Security.Cryptography.Rfc2898DeriveBytes $passPhrase, $saltBytes, $keyIterations).GetBytes(256 / 8);
		
	# Starts the Decryption using the Key and Initialisation Vector
	$d = $rm.CreateDecryptor($keyBytes,$initVectorBytes)
		
	# Create a New memory stream with the encrypted value.
	$ms = new-Object IO.MemoryStream @(,$cipherTextBytes)

	# Read the new memory stream and read it in the cryptology stream
	$cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read"

	$decryptedByteCount = 0;
	
	$decryptedByteCount = $cs.Read($cipherTextBytes, 0, $cipherTextBytes.Length);
    	$cs.Close();
	
	# Stops the cryptology stream
	$cs.Close()

	# Stops the memory stream
	$ms.Close()

	# Clears the RijndaelManaged Cryptology IV and Key
	$rm.Clear()	
	
	return [Text.Encoding]::UTF8.GetString($cipherTextBytes, 0, $decryptedByteCount).TrimEnd([char]0x0000); 


}



$exampleString = "alkane"

write-host "String to encrypt is: $exampleString"

$stringToDecrypt = Encrypt-String  $exampleString "bxwD5j4LK4NEvlakuPp1g==" "JU=JVGLSFSgN4=!-LW" "H2+_=S*QFA=P!Gu_"

write-host "Encrypted is: $stringToDecrypt"

$decrypted =  Decrypt-String $stringToDecrypt "bxwD5j4LK4NEvlakuPp1g==" "JU=JVGLSFSgN4=!-LW" "H2+_=S*QFA=P!Gu_"

write-host "Decrypted is: $decrypted"

C#

using System.Security.Cryptography;

 public static string Encrypt(string plainText, string passPhrase, string salt, string initVector)
    {
        //Create instance of RijndaelManaged
        var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };

        //iterations to derive key
        int keyIterations = 10000;

        //Convert the cipher text to UTF Bytes
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        //Hash the user passphrase with the salt provided to create a key
        byte[] keyBytes = new Rfc2898DeriveBytes(passPhrase, Encoding.ASCII.GetBytes(salt), keyIterations).GetBytes(256 / 8);
      
        //Starts the Encryption using the Key and Inititalisation Vector 
        var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(initVector));

        byte[] cipherTextBytes;

        //Creates a MemoryStream to do the encryption in
        using (var memoryStream = new MemoryStream())
        {
            //Creates the new Cryptology Stream --> Outputs to Memory Stream
            using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
            {
                //Writes the string in the Cryptology Stream
                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                cryptoStream.FlushFinalBlock();
                //Takes the MemoryStream and puts it to an array
                cipherTextBytes = memoryStream.ToArray();
                cryptoStream.Close();
            }
            memoryStream.Close();
        }
        //Converts the array from Base 64 to a string and returns
        return Convert.ToBase64String(cipherTextBytes);
    }

    public static string Decrypt(string encryptedText, string passPhrase, string salt, string initVector)
    {

    
        //Create instance of RijndaelManaged
        var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };

        //iterations to derive key
        int keyIterations = 10000;

        //Convert the plain text to UTF Bytes
        byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);

        //Hash the user passphrase with the salt provided to create a key
        byte[] keyBytes = new Rfc2898DeriveBytes(passPhrase, Encoding.ASCII.GetBytes(salt), keyIterations).GetBytes(256 / 8);
    
        //Starts the Deryption using the Key and Inititalisation Vector 
        var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(initVector));

        int decryptedByteCount = 0;

        //Creates a MemoryStream to do the decryption in, with the encrypted value
        using (var memoryStream = new MemoryStream(cipherTextBytes))
        {
            //Read the new memory stream and read it in the cryptology stream
            using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
            {
                decryptedByteCount = cryptoStream.Read(cipherTextBytes, 0, cipherTextBytes.Length);
                cryptoStream.Close();
            }
            memoryStream.Close();
        }

        return Encoding.UTF8.GetString(cipherTextBytes, 0, decryptedByteCount).TrimEnd('\0');

    }

and call using:

 string encryptedString = Encrypt("alkane", "bxwD5j4LK4NEvlakuPp1g==", "JU=JVGLSFSgN4=!-LW", "H2+_=S*QFA=P!Gu_");
 string decryptedString = Decrypt(encryptedString , "bxwD5j4LK4NEvlakuPp1g==", "JU=JVGLSFSgN4=!-LW", "H2+_=S*QFA=P!Gu_");
Rijndael Encryption and Decryption in C# and Powershell
Rijndael Encryption and Decryption in C# and Powershell

2 thoughts on “Rijndael Encryption and Decryption in C# and Powershell

  1. Hello Kae,

    thanks for this nice piece of code.

    When i use the c# Function to encrypt and use the Powershell Function to decrypt, i get a Result like this “�V��m�8�”. Vice versa is the same.

    Where is my fault?

    Kind Regards

Leave a Reply to Matze Cancel reply