Using SecureString in PowerShell (With SecureKey)

This example uses SecureString with SecureKey. This technique is useful when Key is required to be saved as a non-readable string in a file.

Note, the use of “(1..16)keyword. This is required to encrypt the key such a way that it can be decrypted by any user on any machine as long as the secure key is accessible. (1..16) Gives a  byte array containing  numbers 1 to 16, instead of (1..16) any constant key also can be used, which in turn also can be sourced from a file. I don’t want to go into encrypting the key for the secure key as this would mean recursion of the same logic and have the same problem of unable to decrypt by different user or different machine. As I understand at the top level a static/constant key is required.

For security, Secure Key can be stored in a file share which is accessible to specific user/group.

Steps:

1. Generate key (encrypted) then encrypt password and save both encrypted key password


$key = "1234567891234567"
$plainPassword = "securekey-textpassword"
$securePassword = ConvertTo-SecureString $PlainPassword -AsPlainText -Force
$secureKey = ConvertTo-SecureString $Key -AsPlainText -Force
$encryptedKey = ConvertFrom-SecureString $SecureKey -Key(1..16)
$encryptedPassword = ConvertFrom-SecureString $SecurePassword -SecureKey $secureKey</pre>
<pre>$encryptedKey | Out-File "C:\temp\securekey-enckey.txt" $encryptedPassword | Out-File "C:\temp\securekey-encpass.txt" Write-Host "Key: $Key" Write-Host "Text Password: $textPassword" Write-Host "Encrypted Password: $encryptedPassword" Write-Host "Encrypted Key: $encryptedKey" 

2. Retrieve and decrypt password (using secure key)

$encryptedKeyFromFile = Get-Content "C:\temp\securekey-enckey.txt"
$encryptedPasswordFromFile = Get-Content "C:\temp\securekey-encpass.txt"
$secureDecryptedKey = ConvertTo-SecureString $encryptedKeyFromFile -Key(1..16)
$secureDecryptedPassword = ConvertTo-SecureString $encryptedPasswordFromFile -SecureKey $secureDecryptedKey

$BSTR1 = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureDecryptedPassword)
$textPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR1)

$BSTR2 = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureDecryptedKey)
$key = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR2)

Write-Host "Key: $key"
Write-Host "Text Password: $textPassword"
Write-Host "Encrypted Password: $encryptedPasswordFromFile"
Write-Host "Encrypted Key: $encryptedKeyFromFile"

 

Using SecureString in PowerShell (With Key)

Here is the example of using SecureString, when 16 bytes key is used. Using key we can overcome the problem – “decryption of password can only be done by same user on same machine which were used for encryption”, as mentioned in my earlier post.

1. Generate key, encrypt password and save both key and encrypted password


$textPassword = "withkey-textpassword"
$key = New-Object Byte[] 16 # You can use 16, 24, or 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key)

$securePassword = ConvertTo-SecureString $textPassword -AsPlainText -Force
$encryptedPassword = ConvertFrom-SecureString $SecurePassword -Key $Key

$encryptedPassword | Out-File "c:\temp\withkey-encpass.txt"
$key | Out-File "c:\temp\withkey-plainkey.txt"

Write-Host "Key: $Key"
Write-Host "Encrypted Password: $encryptedPassword"

2. Retrieve key and password then decrypt password using the key


$encryptedPassword = Get-Content "C:\temp\withkey-encpass.txt"
$key = Get-Content "C:\temp\withkey-plainkey.txt"
$secureDecryptedPassword = ConvertTo-SecureString -string $encryptedPassword -Key $key

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureDecryptedPassword)
$textPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

$credentials = New-Object System.Net.NetworkCredential("TestUsername", $secureDecryptedPassword, "TestDomain")

Write-Host "Key: $Key"
Write-Host "Encrypted Password: $encryptedPassword"
Write-Host "Text Password: $textPassword"
Write-Host ("Text Password without marshaling: {0}" -f $credentials.Password)

Using SecureString in PowerShell (No Key)

Here is the example of using SecureString, when no key or SecureKey is used. It should be noted that decryption of password can only be done by same user on same machine which were used for encryption.

Steps:

1. Encrypt and save password


$textPassword = "nokey-textpassword"
$securePassword = ConvertTo-SecureString $textPassword -AsPlainText -Force
$encryptedPassword = ConvertFrom-SecureString $securePassword
$encryptedPassword | Out-File "c:\temp\nokey-encpass.txt"

Write-Host "Encrypted Password: $encryptedPassword"
Write-Host "Text Password: $textPassword"

2. Retrieve and decrypt password


$encryptedPassword = Get-Content "C:\temp\nokey-encpass.txt"
$secureDecryptedPassword = ConvertTo-SecureString -string $encryptedPassword</pre>
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureDecryptedPassword)
$textPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

$credentials = New-Object System.Net.NetworkCredential("TestUsername", $secureDecryptedPassword, "TestDomain")

Write-Host "Encrypted Password: $encryptedPassword"
Write-Host "Text Password: $textPassword"
Write-Host ("Text Password without marshaling: {0}" -f $credentials.Password)

Download VHD from AzureRM VM

Here is a AzureRM version of script to download the VHD. NOTE: before downloading the VHD make sure that it is not in use e.g. parent VM is switched off

Script to Download VM from Azure

#Login-AzureRmAccount
Select-AzureRMSubscription -TenantId <> -SubscriptionId <>

$sourceVHD = <>
$destinationVHD = <>
Save-AzureRmVhd -ResourceGroupName <> -SourceUri $sourceVHD -LocalFilePath $destinationVHD