Secure a password with PowerShell

Sometimes our scripts need to store sensitive information. I’d imagine there are far superior ways to store secrets in a vault and call them into the script when necessary. When that’s out of reach, I’d say this approach is better than storing an API key in clear text. Just know that anyone with the right skillsets can still decrypt.

Below are two methods. In method 1 the key file travels with the script. In method 2 the key file is created by using raw certificate data that ideally would only exist on the endpoints the script runs on.

method 1 - building random key file

# build key file - do this step outside of your script
$PasswordFile = "aes.key"
$Key = New-Object Byte[] 32 
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)
$Key | out-file $KeyFile
# encrypting password with key file - do this step outside of your script
$Key = Get-Content $KeyFile
$PasswordFile = "pw.txt"
$Password = "super-secure-password" | ConvertTo-SecureString -AsPlainText -Force
$Password | ConvertFrom-SecureString -key $Key | Out-File $PasswordFile 

# The script you would run that has pw.txt and aes.key available 
$Key = Get-Content $KeyFile
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
# ONLY Use this if the secure-password is needed in clear text
$MyCredential = (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($MyCredential)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

method 2 - building key with raw certificate data

# encrypting password with key file - do this step outside of your script
$Key = (Get-ChildItem Cert:\LocalMachine\Root\<<thumbprint-of-script-in-root-store>>).RawData[0..31]
$PasswordFile = "pw.txt"
$Password = "super-secure-password" | ConvertTo-SecureString -AsPlainText -Force
$Password | ConvertFrom-SecureString -key $Key | Out-File $PasswordFile 

# The script you would run that has pw.txt available 
$Key = (Get-ChildItem Cert:\LocalMachine\Root\<<thumbprint-of-script-in-root-store>>).RawData[0..31]
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
# ONLY Use this if the secure-password is needed in clear text
$MyCredential = (Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($MyCredential)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

This post was inspired from Part 1 and 2 by Kris Powell at PDQ and delves into details that this post doesn’t expand on –

1 Like