Powershell: Working with AES encryption – Part 1
Powershell PowershellSometimes there is a requirement to run a PowerShell script that may use credentials, whilst it’s always bad to embed these credentials in your script, there are a number of ways to tackle this, one being the use of an AES key and encrypted credentials or using a secret store (like Azure key vault or a local vault). In this article I will cover the use of an AES key, and encryption of creds for use in multiple places. This has an advantage over standard methods of encrypting creds for use on a single machine / user whereby in that scenario move the encrypted creds won’t work on another machine or user session and is tied to the machine and the user session that encrypted it.
AES strings can easily generated by Powershell by using the New-Object function and the Byte parameter, then using the .net for the Cryptography function, like below.
$Key = New-Object Byte[] 16 # You can use 16, 24, or 32 for AES
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
this will generate a Byte string like below, with 16 numbers in the sequence:
224
50
152
212
111
199
157
75
82
77
107
126
71
227
230
149
this can then be outputted to a file for future use, both for encrypting and decrypting credentials, like so:
Clear-Host
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
write-host "Current directory is: $dir"
#generate AES key for use
$KeyFile = "$dir\AES.key"
$Key = New-Object Byte[] 16 # You can use 16, 24, or 32 for AES
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | out-file $KeyFile
Now that we have generated our AES key file, we can then use that key to start encrypting anything we want, for example our username and password, so in the next portion we’ll get the username and password you want to encrypt.
first step, we need to read in the AES.key file to allow us to encrypt the credentials
#define the credential file, and read in the AES key for encrypting
$PasswordFile = "$dir\Creds.bob"
$KeyFile = "$dir\AES.key"
$Key = Get-Content $KeyFile
now we need to tell it the username and password, or in the case we’re going to mix it up and put the password first.
#asks for the password, encrypts it using the AES key file
[string][ValidateNotNullOrEmpty()] $pwd = read-host "Enter password"
and now the username
#asks for the username, encrypts it using the AES key file
[string][ValidateNotNullOrEmpty()] $User = read-host "enter username"
note the [string][ValidateNotNullOrEmpty()], mean neither enter can be empty or null, now we’ll encrypt those entries, and place them into a variable for use called $content
#add the password and username to the variable $content separating them from each other by ' ; ' note the spaces. $content = (ConvertTo-SecureString -String $pwd -AsPlainText -Force | ConvertFrom-SecureString -Key $key) + " ; " + (ConvertTo-SecureString -String $user -AsPlainText -Force | ConvertFrom-SecureString -Key $key)
now all we need to do is write the $content to the credentials file (our Creds.bob file)
#output the $content variable to the credential file.
$content | out-file $PasswordFile
now lets do some housekeeping on the memory buffer and clear our $content variable and $key
#clear the variable so it's no longer in memory
$null = $content
$null = $key
and that it, we’ve encrypted our username and password into a file, and have an AES key that we can use to decrypt it for use in a powershell script.
here is all the steps in a single script:
#generate AES key for use
$KeyFile = "$dir\AES.key"
$Key = New-Object Byte[] 16 # You can use 16, 24, or 32 for AES
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | out-file $KeyFile
#define the credential file, and read in the AES key for encrypting
$PasswordFile = "$dir\Creds.bob"
$KeyFile = "$dir\AES.key"
$Key = Get-Content $KeyFile
#asks for the password, encrypts it using the AES key file
[string][ValidateNotNullOrEmpty()] $pwd = read-host "Enter password"
write-host "encrypting $pwd`n"
#asks for the username, encrypts it using the AES key file
[string][ValidateNotNullOrEmpty()] $User = read-host "enter username"
write-host "encrypting $user`n"
#add the username to the variable $content seperating it from the previous data by ' ; ' note the spaces
$content = (ConvertTo-SecureString -String $pwd -AsPlainText -Force | ConvertFrom-SecureString -Key $key) + " ; " + (ConvertTo-SecureString -String $user -AsPlainText -Force | ConvertFrom-SecureString -Key $key)
#output the $content variable to the credential file.
$content | out-file $PasswordFile
#clear the variable so it's no longer in memory
$null = $content
$null = $key
To see how to use these encrypted credentials see Working with AES encryption – Part 2, until then Happy POSH coding.