Skip to content

Instantly share code, notes, and snippets.

@ctigeek
Last active March 25, 2024 23:16
Show Gist options
  • Star 45 You must be signed in to star a gist
  • Fork 19 You must be signed in to fork a gist
  • Save ctigeek/2a56648b923d198a6e60 to your computer and use it in GitHub Desktop.
Save ctigeek/2a56648b923d198a6e60 to your computer and use it in GitHub Desktop.
Aes Encryption using powershell.
function Create-AesManagedObject($key, $IV) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Create-AesKey() {
$aesManaged = Create-AesManagedObject
$aesManaged.GenerateKey()
[System.Convert]::ToBase64String($aesManaged.Key)
}
function Encrypt-String($key, $unencryptedString) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
$aesManaged = Create-AesManagedObject $key
$encryptor = $aesManaged.CreateEncryptor()
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
[byte[]] $fullData = $aesManaged.IV + $encryptedData
$aesManaged.Dispose()
[System.Convert]::ToBase64String($fullData)
}
function Decrypt-String($key, $encryptedStringWithIV) {
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
$IV = $bytes[0..15]
$aesManaged = Create-AesManagedObject $key $IV
$decryptor = $aesManaged.CreateDecryptor();
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
$aesManaged.Dispose()
[System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}
$key = Create-AesKey
$key
$unencryptedString = "blahblahblah"
$encryptedString = Encrypt-String $key $unencryptedString
$backToPlainText = Decrypt-String $key $encryptedString
@smittix
Copy link

smittix commented Apr 9, 2016

How would you decrypt using this?

@ctigeek
Copy link
Author

ctigeek commented Apr 11, 2016

@smittix
Did you try the Decrypt-String function?

I just tested it and it worked for me:
http://pastebin.com/Yt2tpiDY

@djcasl
Copy link

djcasl commented Aug 24, 2016

Thanks for this incredible base, I did make some mods for my own purposes.

Line 9 $aesManaged.IV = [System.Convert]::FromBase64String($IV) to $aesManaged.IV = [Text.Encoding]::UTF8.GetBytes($IV)
Got an error with systemconvert
Line 17 $aesManaged.Key = [System.Convert]::FromBase64String($key) to $aesManaged.Key = [Text.Encoding]::UTF8.GetBytes($key)
Same reason

And basically this script will generate a new key everytime since you are not using a steady Init vector.
So this wil only decrypt your encrypted string in the same PS session, moment you close this, you cannot decrypt anymore.

Just to let you know.

Still many thanks, you helped me a lot.

@thanosazlin
Copy link

thanosazlin commented Sep 21, 2017

@djcasl... i'm new to ecryption, but i have encrypted via a .net application using AES, which i am looking for a way to decrypt a string that was encrypted AES in .net from powershell.. how would i use the above code just the decrypt part, to decrypt my string from .net if i know the password and salt i am using from .net ?

btw here is the .net code i'm using, from cipher_utility.cs https://bitlush.com/blog/symmetric-encryption-in-c-sharp , see AES example..

public static string Encrypt<T>(string value, string password, string salt)
             where T : SymmetricAlgorithm, new()
        {
            DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));

            SymmetricAlgorithm algorithm = new T();

            byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
            string test = Encoding.UTF8.GetString(rgbKey);

            ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIV);

            using (MemoryStream buffer = new MemoryStream())
            {
                using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
                {
                    using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
                    {
                        writer.Write(value);
                    }
                }

                return Convert.ToBase64String(buffer.ToArray());
            }
        }

@arruw
Copy link

arruw commented Jan 8, 2018

@thanosazlin I have similar problem, have you found the solution?

Thanks!

@wbrianwhite
Copy link

@djcasl... i'm new to ecryption, but i have encrypted via a .net application using AES, which i am looking for a way to decrypt a string that was encrypted AES in .net from powershell.. how would i use the above code just the decrypt part, to decrypt my string from .net if i know the password and salt i am using from .net ?

btw here is the .net code i'm using, from cipher_utility.cs https://bitlush.com/blog/symmetric-encryption-in-c-sharp , see AES example..

public static string Encrypt<T>(string value, string password, string salt)
             where T : SymmetricAlgorithm, new()
        {
            DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));

            SymmetricAlgorithm algorithm = new T();

            byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
            byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
            string test = Encoding.UTF8.GetString(rgbKey);

            ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIV);

            using (MemoryStream buffer = new MemoryStream())
            {
                using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
                {
                    using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
                    {
                        writer.Write(value);
                    }
                }

                return Convert.ToBase64String(buffer.ToArray());
            }
        }

With something like that with callouts to other functions etc, probably the easiest is to have your powershell do something like

[System.Reflection.Assembly]::LoadFrom("C:\Apps\MyApp\MyLibrary.dll") $foo = [MyLibrary.MyCrypt]::Decrypt("encryptedValue", "password", "salt")

@djcasl
Copy link

djcasl commented Dec 18, 2019

Didn't know anyone was still using / reading this.
My last comment was from three years ago, but now there should be way better ways to do this.
My Script that uses this, still works though.

Usage is basically:
$encryptedString = Encrypt-String $key $unencryptedString
$backToPlainText = Decrypt-String $key $encryptedString

Things you should keep in mind, that Padding is very important. The padding used here is:
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
I on the other hand use $aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
More info on padding

If I would use this code now, I would rebuild the top like:
function Create-AesManagedObject
{
Param
(
#Dont's declare Key and IV type so you can use anything (dirty powershelling)
$key,
$IV,
#I Declared an IV Const byte array variable before this function
[string] $Mode = "CBC",
[string]$Padding = "PKCS7",
[int] $BSize = 128,
[int] $MKeySize = 256
)

$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::$Mode
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::$Padding
$aesManaged.BlockSize = $BSize
$aesManaged.KeySize = $MKeySize

This Part I changes as well
if ($IV) {
if ($IV.getType().Name -eq "String") {
#was $aesManaged.IV = [System.Convert]::FromBase64String($IV)
$aesManaged.IV = [Text.Encoding]::UTF8.GetBytes($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
#was $aesManaged.Key = [System.Convert]::FromBase64String($key)
$aesManaged.Key = [Text.Encoding]::UTF8.GetBytes($key)
}
else {
$aesManaged.Key = $key
}

Last note:
I would also put al these functions in a seperate module now. To keep the main code cleaner, but that is also up to you
Easiest way I do this.
$custommodule = \FULLPath\modulename.psm1"
Import-Module -DisableNameChecking $custommodule

@wbrianwhite
Copy link

Thanks for the reply 😀
We had a choco package that depended on another choco package that installed a dotNet console app to do encryption, but had some issues when the dependency resolution in some cases, so we were looking for a simple way to do encryption directly in the chocoInstall.ps1.

@djcasl
Copy link

djcasl commented Dec 19, 2019

@wbrianwhite Glad I could help, good luck with your scriptwork.

@Zorahn
Copy link

Zorahn commented Mar 2, 2020

Hey, just tried your functions today, and thanks, looks great. Good job

I did, however get an error after updating with your latest notes. The size of the key is invalid when I use $aesManaged.Key = [Text.Encoding]::UTF8.GetBytes($key) , but when I switch back to FromBase64String it works..

Pretty new to this whole encryption thing, so no idea why, but probably something I've forgotten.. Anyway, works with the first part.

@djcasl
Copy link

djcasl commented Mar 2, 2020

@Zorahn , might have something to do with the characterset you are using. But that is the main reason when I make changes like this, I always put the old stuff in the comments. Please note I am not the original creator of this Example so all credits go to @ctigeek

Glad it works for you, Encryption is a very tricky thing. It took me a while as well to get it working for my purpose.

@D3vil0p3r
Copy link

D3vil0p3r commented Jun 27, 2021

Very nice project in PowerShell.
As block cipher mode, I see that we can only use the following: CBC,ECB,OFB,CFB,CTS.
How can we implement the GCM in this code?

@D3vil0p3r
Copy link

@alan-null
Copy link

@D3vil0p3r I created AES+GCM wrapper for my own purposes

You might find this helpful:
https://github.com/PowerShellLibrary/Crypto.AES

@D3vil0p3r
Copy link

@D3vil0p3r I created AES+GCM wrapper for my own purposes

You might find this helpful: https://github.com/PowerShellLibrary/Crypto.AES

Thank you @alan-null I appreciate this. I will give a look to it in the next days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment