Decrypt PowerShell Secure String Password

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to easily decrypt the Windows PowerShell secure string password.

Hey, Scripting Guy! Question Hey, Scripting Guy! We have an FTP site that I have to use on a regular basis. I need an easy way to get a credential and use that credential with the FTP site so that I can download a file that changes on a daily basis. I found a few scripts and functions on the Internet that will decrypt the secure string password from a Windows PowerShell credential object, but they all seem really complicated. Is there an easy way to do this?


Hey, Scripting Guy! Answer Hello AD,

Microsoft Scripting Guy, Ed Wilson, is here. Today I am sitting here drinking a cup of Earl Grey tea with a pinch of lavender in it. I love the way the two flavors complement each other. As I look over my email, I ran across your question. Although you did not include a link to the complicated versions of the scripts and functions you ran across, I will venture to say that my method should be relatively painless.

           Note   What I am showing here today is exactly by design, and is not a hack.

Using Get-Credential for credentials

I love using the Get-Credential cmdlet to retrieve a credential object. It is already set up to work; and therefore, it is easy to use. If I need credentials, I do not need to mess around writing HTAs, creating various WinForms to prompt for a user name and password, or worry about how to mask the password—all of which were problems before Windows PowerShell and the Get-Credential cmdlet. So, like I say, I absolutely love it. To use the Get-Credential cmdlet, I generally store the resulting credential object in a variable. (I do not have to do so, because I can use it directly if I need to, but it is more flexible to store it in a variable.) Here is the command.

$credential = Get-Credential

When I run this command, a dialog box appears. The box is already set up to use, with a user name on the top, and it masks the password in the bottom box. The box is shown here.

Image of dialog box

 The problem with Get-Credential

The problem with the Get-Credential cmdlet is that it returns a PSCredential object. In itself, this is not an issue, but it does mean that I can only use the credential object for cmdlets and for other items that know what a PSCredential object is. Not even all .NET classes know how to deal with a PSCredential object, so when it comes to connecting to legacy databases and things like websites and FTP sites, there is little hope of being able to use the object directly.

Luckily, I can use the Get-Member cmdlet to look at the members of a PSCredential object. The members are listed here.

PS C:\> $credential | gm 

   TypeName: System.Management.Automation.PSCredential


Name                 MemberType Definition

—-                 ———- ———-

Equals               Method     bool Equals(System.Object obj)

GetHashCode          Method     int GetHashCode()

GetNetworkCredential Method     System.Net.NetworkCredential GetNetworkCredential()

GetObjectData        Method     void GetObjectData(System.Runtime.Serialization.S…

GetType              Method     type GetType()

ToString             Method     string ToString()

Password             Property   securestring Password {get;}

UserName             Property   string UserName {get;}

At first, it looks like things are relatively easy. If I want to see the user name, all I need to do is access the UserName property as shown here.

PS C:\> $credential.UserName


That is cool. Now what about the password? When I access the Password property, it returns SecureString. This is shown here.

PS C:\> $credential.Password


Hmmm, what if I look at the members of SecureString? I pipe it to the Get-Member cmdlet, and I see the following members.

PS C:\> $credential.Password | gm 

   TypeName: System.Security.SecureString


Name         MemberType Definition

—-         ———- ———-

AppendChar   Method     void AppendChar(char c)

Clear        Method     void Clear()

Copy         Method     securestring Copy()

Dispose      Method     void Dispose(), void IDisposable.Dispose()

Equals       Method     bool Equals(System.Object obj)

GetHashCode  Method     int GetHashCode()

GetType      Method     type GetType()

InsertAt     Method     void InsertAt(int index, char c)

IsReadOnly   Method     bool IsReadOnly()

MakeReadOnly Method     void MakeReadOnly()

RemoveAt     Method     void RemoveAt(int index)

SetAt        Method     void SetAt(int index, char c)

ToString     Method     string ToString()

Length       Property   int Length {get;}

Ok, cool. I will try the ToString method and see what happens.

PS C:\> $credential.Password.ToString()


Well, that was less than illuminating…

What if I try the Length property? Does it give me anything?

PS C:\> $credential.Password.Length


It does.This is promising. I can at least write code that checks the length of the password and provides some sort of feedback to users regarding the length of the password they supply. It could be rather a cool solution.

What if I use the ConvertFrom-SecureString cmdlet? This is a standard Windows PowerShell cmdlet, so I decide to pipe the password to the ConvertFrom-SecureString cmdlet. The following illustrates the output.

PS C:\> $credential.Password | ConvertFrom-SecureString






This latest representation is a string, and therefore there are no more options available for decrypting the password—at  least, none that are very direct or easy to use.

Get a network credential

The solution, is to go back to the PSCredential object itself. It has a method that is designed to help with the exact scenario. I need to provide credentials to a legacy type of interface that does not know how to handle a PSCredential. Therefore, I need to be able to get both the user name and the password in an easy-to-use and easy-to-digest manner. When I call the GetNetworkCredential method from the PSCredential object, it returns the user name and the domain name. This is shown here.

PS C:\> $credential.GetNetworkCredential() 

UserName                                           Domain

——–                                           ——

someuser                                           mydomain

If I pipe the returned object to the Get-Member cmdlet, however, I see that I now have a NetworkCredential object. The members are listed here.

PS C:\> $credential.GetNetworkCredential() | gm 

   TypeName: System.Net.NetworkCredential


Name           MemberType Definition

—-           ———- ———-

Equals         Method     bool Equals(System.Object obj)

GetCredential  Method     System.Net.NetworkCredential GetCredential(uri uri, str…

GetHashCode    Method     int GetHashCode()

GetType        Method     type GetType()

ToString       Method     string ToString()

Domain         Property   string Domain {get;set;}

Password       Property   string Password {get;set;}

SecurePassword Property   securestring SecurePassword {get;set;}

UserName       Property   string UserName {get;set;}

I see the password has a SecureString for the SecurePassword property, but there is also the Password property that is a plain string. So, I pipe the NetworkCredential object to the Format-List cmdlet and the following appears.

PS C:\> $credential.GetNetworkCredential() | fl * 

UserName       : someuser

Password       : SomeUsersPassword

SecurePassword : System.Security.SecureString

Domain         : mydomain

If I need only the password, I simply retrieve the Password property as shown here.

PS C:\> $credential.GetNetworkCredential().password


By the way, I can also get the password length here. This is because all string objects contain a Length property. This is shown here.

PS C:\> $credential.GetNetworkCredential().password.length


AD, that is all there is to using the NetworkCredential object. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy