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
Real nice examle, but can not handle full ASCII. é € åäö etc. all gives ???
You could base64 encode the data before you AES encrypt it, avoiding the issues with ASCII/UTF-8 support… or the lack there-of.
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.