≡ Menu

Compare secure strings entered through powershell

Can’t we really see the text/password entered through -AsSecureString or with Get-Credential? What I have to do if I got a requirement to compare the passwords? The example scenario for me as a System administrator is, if I have a script which resets admin password acrosss a list of hosts, I will prefer the script to ask for the password two times in secure format and inturn my script should compare these two passwords and proceed only if the passwords entered at two attempts is matched.

In one of the powershell blog author talked about seeing the secure text in plain format. I used that and developed below script for comparing the passwords using powershell.

Write-Host "Hey..!! I am here to compare the password you are entering..."
$pwd1 = Read-Host "Passowrd" -AsSecureString
$pwd2 = Read-Host "Re-enter Passowrd" -AsSecureString
$pwd1_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd1))
$pwd2_text = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd2))

if ($pwd1_text -ceq $pwd2_text) {
Write-Host "Passwords matched"
} else {
Write-Host "Passwords differ"
}

Let me know if you have any comments/questions…

{ 13 comments… add one }
  • Jonathan Santos November 23, 2012, 2:42 am

    Very Good!

    Thanks!!

  • Ronan Fahy December 11, 2012, 8:19 pm

    Hi – nice script but one small problem, you’re not handling case sensitivity – i.e. ABC and abc and AbC are all coming out as matching passwords. If you used:

    if ($pwd1_text.compareTo($pwd2_text) -eq 0) it’ll work.

    • Sitaram Pamarthi December 11, 2012, 9:58 pm

      That is very good point. I think using case sensitive equal comparator in Powershell is very easy. I updated the code to include -ceq instead of -eq.
      Thanks for highlighting that.

  • Alex November 24, 2015, 8:22 pm

    An even smaller problem, you have a typo in password. Unless you were planning on developing a new cereal, pass-o-wrds. And if you are, I would certainly like some.

    Thanks for the script. Can you elaborate where “[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR” comes from?

  • Roger McCarrick May 21, 2017, 6:11 am

    This is great.
    I’ve been trying to put this into a function or a loop, so that if passwords differ, it runs again and keeps running until the password are the same (or ctrl C). I have tried ‘while’ and called it as a function, but even when the passwords are the same it keeps asking to enter a password again.

    Any ideas?
    thanks
    Roger

    • Wintel Rocks June 27, 2017, 2:22 pm

      Roger, please post your code here. It is easy to comment that way.

  • Jerry Eakle November 2, 2017, 9:12 pm

    Here is the while loop I use
    $Matched = $False
    Do {
    $SecurePassword1 = Read-Host -Prompt “Enter Password ” -AsSecureString
    $SecurePassword2 = Read-Host -Prompt “Confirm Password” -AsSecureString
    If (([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword2))) -eq ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword1)))) {$Matched = $True}
    Else {Write-Warning “Passwords do not match!!! They must match to continue.”;$Matched = $False}
    }
    While ($Matched -ne $True)

    • Wintel Rocks November 12, 2017, 9:40 pm

      Jerry, Have you faced any problems running the code?

  • Rui December 21, 2018, 9:15 pm

    The one issue I see with the code is the fact that it incorrectly uses ‘-eq’ instead the correct ‘-ceq’. As it stands test123 and Test123 would be considered equal, even though it is not accurate. Otherwise works quite well. Thank you.

    • Wintel Rocks December 22, 2018, 9:02 am

      The code was corrected back in 2012 to address that. Since then -CEQ is in the code. Where you saw -eq?

  • Perry Harris September 14, 2019, 7:35 am

    Of course the reason to use securestring in the first place, so that the text isn’t plain text is negated when we assign it to $pwd1_text and $pwd2_text. It still gets convert to plain text in memory but no variable is possibly left if we do the comparisons as such:

    if ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd1)) -ceq [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd2)))

    Sure it is a little ungainly, but avoids the two plain text variables.

    • Wintel Rocks October 7, 2019, 5:00 pm

      Thank you for commenting. I felt it is a bit difficult to read, agree?

Leave a Comment