Trial #41: Saving Sensitive Data to File with PowerShell

1 minute read

Problem:

You may want to store credentials on a computer for later use, either to save repeated entry or to allow for automation. However, this information should rarely be trivially accessible to another user of the computer. Therefore, saving credentials and other secrets in clear text is not advisable. Some form of encryption or at least obfuscation is advisable.

Solution:

.NET and PowerShell has a Class called SecureString that can be a safer way to hold sensitive data in memory than a simple System String. Although this is not to be considered completely safe, particularly on non-Windows systems, I am unaware of a better, easily supported way of getting at least some protection in PowerShell. I’d love to hear about more rock solid options in a comment and I will post an additional article. Use this method if your alternative is storing in clear text, as the cost is low enough to be considered free. If your working with state secrets this is certainly not the final word.

Acquire your SecureString

One way to acquire a [SecureString] is from the host.

$secureString = Read-Host -AsSecureString

You can also convert a standard string from some other input.

$secureString = "Secret" | ConvertTo-SecureString -AsPlainText

Persisting your SecureString

PowerShell has the ConvertFrom-SecureString Cmdlet.

The ConvertFrom-SecureString cmdlet converts a secure string (System.Security.SecureString) into an encrypted standard string (System.String). Unlike a secure string, an encrypted standard string can be saved in a file for later use.
ConvertFrom-SecureString

This is an essential step to serialise our SecureString prior to persisting to a text file.

$secureString | ConvertFrom-SecureString > secret.txt

Or even a json structure.

@{
    Secret = $secureString | ConvertFrom-SecureString
} |
   ConvertTo-Json > secret.json

Importing your SecureString

When you read your secure string back from file, it is in the form of an encrypted String, this will almost always need to be converted back to a SecureString and ultimately a clear text String.

$encryptedString = Get-Contents secret.txt -Raw
$secureString = $encryptedString | ConvertTo-SecureString
$clearTextString = $secureString | ConvertFrom-SecureString -AsPlainText

Updated: