Is it possible using the System.Windows.Forms.TextBox (or any other method) to enter in text that can then be converted to securestring? I would like to be able to take a value entered, convert it to securestring and write that to a file which could then be called on if needed and the securestring converted back should we need to identify the value.
I've looked into something similar to this, but since I am using the TextBox forms, I don't want to rely on Read-Host
$secstr = Read-Host -AsSecureString "Enter your text"
$secstr | ConvertFrom-SecureString | out-file C:\temp\test.txt
$secstr = get-content c:\temp\test.txt | ConvertTo-SecureString -AsPlaintText -Force
Essentially, I want to have a text box use masked/password characters (which I can do with $TextBox.PasswordChar = "*" and then take that input and dump it into a securestring text file. Then, I could use another script to call on that file and display the text in plain text for the end user should they need to know that current value.
Use a MaskedTextBox instead of a regular TextBox if you want to embed this in a custom GUI:
Add-Type -Assembly 'System.Windows.Forms'
$form = New-Object Windows.Forms.Form
$password = New-Object Windows.Forms.MaskedTextBox
$password.PasswordChar = '*'
$password.Top = 100
$password.Left = 80
$form.Controls.Add($password)
$form.ShowDialog()
[source]
and then convert the text to a secure string:
$secstr = $password.Text | ConvertTo-SecureString -AsPlaintText -Force
If you just want to prompt for credentials you could use Get-Credential, which already stores the entered password as a secure string:
PS C:\> $cred = Get-Credential
Cmdlet Get-Credential an der Befehlspipelineposition 1
Geben Sie Werte für die folgenden Parameter an:
Credential
PS C:\> $cred.Password
System.Security.SecureString
An additional way is to use a plain TextBox and as Ansgar mentioned use the PasswordChar attribute:
$textbox = New-Object System.Windows.Forms.Textbox
$textbox.Size = '75,23'
$textbox.PasswordChar = '*'
$form.Controls.Add($textbox)
Related
I have two functions, Save Credential to create a .cred file:
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($Username, $PWord)
$cred.Password | Out-File "some\path\$($cred.Username).cred" -Force
and Get Credential to retrieve the password:
$string = Get-Content "some\path\$($Username).cred" | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $string
return $cred
I cannot for the life of me figure out how to retrieve the password from the .cred file that I created. The errors I get are:
ConvertTo-SecureString: Input String was not in the correct format
New-Object: Exception calling .actor with 2 arguments. Cannot process argument because the value of argument "password" is null. change the value of argument password to a non-null value
What version are you bound to? I might not be following properly, but it looks like you don't care about the whole credential and just want the password, so couldn't it just be:
#set
$pwd = "replace me"
$securepwd = $pwd | ConvertTo-SecureString -AsPlainText -Force
$encryptedpwd = $securepwd | ConvertFrom-SecureString
Out-File -FilePath C:\temp\Reference.cred -InputObject $encryptedpwd
then
#get
$securepwd = (Get-Content -Path C:\temp\Reference.cred) | ConvertTo-SecureString
#commented out 3 lines shows how to decrypt in case you want to view it/verify it, but isn't necessary
#$Marshal = [System.Runtime.InteropServices.Marshal]
#$Bstr = $Marshal::SecureStringToBSTR($securepwd)
#$pswd = $Marshal::PtrToStringAuto($Bstr)
#$Marshal::ZeroFreeBSTR($Bstr)
$RunAs = New-Object System.Management.Automation.PSCredential ('Domain\Account', $securepwd)
I'm not as good as most folks on here though, just giving it a stab.
I am fighting with outputting text file and getting file content in exactly the same way as it was provided by the user. I tried to find an answer but the only thing I can find is how to change multiline into one string which is quite the opposite I need.
How to ensure that input provided by the user in multiline will not be altered to single line in PowerShell?
Details:
In inputbox I provide details in multiline:
PowerShell saves the output in one line:
I want PowerShell to save multiline input and then show multiline output.
Here is the code:
function Notes
{
$var = $Users.Text
$var | Out-File C:\Users\A570654\Desktop\users.txt
$var = Get-Content C:\Users\A570654\Desktop\users.txt
Set-Content -Path C:\Users\A570654\Desktop\notes.txt "*************************************************
$var
*************************************************"
Invoke-Item -Path C:\Users\A570654\Desktop\notes.txt
}
############################## FORMS #######################################
$Users = New-Object System.Windows.Forms.RichTextBox
$Users.Size = New-Object System.Drawing.size(470,85)
$Users.Location = New-Object System.Drawing.Size(10,100)
$Users.MultiLine = $true
$Users.AutoSize = $true
$Users.ScrollBars = "Vertical"
$users.AcceptsTab
$form = New-Object system.windows.forms.form
$form.size = New-Object system.drawing.size(600,600)
$button = New-Object system.windows.forms.button
$button.text = "Get Notes"
$button.Add_Click({Notes})
$form.Controls.Add($Users)
$form.Controls.Add($button)
$form.Showdialog()
The reason why I decided to save the string in file is that output shows spaces as in picture 2. If I decide not to save output to file and then get its content then string appears in the following format: JohnTomKate.
You are saving the user input to a file and reload the content which will give you the current output. So just use the variable without reassigning it:
$var = $Users.Text
$var | Out-File C:\Users\A570654\Desktop\users.txt
Set-Content -Path C:\Users\A570654\Desktop\notes.txt "*************************************************
$var
*************************************************"
Output:
*************************************************
John
Tom
Kate
*************************************************
I am trying to have my password secured and stored in a file so that I don't need to enter each time when I run the script.
First step, I ran the following, entered the password which got stored into E:\cred.txt file. The txt file now contains an encrypted password.
(Get-Credential).Password | ConvertFrom-SecureString | Out-File "E:\cred.txt"
Secondly, I ran the below Script:
$File = "E:\cred.txt"
$User = "jason#domain.com"
#### I have two different user accounts, one for admin and other for operator,
#### however both user accounts use same password.
$adminuser = $User
$operator = $User -replace "#domain.com"
#### I would need to read $File to get only the password
$pass = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList (Get-Content $File | ConvertTo-SecureString)
$adminuser
$operator
$pass
Output:
jason#domain.com
jason
UserName Password
-------- --------
From the output, it seems New-Object refers to both UserName and Password. And when I try to connect to systems, it fails with Authentication error. Since I already have two different usernames hard coded within the script, how should I get only the password stored in $pass? or is it possible to include all usernames ($User, $adminuser, $operator) into the cred.txt file?
Try this:
#saving credentials
Get-Credential | Export-CliXml -Path c:\credential.xml
#importing credentials to a variable
$Credential = Import-CliXml -Path c:\credential.xml
Or this:
#you could then write it to a file or, i say its a better approach to a registry key
$SecurePassword = ConvertTo-SecureString -String 'P#ssw0rd' -AsPlainText -Force | ConvertFrom-SecureString
#now you are taking it back as a secure string
$RegistrySecureString = $SecurePassword | ConvertTo-SecureString
#you can aslo see the password
$UserName = "NULL"
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $RegistrySecureString
$Password = $Credentials.GetNetworkCredential().Password
#P#ssw0rd
I'm trying to use WinSCP .NET assembly with secure credential, when the password secured in external file.
# Load WinSCP .NET assembly
Add-Type -Path "D:\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
# Env
$sessionOptions.HostName = "blabla.com"
$sessionOptions.UserName = "UUUU"
#$sessionOptions.Password = "PPPP"
$sessionOptions.SshHostKeyFingerprint = "XXXXXXXXX"
$remotePath = "/home/UUUU/"
With hard coded password its working. If I would like to use securestring for the password, how should I do that?
I tried:
read-host -assecurestring | convertfrom-securestring | out-file D:\securestring.txt
To keep the secure password in a file. Then, in my script, I get it back:
$sessionOptions.Password = get-Content D:\securestring.txt | convertto-securestring
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $sessionOptions.UserName, $sessionOptions.Password}
But it's not working...
Since WinSCP 5.7, the assembly accepts the SecureString using the SessionOptions.SecurePassword.
See https://winscp.net/eng/docs/library_sessionoptions
Thanks for inspiring this improvement.
While the assembly keeps the password encrypted in memory, it still needs to decrypt it eventually. Improvements to limit internal copies of the decrypted password are pending.
As #Matt pointed out, the WinSCP .Net assembly doesn't accept secure strings or credential objects. You need to pass the password as a plaintext string. You can store the secure string in a file, though:
Read-Host 'Enter password' -AsSecureString |
ConvertFrom-SecureString |
Out-File 'C:\password.txt'
and use a PSCredential object to retrieve the decrypted password from the secure string after you read it from the file:
$un = 'username'
$pw = Get-Content 'C:\password.txt' | ConvertTo-SecureString
$cred = New-Object Management.Automation.PSCredential $un, $pw
try {
Add-Type -Path 'WinSCPnet.dll'
$opt = New-Object WinSCP.SessionOptions
$opt.Protocol = [WinSCP.Protocol]::Sftp
$opt.HostName = 'example.org'
$opt.UserName = $cred.UserName
$opt.Password = $cred.GetNetworkCredential().Password
$opt.SshHostKeyFingerprint = 'ssh-rsa 2048 ...'
$sftp = New-Object WinSCP.Session
$sftp.Open($opt)
...
} catch {
...
} finally {
if ($sftp) { $sftp.Dispose() }
}
WinSCP sample code taken from the documentation.
Note, however, that the password must be saved by the same user who is running the SFTP PowerShell script, because the encryption key is derived from that user's password.
According to WinSCP the password property just supports a string. So trying to pass a secure string will not work. If you really want to store the password in a file, you could attempt to store it as the secure string but that is a really bad idea in general since it can be unsecured just as easily (Also not sure if it is possible). I recommend the following option.
# Only stored in memory which is safer.
$sessionOptions.Password = read-host
If you have your heart set on something else you could try this. Just know for previous reasons I do not condone this. Also i have to see if it even works because it looks like you cant output securestring to file.
read-host | out-file D:\securestring.txt
$sessionOptions.Password = get-Content D:\securestring.txt
Ansgar's explains what I didn't know was possible. You can stored the secure string in a file and use it elsewhere.
I'm trying to use Powershell to connect to VSO. Here is my code:
$tfsServer = New-Object System.Uri("the server is here")
$creds = [System.Net.CredentialCache]::DefaultNetworkCredentials
$tfsCollection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($tfsServer,$creds)
$tfsCollection.Authenticate()
When it reaches the Authenticate line, it pops up a box for me to enter my credentials. I need it to not pop up this box, as this script will be scheduled, and I can't keep entering the credentials. How can I pass the current user's credentials to the TFS object?
Try this:
First, run this command which will prompt you once for your password, and then save it in an encrypted format.
read-host -prompt Password -assecurestring | convertfrom-securestring | out-file .\ps-password.pwd -ErrorAction Stop
Change the $username variable
$Username = 'jdoe'
$Password = Get-Content ".\ps-password.pwd" | ConvertTo-SecureString
$creds = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $Username,$Password
$tfsServer = New-Object System.Uri("the server is here")
$tfsCollection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($tfsServer,$creds)
$tfsCollection.Authenticate()
Use the constructor that just takes a URI. It will default to using the credentials of the current user.
To connect to Visual Studio Online, you have to follow the instructions at Buck's post. Shortly:
enable alternate credentials on the VSO account
set alternate user and password
use code similar to the following
$tfsServer = New-Object System.Uri("the server is here")
$netCred = New-Object NetworkCredential("alternate_user","alternate_password")
$basicCred = New-Object Microsoft.TeamFoundation.Client.BasicAuthCredential($netCred)
$tfsCred = New-Object Microsoft.TeamFoundation.Client.TfsClientCredentials($basicCred)
$tfsCred.AllowInteractive = $false
$tfsCollection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($tfsServer,$tfsCred)
$tfsCollection.EnsureAuthenticated()
I know no way of using current process credentials with VSO, but you must explicitly pass them.
Use EnsureAuthenticated and do not specify credentials.
$tfsCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection("the server is here")
$tfsCollection.EnsureAuthenticated()
This way it will use the account running the process.