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
1 2 | [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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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
1 2 3 4 5 | $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
1 2 3 4 5 | $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.