I hit on a few posts that dialed me into a process that seems to work reliably. The result is below. Its a standalone test script but can be easily imported into any script.
What I do is use an XML file as a config file and read it when a script starts. The encoded string this script creates is suitable for storage this way and recalls cleanly. I also include the encrypted AES key in the XML file so both can be read and the internals of the calling script can remain generic. This recovered password can be de-crypted by anyone not just the user who encrypted it so it works fine for service accounts running automated scripts.
The script stays in whatever folder you put it in so it's best to put it in a new empty folder for testing.
Now for the usual disclaimer... This is only nominally secure. Anyone who knows what they are doing can de-crypt the password since BOTH the encryption key and password locations are available. This is just to prevent the password from being stored as plain text.
Clear-Host
Function RandomKey { #-[ function creates a random byte
string of specified length ]--
$Length = 32 #16,24, or 32
$Script:RKey = @()
For ($i=1; $i -le $Length; $i++) {
[Byte]$RByte = Get-Random -Minimum 0 -Maximum 256
$Script:RKey += $RByte
}
Return $Script:RKey
}
$ByteArray = RandomKey
$Password_IN = 'MyP@ssw0rd'
$User = "domain\serviceaccount"
write-host "Input
password :"$Password_IN -ForegroundColor Red
write-host "byte
array :"$Script:ByteArray -ForegroundColor white
#----------[ Creating AES key
with random data and export to file ]-------------
$KeyFile = "$PSScriptRoot\AESkey.txt"
#$RndKey = New-Object Byte[]
16 # You can use 16, 24, or 32 for AES
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($ByteArray)
$Base64String = [System.Convert]::ToBase64String($ByteArray);
$Base64String | out-file $KeyFile
Write-Host "Byte
array as base64 string :"$Base64String -ForegroundColor Cyan
#-------------[ Creating
SecureString object ]----------------------------------
$PasswordFile = "$PSScriptRoot\AESPassword.txt"
$KeyFile = "$PSSCriptRoot\AESkey.txt"
$Base64String = (Get-Content $KeyFile)
$ByteArray = [System.Convert]::FromBase64String($Base64String);
$Password = $Password_IN | ConvertTo-SecureString -AsPlainText -Force
$Password | ConvertFrom-SecureString -key $ByteArray | Out-File $PasswordFile
Write-Host "encrypted
pwd :"(Get-Content $PasswordFile) -ForegroundColor Green
# Creating PSCredential object
$PasswordFile = "$PSScriptRoot\AESPassword.txt"
$KeyFile = "$PSSCriptRoot\AESkey.txt"
$Base64String = (Get-Content $KeyFile)
$ByteArray = [System.Convert]::FromBase64String($Base64String);
write-host "decrypted
byte array :"$ByteArray
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $PasswordFile | ConvertTo-SecureString -Key $ByteArray)
#----------------------[ Useable
result ]---------------------------------------
$Password = $Credential.GetNetworkCredential().Password
$UserID = $Credential.GetNetworkCredential().Username
write-host "decrypted
password :"$Password -ForegroundColor yellow