Secure Strings
Secure Strings are a way to work with encrypted data – one of the common uses is to protect passwords used in scripts. The way to use them may not be obvious at first sight. I hope to clear some of the confusion around them in this post.
A common technique when asking for a password is to use Read-Host as follows
PS> $password = Read-Host "Pasword" -AsSecureString
Pasword: *********
The password you type is not displayed on screen. If you examine $password we get this
PS> $password
System.Security.SecureString
PS> $password | gm
TypeName: System.Security.SecureString
Name MemberType Definition
---- ---------- ----------
AppendChar Method System.Void AppendChar(char c)
Clear Method System.Void Clear()
Copy Method System.Security.SecureString Copy()
Dispose Method System.Void Dispose()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
InsertAt Method System.Void InsertAt(int index, char c)
IsReadOnly Method bool IsReadOnly()
MakeReadOnly Method System.Void MakeReadOnly()
RemoveAt Method System.Void RemoveAt(int index)
SetAt Method System.Void SetAt(int index, char c)
ToString Method string ToString()
Length Property System.Int32 Length {get;}
According to the .NET documentation
Represents text that should be kept confidential. The text is encrypted for privacy when being used, and deleted from computer memory when no longer needed. This class cannot be inherited.
We can also get to this point in another way
$password2 = ConvertTo-SecureString -String "Password1" -AsPlainText -Force
One draw back to secure strings is that we can’t save them in a file. To do that we need to convert our secure string to an encrypted string using ConvertFrom-SecureString. We some options around the way we encrypt the string as the help file states:
If an encryption key is specified by using the Key or SecureKey parameters, the Rijndael encryption algorithm is used. The specified key must have a length of 128, 192, or 256 bits because those are the key lengths supported by the Rijndael encryption algorithm. If no key is specified, the Windows Data Protection API (DPAPI) is used to encrypt the standard string representation.
PS> $encrypted = ConvertFrom-SecureString -SecureString $password
PS> $encrypted
01000000d08c9ddf0115d1118c7a00c04fc297eb010000001a0fef9547d2e843afa025568a159d2f000000000200000000001066000000010000200
00000377a37eb27c57206a2c73a68fc9c4cad477420a354d9812706e16a836a3a0a4c000000000e80000000020000200000000ce7e56d09c6d1f741
f5ae5f523a2fbd1f9cf001dac56c969e0720f5d7f7c47a20000000914d09c3b241989227b050ab3d8b80b8cb66c13deffb70d6fe159423069ea9f04
000000092aa705254309565d6a0b55c68bfdd4079be1697f549333af9846f9e00438fba406a7e3f5ac77df8a20aa86bf6dbe8283b2ee9e1feb24d17
e37660eb2854dda6
We can save our encrypted string directly to disk
ConvertFrom-SecureString -SecureString $password | Set-Content encrypted.txt
and view the contents by
Get-Content encrypted.txt
If we want to get our secure string back from disk
$secured = ConvertTo-SecureString -String $(Get-Content encrypted.txt)
If you do decide to use the Key or SecureKey parameters when encrypting\decrypting secure strings make sure you remember the key!!
Having got our secure string we need to use either to supply credentials or to use the password in another program
If we want to create a credential object to use with a PowerShell cmdlet for instance
PS> $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "userid", $secured
PS> $cred | ft -a
UserName Password
-------- --------
userid System.Security.SecureString
If we need to use the password as plain text e.g. when setting an AD password or passing it into a command line utility that expects a plain text password we can access the password by using
PS> $cred.GetNetworkCredential().Password
Password1
Secure strings are useful to help key passwords and other sensitive data secure but we just need to be careful in how we use them.