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

Comments (14)

  1. Anonymous says:

    I need to generate a password length report for a list of users from a .txt file. Please help. Thanks!

  2. "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."

    You can decrypt the Get-Credential provided password ($credential.Password) using:

    $PlainTextPassword= [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR( (ConvertTo-SecureString $credential.Password) ))

  3. kenny says:

    This came as a chock to me!

    So using the Get-Crendentials command in a script is a security issue?

  4. Hardik Kamdar says:

    $credential = Get-Credential


    Those above 2 lines seem simpler. But nice to know another way. Thanks Michel

  5. Ed Wilson says:

    @Michel de Rooij Thank you for sharing this code. I have seen it several times, and personally I find it a bit confusing. Therefore my statement of 'none that are very direct or easy to use." But, this is great because you show how to do this without using the power of PowerShell. Thank you for sharing.

  6. Ed Wilson says:

    @Kenny This is the reason I share this information, is that I want people to know what is going on. This is, in my mind, not a security issue because I know the password before I store it in a credential object. Therefore, that I am able to decrypt my own password that I just typed in, does not seem like a security issue. But yes, some people are shocked that this is directly accessible. The main point here, is that it is very easy to use Get-Credential to solicit credentials, and then you can get the plain text required for use with things like FTP — which by their very nature are plain text and therefore insecure. All this is by design, and is not therefore necessarily a security issue.

  7. kenny says:


    Good point, Thanks Ed!

  8. ML49448 says:

    This was an amazing answer to a question that has been bothering me for about 3 months now.  Excelent explaination of how this all works.

  9. anand Sonawane says:

    All files including videos, photos and documents on your computer are encrypted.

    Encryption was produced using a unique public key generated for this computer. To decrypt files, you need to obtain the private key.

    The single copy of the private key, which will allow you to decrypt the files, located on a secret server on the Internet; the server will destroy the key after a time specified in this window. After that, nobody and never will be able to restore files.

    In order to decrypt the files, open site and follow the instructions.

    If is not opening, please follow the steps below:

    1. You must download and install this browser
    2. After installation, run the browser and enter the address: 4sfxctgp53imlvzk.onion/index.php
    3. Follow the instructions on the web-site. We remind you that the sooner you do, the more chances are left to recover the files.


    Your Personal CODE: 00000002-F8688D7B

  10. Ankit Amrutiya says:

    pkz hepl me

    how to decript this string


  11. Chris says:

    @Amkit Amrutiya
    This isn’t encrypted, it’s just the ASCII codes for each char
    Try the following:
    "110,101,121,99,121,112,108,54,66,57,55,53".Split(",") | ForEach {[char][Int]$_}

    @Mod, could you please remove the very dodgy SPAM comment from anand Sonawane, anyone reading, I’d recommend against following the instructions! 🙂

  12. ScriptingPower says:

    Ed writes that recovering the cleartext is not an issue for things like FTP ok.
    But what if you are looking for a secure way to Change a credentials for a Service account.
    The only way i found was using wmi
    Something like
    $service = gwmi win32_service -computer [computername] -filter "name=’whatever’"
    Even if I run it on a local Computer ist still the plaintext Password and so somewhere unencrypted in Memory.
    Is there a fuction that uses Pscredentials without Need tor econvert to plain text ?

  13. Diepkv says:

    Thank you for sharing this tip

  14. Itamarm says:

    Getting $credential.Password in plain text is very simple:

    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.Password)
    $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)