Forum Discussion
calvinrafael
Aug 16, 2024Copper Contributor
Powershell masking password
Hello Everyone,
I have the script (API POST) below which is working fine.
$UserPass = "username:password"
[string]$stringToEncode=$UserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("content-type", "application/json")
$headers.Add("accept", "application/json")
$headers.Add("Authorization", "Basic " + $encodedString)
Invoke-RestMethod -Uri "https://api_base_url/session" -Headers $headers -Method POST
I want to mask the password instead of plain text. So modified it to below which will ask to enter the masked password.
$UserPass = "username:$(Read-Host -Prompt "Please type the password" -AsSecureString)"
But the whole script is not working anymore. When I troubleshoot, there is a difference in encoding/decoding. I ran an online base64 decode and encode, the result is different.
Plain text password - username:password
dXNlcm5hbWU6cGFzc3dvcmQ= ---> username:password
Masked password - username:$(Read-Host -Prompt "Please type the password" -AsSecureString)
dXNlcm5hbWU6U3lzdGVtLlNlY3VyaXR5LlNlY3VyZVN0cmluZw== ---> username:System.Security.SecureString
How can I mask the password but able to read the System.Security.SecureString as the actual password?
Thank you in advanced.
2 Replies
Sort By
- LainRobertsonSilver Contributor
Hi, Roel.
A secure string is encrypted, not simply encoded (which is what base64 conversion is). You cannot easily read a secure string a plain text - which is by design (or it wouldn't be particularly secure, and barely even obscure).
There are various ways to coerce the SecureString value back to plain text, where the easiest is to leverage the built-in [pscredential] class.
Note: Secure string objects are not portable between machines. I mention this solely because I've seen people in the past try to save them on the machine they've generated them, port the script and saved encrypted password to another machine and wonder why it doesn't work. It's not meant to, so don't try.
Example
# Replace this line from your script/forum post. $UserPass = "username:$(Read-Host -Prompt "Please type the password" -AsSecureString)" # With these lines. Note: The username parameter in the pscredential constructor is ignored in this example, meaning it can be any value. $Password = Read-Host -Prompt "Enter password" -AsSecureString; $Credential = [pscredential]::new("Foo", $Password); $UserPass = "username:$($Credential.GetNetworkCredential().Password)";
Cheers,
Lain
- calvinrafaelCopper Contributor
LainRobertson I really appreciate your help and response. Thanks for your code.
Adding below code works for me.
$password = (Read-Host -Prompt "Please type the password" -AsSecureString)
$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($password)
$result = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr)
#$result
$UserPass = "username:$($result)"
[string]$stringToEncode=$UserPass
$encodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($stringToEncode))
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("content-type", "application/json")
$headers.Add("accept", "application/json")
$headers.Add("Authorization", "Basic " + $encodedString)