Powershell: En- and Decrypt string with AES256

Hi,

if you have the requierment to encrypt strings in Powershell the .NET Framework offers some classes for this case. This is a symmetric encryption. Receiver and Sender uses the same Password/Key to en- and decrypt the message.

First of all you have to load two Assemblies

[System.reflection.assembly]::LoadWithPartialName("System.Security")|out-null
[System.reflection.assembly]::LoadWithPartialName("System.IO")|out-null

This is the Encrypt function. It requieres 4 Parameters.

    • aBytesToBeEncrypted => The string to as byte array
      aPasswordBytes => The password as byte array
      raEncryptedBytes => A reference to byte array to which the encrypted data is written
      aCustomSalt=> A byte array of a salt
  • function fAESEncrypt()
    {
    	Param(
    		[Parameter(Mandatory=$true)][byte[]]$aBytesToBeEncrypted,
    		[Parameter(Mandatory=$true)][byte[]]$aPasswordBytes,
    		[Parameter(Mandatory=$true)][ref]$raEncryptedBytes,
    		[Parameter(Mandatory=$false)][byte[]]$aCustomSalt
    	)		
        [byte[]] $encryptedBytes = @()
        # Salt must have at least 8 Bytes!!
        # Encrypt and decrypt must use the same salt
        # Define your own Salt here
        [byte[]]$aSaltBytes = @(4,7,12,254,123,98,34,12,67,12,122,111) 
    	if($aCustomSalt.Count -ge 1)
    	{
    		$aSaltBytes=$aCustomSalt
    	}	
        [System.IO.MemoryStream] $oMemoryStream = new-object System.IO.MemoryStream
        [System.Security.Cryptography.RijndaelManaged] $oAES = new-object System.Security.Cryptography.RijndaelManaged
        $oAES.KeySize = 256;
        $oAES.BlockSize = 128;
        [System.Security.Cryptography.Rfc2898DeriveBytes] $oKey = new-object System.Security.Cryptography.Rfc2898DeriveBytes($aPasswordBytes, $aSaltBytes, 1000);
        $oAES.Key = $oKey.GetBytes($oAES.KeySize / 8);
        $oAES.IV = $oKey.GetBytes($oAES.BlockSize / 8);
        $oAES.Mode = [System.Security.Cryptography.CipherMode]::CBC
        $oCryptoStream = new-object System.Security.Cryptography.CryptoStream($oMemoryStream, $oAES.CreateEncryptor(), [System.Security.Cryptography.CryptoStreamMode]::Write)
    	try
    	{
    		$oCryptoStream.Write($aBytesToBeEncrypted, 0, $aBytesToBeEncrypted.Length);
    		$oCryptoStream.Close();
    	}
    	catch [Exception]
    	{
    		$raEncryptedBytes.Value=[system.text.encoding]::ASCII.GetBytes("Error occured while encoding string. Salt or Password incorrect?")
    		return $false
    	}	
        $oEncryptedBytes = $oMemoryStream.ToArray();
        $raEncryptedBytes.Value=$oEncryptedBytes;
    	return $true
    }
    

    And the decrypt function, also 4 parameters are requiered

    • aBytesToDecrypt=> The byte array which holds the encrypted data
      aPasswordBytes => The password as byte array
      raDecryptedBytes=> A reference to byte array to which the decrypted data is written
      aCustomSalt=> A byte array of a salt
  • function fAESDecrypt()
    {
    	Param(
    		[Parameter(Mandatory=$true)][byte[]]$aBytesToDecrypt,
    		[Parameter(Mandatory=$true)][byte[]]$aPasswordBytes,
    		[Parameter(Mandatory=$true)][ref]$raDecryptedBytes,
    		[Parameter(Mandatory=$false)][byte[]]$aCustomSalt
    	)	
        [byte[]]$oDecryptedBytes = @();
    	# Salt must have at least 8 Bytes!!
    	# Encrypt and decrypt must use the same salt
        [byte[]]$aSaltBytes = @(4,7,12,254,123,98,34,12,67,12,122,111) 
    	if($aCustomSalt.Count -ge 1)
    	{
    		$aSaltBytes=$aCustomSalt
    	}
        [System.IO.MemoryStream] $oMemoryStream = new-object System.IO.MemoryStream
        [System.Security.Cryptography.RijndaelManaged] $oAES = new-object System.Security.Cryptography.RijndaelManaged
        $oAES.KeySize = 256;
        $oAES.BlockSize = 128;
        [System.Security.Cryptography.Rfc2898DeriveBytes] $oKey = new-object System.Security.Cryptography.Rfc2898DeriveBytes($aPasswordBytes, $aSaltBytes, 1000);
        $oAES.Key = $oKey.GetBytes($oAES.KeySize / 8);
        $oAES.IV = $oKey.GetBytes($oAES.BlockSize / 8);
        $oAES.Mode = [System.Security.Cryptography.CipherMode]::CBC
    	$oCryptoStream = new-object System.Security.Cryptography.CryptoStream($oMemoryStream, $oAES.CreateDecryptor(), [System.Security.Cryptography.CryptoStreamMode]::Write)
    	try
    	{
    		$oCryptoStream.Write($aBytesToDecrypt, 0, $aBytesToDecrypt.Length)
    		$oCryptoStream.Close()
    	}
    	catch [Exception]
    	{
    		$raDecryptedBytes.Value=[system.text.encoding]::ASCII.GetBytes("Error occured while decoding string. Salt or Password incorrect?")
    		return $false
    	}
        $oDecryptedBytes = $oMemoryStream.ToArray();
    	$raDecryptedBytes.Value=$oDecryptedBytes
    	return $true
    }
    

    And how to use it 🙂 . Define a salt and password for encryption and encrypt the string

    $aCustomSalt=@(1,2,3,4,5,6,7,9,10,11,254,253,252)
    $sPassword="A Secret Password"
    $sInput="A secret Message" 
    [byte[]]$aEncryptedMessage=$null
    fAESEncrypt ([system.text.encoding]::ASCII.GetBytes($sInput)) ([system.text.encoding]::ASCII.GetBytes($sPassword)) ([ref]$aEncryptedMessage) $aCustomSalt
    

    Decryption

    $aCustomSalt=@(1,2,3,4,5,6,7,9,10,11,254,253,252)
    $sPassword="A Secret Password"
    [byte[]]$aDecryptedMessage=$null
    fAESDecrypt $aEncryptedMessage ([system.text.encoding]::ASCII.GetBytes($sPassword)) ([ref]$aDecryptedMessage) $aCustomSalt
    write-host "Your Message:" ([System.Text.Encoding]::UTF8.GetString($aDecryptedMessage))
    

    This is it 🙂

    Michael

    2 thoughts on “Powershell: En- and Decrypt string with AES256”

    1. The encryption given here cannot be used for two reasons: firstly, as said above, there is no base64 stage to remove problems with encodings, and secondly, after encryption we see an unexpected message with the text True. Please improve the script.

    Leave a Reply