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_");
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