Closed colombeen closed 5 years ago
@colombeen Thanks for the suggestion.
I was thinking about doing this before, it's not too hard to implement but would be a breaking change in terms of existing functionality. Also because the API expects plaintext passwords for updating the resources and creating new ones ect the password would have to be converted back to plain text at certain points in the code.
So i'm not sure how to best handle the situation. Maybe all passwords as secure strings by default with a new function to decrypt the passwords if desired?
EG. to find an Password entry and show the password in plain text would be something like below.
Find-PasswordStatePassword -id 1 | Decrypt-Password
For other cases such as updating a password a check would need to added to see if the input is of a secure string type to decrypt before trying to update.
Otherwise the following would end up with Passwords of System.securestring
Find-PasswordstatePassword -id 1 | Update-PasswordStatePassword -url "https://google.co.uk"
Not sure if you had any thoughts?
Decryption of secure strings is as simple as the below:
$SecurePassword = ConvertTo-SecureString $PlainPassword
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
On the other hand, you could try a PSCredential instead of a SecureString, it's easier to "decode" with $PSCredential.GetNetworkCredential().Password
I think i have a working solution for this, using custom classes.
The Password will be stored as a secure string by default but the class will have a method to expose the password as plain text.
Class EncryptedPassword {
EncryptedPassword ($Password){
$this.Password = ConvertTo-SecureString -String $Password -AsPlainText -Force
}
$Password
}
class PasswordResult {
# Properties
[int]$PasswordID
[String]$Title
[String]$Username
[EncryptedPassword]$Password
[String]GetPassword(){
$SecureString = $this.Password.Password
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
}
[String]$Description
[String]$Domain
# Hidden Properties
hidden [String]$hostname
hidden [String]$GenericField1
hidden [String]$GenericField2
hidden [String]$GenericField3
hidden [String]$GenericField4
hidden [String]$GenericField5
hidden [String]$GenericField6
hidden [String]$GenericField7
hidden [String]$GenericField8
hidden [String]$GenericField9
hidden [String]$GenericField10
hidden [int]$AccountTypeID
hidden [string]$notes
hidden [string]$URL
hidden [string]$ExpiryDate
hidden [string]$allowExport
hidden [string]$accounttype
}
So the result would look like below:
Find-PasswordStatePassword -PasswordID 6592
PasswordID : 6592
Title : testing
Username : test
Password : EncryptedPassword
Description :
Domain :
And the password revealed by: (Find-PasswordStatePassword -PasswordID 6592).Getpassword()
eg.
(Find-PasswordStatePassword -PasswordID 6592).Getpassword()
CorrectHorseStapleBattery
And i think i'll look at adding some sort of global preference to reveal in plaintext by default to maintain backwards compatibility.
Will probably take a couple of days to clean the code, fix tests and update the documentation.
Looks very interesting!
Pull request #12 adds support for secure strings.
Readme docs have been updated to reflect this.
New published version: https://www.powershellgallery.com/packages/passwordstate-management/0.0.94
Just a suggestion, changing the returned object password property to a securestring instead of a regular string. Just a little bit more secure then just showing the password.
I was trying to implement it myself but I can't seem to get it working.