CredentialsWithKey.ps1


<#==============================================================================
         File Name : CredentialsWithKey.ps1
   Original Author : Kenneth C. Mazie (kcmjr AT kcmjr.com)
                   :
       Description : I've tried numerous times to get a service account password into an
                   : encrypted file and then recall it. Sometimes it's worked, sometimes not.
                   : 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 an
                   : external 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.
                   :
         Arguments : None
                   :
             Notes : None
                   :
      Requirements : None
                   :
          Warnings : NOTE !!! 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.
                   :
             Legal : Public Domain. Modify and redistribute freely. No rights reserved.
                   : SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF
                   : ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
                   :
           Credits : Code snippets and/or ideas came from many sources around the web.
                   :
    Last Update by : Kenneth C. Mazie (email kcmjr AT kcmjr.com for comments or to report bugs)
   Version History : v1.00 - 09-12-16 - Original
    Change History : v1.10 - 03-02-18 - Formatted for upload to PS Gallery
                   :
#===============================================================================#>

<#PSScriptInfo
.VERSION 1.10
.GUID ff96e89e-d400-471f-a33f-8de7663a56a6
.AUTHOR Kenneth C. Mazie (kcmjr AT kcmjr.com)
.DESCRIPTION
Creates AES encrypted string for use as credentials stored within a script.
#>


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

<#------------------------[ To Recall ]------------------------------------------
To use:
I store the results in an XML file like so...
 
<Credentials>
    <UserName>domain\serviceaccount</UserName>
    <Password>76492d1116743f8AHIAeEAYQBhAGQANQBkADQAZQAzAGYANAAyADUAYTgBaADcAYwBtAHAWnHbuTOeJWnHbuTOeJFEAPGMAYQBhAGQA2AADEANgBiADA7IXN0I16051/0a534bie8AANwBkADEANAA4AGQAZgA3ADIAYQAwADYAZAA3AGUAZgBkAGYAZAA=</Password>
    <Key>kdWnHbu04234h5M/0a534bie8A13bgBTOeJ7IX605mE=</Key>
</Credentials>
 
Read the file ...
 
        [xml]$Script:Configuration = Get-Content $Script:ConfigFile
        $Script:UserName = $Script:Configuration.Settings.Credentials.Username
        $Script:EncryptedPW = $Script:Configuration.Settings.Credentials.Password
        $Script:Base64String = $Script:Configuration.Settings.Credentials.Key
 
Decode and store as variables...
        $ByteArray = [System.Convert]::FromBase64String($Script:Base64String);
        $Script:Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Script:UserName, ($Script:EncryptedPW | ConvertTo-SecureString -Key $ByteArray)
        $Script:Password = $Script:Credential.GetNetworkCredential().Password
 
#>