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.