How to fill the prompt in powershell script - powershell

I use a command like this:
get-pfxcertificate C:\test.pfx
Enter password: *******
The command ask me to fill the prompt. But I can't do that in my script (test.ps1 for ex)
What I need is like this:
get-pfxcertificate C:\test.pfx -password "123456"
or something similar so I can run my script without fill in the prompt each time
I'm very thankful for any reply

There's no Password parameter, you can try with a .NET class:
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import('C:\test.pfx','123456','DefaultKeySet')

Another option is to extend the abilities of Get-PfxCertificate, essentially enabling the password to be passed in.
# create a backup of the original cmdlet
if(Test-Path Function:\Get-PfxCertificate){
Copy Function:\Get-PfxCertificate Function:\Get-PfxCertificateOriginal
}
# create a new cmdlet with the same name (overwrites the original)
function Get-PfxCertificate {
[CmdletBinding(DefaultParameterSetName='ByPath')]
param(
[Parameter(Position=0, Mandatory=$true, ParameterSetName='ByPath')] [string[]] $filePath,
[Parameter(Mandatory=$true, ParameterSetName='ByLiteralPath')] [string[]] $literalPath,
[Parameter(Position=1, ParameterSetName='ByPath')]
[Parameter(Position=1, ParameterSetName='ByLiteralPath')] [string] $password,
[Parameter(Position=2, ParameterSetName='ByPath')]
[Parameter(Position=2, ParameterSetName='ByLiteralPath')] [string]
[ValidateSet('DefaultKeySet','Exportable','MachineKeySet','PersistKeySet','UserKeySet','UserProtected')] $x509KeyStorageFlag = 'DefaultKeySet'
)
if($PsCmdlet.ParameterSetName -eq 'ByPath'){
$literalPath = Resolve-Path $filePath
}
if(!$password){
# if the password parameter isn't present, just use the original cmdlet
$cert = Get-PfxCertificateOriginal -literalPath $literalPath
} else {
# otherwise use the .NET implementation
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($literalPath, $password, $X509KeyStorageFlag)
}
return $cert
}
And now you can call it
# tada: extended cmdlet with `password` parameter
Get-PfxCertificate 'C:\path\to\cert.pfx' 'password'
Also, if you still need the prompt, you can do something like this.
$pwd = Read-Host 'Please enter your SSL Certificate password.'
Get-PfxCertificate 'C:\path\to\cert.pfx' $pwd

There is now a Get-PfxData command in PowerShell that gets the certificate and chain. The command includes a -Password parameter that takes a SecureString object so you can avoid being prompted.
The EndEntityCertificates property contains an array of certificates at the end of the certificate chain and will contain the same certificate object created by the Get-PfxCertificate command.
The following example converts a normal string to a SecureString object, loads the certificates from a file, then assigns the first/only end certificate to the $SigningCert variable:
$SecurePassword=ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force
$PfxData=Get-PfxData -FilePath ".\cert_filename.pfx" -Password $SecurePassword
$SigningCert=$PfxData.EndEntityCertificates[0]
You can now apply $SigningCert without being prompted for the password.

Thanks to Shay for pointing me in the right direction.
My need was getting the Thumbprint from the PFX file, so I used the non-persistent DefaultKeySet.
Testing under 2012 PS3 fails unless the key set is fully qualified.
Also, a blank space between Import and left parenthesis, i.e. "$cert.Import^^(Sys..." causes an error. Picky, picky parser.
My PFX password is encrypted in the source.
I decrypt it at runtime so it is not visible in the souce.
Set-StrictMode -Version Latest
[string] $strPW = '123456'
[string] $strPFX = 'C:\MyCert.pfx'
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($strPFX,$strPW,[System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"DefaultKeySet")
$cert.Thumbprint

If you are forced to use Windows Powershell (v5.*), then previous solutions in the thread are for you.
However if you can use Powershell 7/Powershell Core, then its own Get-PfxCertificate command does have a -Password parameter.
After installing Powershell 7 and making sure to use pwsh and not powershell, you can load the certificate that way:
$certificate = (Get-PfxCertificate <certificate_path>.pfx -Password (ConvertTo-SecureString -String "<password>" -AsPlainText -Force))

This also works using native PowerShell instead of .NET:
$securePassword = ConvertTo-SecureString -String $strPW -Force -AsPlainText
$cert = Import-PfxCertificate -FilePath $strPFX cert:\LocalMachine\My -Password $securePassword

Related

Unable to locate the private key container when imported using Import-PfxCertificate [duplicate]

I used following PowerShell function to import PFX to my Windows 2008 R2 server's certificate store
function Import-PfxCertificate ([String]$certPath,[String]$certificateStoreLocation = "CurrentUser",[String]$certificateStoreName = "My",$pfxPassword = $null)
{
$pfx = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($certPath, $pfxPassword, "Exportable,PersistKeySet")
$store = new-object System.Security.Cryptography.X509Certificates.X509Store($certificateStoreName,$certificateStoreLocation)
$store.open("MaxAllowed")
$store.add($pfx)
$store.close()
return $pfx
}
The caller of the function looks like $importedPfxCert = Import-PfxCertificate $pfxFile "LocalMachine" "My" $password I installed it to local machine's My store. Then I granted read permission to my IIS Application pool.
I have a WCF service which needs to use it
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<serviceCertificate findValue="MyCertName" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
When I use a client to call the service, I got exception from WCF It is likely that certificate 'CN=MyCertName' may not have a private key that is capable of key exchange or the process may not have access rights for the private key.
If I remove it from MMC, and manually import the same PFX file from Certificate MMC, to same store and grant same permission, my client can call the service without problem.
So it leads me to think, for some reason if I use PowerShell the private key is screwed somehow.
The funny thing is in either way, I go to MMC and double click on my installed certificate I can see You have a private key that corresponds to the certificate. so it looks like private key is loaded even in PowerShell. permission settings are identical.
Any clue or experience?
Have same issue. Next script work:
function InstallCert ($certPath, [System.Security.Cryptography.X509Certificates.StoreName] $storeName)
{
[Reflection.Assembly]::Load("System.Security, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a")
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath, "", $flags)
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite);
$store.Add($cert);
$store.Close();
}
I updated Sergey's answer to the following. Note that the using namespace ... syntax is only valid for PS 5.0 and later. If you need this for an earlier version, you will have to add the full namespace, System.Security.Cryptography.X509Certificates, as needed.
using namespace System.Security
[CmdletBinding()]
param (
[parameter(mandatory=$true)] [string] $CertificateFile,
[parameter(mandatory=$true)] [securestring] $PrivateKeyPassword,
[parameter(mandatory=$true)] [string] $AllowedUsername
)
# Setup certificate
$Flags = [Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet `
-bor [Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet `
-bor [Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$Certificate = New-Object Cryptography.X509Certificates.X509Certificate2($CertificateFile, $PrivateKeyPassword, $Flags)
# Install certificate into machine store
$Store = New-Object Cryptography.X509Certificates.X509Store(
[Cryptography.X509Certificates.StoreName]::My,
[Cryptography.X509Certificates.StoreLocation]::LocalMachine)
$Store.Open([Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$Store.Add($Certificate)
$Store.Close()
# Allow read permission of private key by user
$PKFile = Get-ChildItem "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$($Certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
$PKAcl = $PKFile.GetAccessControl("Access")
$ReadAccessRule = New-Object AccessControl.FileSystemAccessRule(
$AllowedUsername,
[AccessControl.FileSystemRights]::Read,
[AccessControl.AccessControlType]::Allow
)
$PKAcl.AddAccessRule($ReadAccessRule)
Set-Acl $PKFile.FullName $PKAcl
Save this script to InstallCertificate.ps1, then run it as Administrator:
PS C:\Users\me> .\InstallCertificate.ps1
cmdlet InstallCertificate.ps1 at command pipeline position 1
Supply values for the following parameters:
CertificateFile: c:\my\path\mycert.pfx
PrivateKeyPassword: *********************
AllowedUsername: me
PS C:\Users\me> ls Cert:\LocalMachine\My
<Observe that your cert is now listed here. Get the thumbprint>
PS C:\Users\me> (ls Cert:\LocalMachine\My | ? { $_.Thumbprint -eq $Thumbprint }).PrivateKey
After rebooting, the last line should show that the private key is still installed even as non-Administrator.
Edited to add the ACL step as described in https://stackoverflow.com/a/37402173/7864889.
I had a similar issue on one of our dev servers when importing a certificate through the MMC. My problem was that the Administrators group did not have any permissions on the MachineKeys folder.
C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys
I added full control on the MachineKeys folder to Administrators and it was able to successfully create the private key when importing the certificate.
Make sure the user you're running Powershell under has access to write to the MachineKeys folder.
The following code referenced below, by Sergey Azarkevich, is what did the trick for me:
$flags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
I landed on this SO thread as the built in Import-PfxCertificate was not importing CAPI certificates correctly. Unfortunately powerdude's answer cmdlet didnt work for me as it threw The property 'CspKeyContainerInfo' cannot be found on this object. Verify that the property exists. when setting the permissions.
After combining it with this wonderful gist from
milesgratz it worked.
Here is the final modified version made to look like a Import-PfxCertificate substitution.
# Import-CapiPfxCertificate.ps1
# for CNG certificates use built in Import-PfxCertificate
using namespace System.Security
[CmdletBinding()]
param (
[parameter(mandatory=$true)] [string] $FilePath,
[parameter(mandatory=$true)] [securestring] $Password,
[parameter(mandatory=$true)] [string] $CertStoreLocation,
[parameter(mandatory=$false)] [string] $AllowedUsername
)
if (-not ($CertStoreLocation -match '^Cert:\\([A-Z]+)\\([A-Z]+)$')) {
Write-Host "Incorrect CertStoreLocation. See usage in the Import-PfxCertificate documentation" -ForegroundColor Red
exit 1;
}
$StoreName = $Matches.2
$StoreLocation = $Matches.1
# Setup certificate
$Flags = [Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet `
-bor [Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet `
-bor [Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$Certificate = New-Object Cryptography.X509Certificates.X509Certificate2($FilePath, $Password, $Flags)
# Install certificate into the specified store
$Store = New-Object Cryptography.X509Certificates.X509Store(
$StoreName,
$StoreLocation)
$Store.Open([Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$Store.Add($Certificate)
$Store.Close()
if (-not ([string]::IsNullOrEmpty($AllowedUsername))) {
# Allow read permission of private key by user
$PKUniqueName = ([System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate)).key.UniqueName
$PKFile = Get-Item "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$PKUniqueName"
$PKAcl = Get-Acl $PKFile
$PKAcl.AddAccessRule((New-Object AccessControl.FileSystemAccessRule($AllowedUsername, "Read", "Allow")))
Set-Acl $PKFile.FullName $PKAcl
}

New-PSDrive's "-Persist" flag not working: drives removed on reboot

The script mounts the drive correctly, but the drive is not persisted after rebooting the machine:
function RemapDrive {
param(
$DriveLetter,
$FullPath,
$Credential
)
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
# $DriveLetter must be concatenated with ":" for the command to work
net use "${DriveLetter}:" /del
## $DriveLetter cannot contain ":"
$psDrive = New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Credential $Credential -Scope "Global" -Persist
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X" -FullPath "\\my-server\x" -Credential $credential
What I have found:
“When you scope the command locally, that is, without dot-sourcing, the Persist parameter does not persist the creation of a PSDrive beyond the scope in which you run the command. If you run New-PSDrive inside a script, and you want the new drive to persist indefinitely, you must dot-source the script. For best results, to force a new drive to persist, specify Global as the value of the Scope parameter in addition to adding Persist to your command.”
I have tried executing the script with ". .\my-script.ps1" (to dot-source the script?), but the result is the same.
Playing around with "net use" and the registry to try to add the network drive has lead me to a cul-de-sac as well.
Specs:
Windows 10 Home
Powershell version:
Major Minor Build Revision
----- ----- ----- --------
5 1 18362 1171
Basically, New-PSDrive doesn't have the /SAVECRED parameter from net use, and will not persistently map drives as a user other than the one running the script.
There are three ways to handle this:
[Recommended] Fix the file share permissions instead of using a separate username/password, then use New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Scope 'Global' -Persist with no credential flag. This assumes your file share allows kerberos logins, so may not work in some edge cases.
Use net use, and include the username, password, /persistent:yes and /savecred. This can be done in powershell without any issues.
Set the powershell script you already have to run at startup.
Set up your script to use the credential manager - see the answer here
Install the CredentialManager powershell module
set HKCU\Network\[drive letter]\ConnectionType = 1
set HKCU\Network\[drive letter]\DeferFlags= 4
What finally work was user19702's option #2, with a bit of extra work regarding the registration of the username and the password.
WARNING: as he mentioned, the best option (option #1) would have been "fixing the file share permissions instead of using a separate username/password". This was not possible in my case, and this is why I had to go with option #2.
This is the script:
# ---
# Helper functions:
function RemapDrive {
param(
$DriveLetter,
$Server,
$FullPath,
$Credential
)
# For net.exe to work, DriveLetter must end with with ":"
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
net use "$DriveLetter" /del
# "net use" requires username and password as plain text
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.Password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$Username=$Credential.Username
Write-Host "Registring credentials for server '$Server' ..."
cmdkey /add:$Server /user:$Username /pass:$Password
Write-Host "Mapping the drive ..."
net use $DriveLetter $FullPath /persistent:yes i
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
# ---
# Process to execute:
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X:" -Server "my-server" -FullPath "\\my-server\x" -Credential $credential
If you do not want to use a hardcoded password in BuildCredential, but you want to prompt the user instead:
function GetCredential {
param(
$Label
)
$credential = Get-Credential -Message "Write your credentials for '$Label':"
if(!$credential) {
throw "A credential was needed to continue. Process aborted."
}
return $credential
}
Also, if instead of using $Server as a param, you want to extract it from $FullPath using regex, you can do that.
It presumes the $FullPath has the following format: \\server-name\dir1\dir2\etc
# Get server name using regex:
$FullPath -match '\\\\(.*?)\\.*?'
$Server = $Matches[1]

Getting private keys to work on windows 7 powershell version 2

Firstly, I know that very similar questions have been asked, but having read through the solutions and modifying my own workflow has not produced the correct results.
I am hoping that by showing the code I am using, someone may be able to point out where I am going wrong. I am trying to import a priate key from my windows 10 machine to my legacy windows 7 with powershell version 2 installed.
The error I am facing is that $cert.hasprivatekey returns true but $cert.privatekey always returns null. However this happens on the windows 10 machine as well so it seems to be a problem generating a key but every guide I have found uses the same syntax!
Here is the code to create the key:
$store = "cert:\CurrentUser\My"
$params = #{
CertStoreLocation = $store
Subject = "CN=Test1"
KeyLength = 2048
KeyAlgorithm = "RSA"
KeyUsage = "DataEncipherment"
Type = "DocumentEncryptionCert"
KeyExportPolicy = 'Exportable'
}
# generate new certificate and add it to certificate store
$cert = New-SelfSignedCertificate #params
Get-ChildItem -path $store
$pwd = ("P#ssword" | ConvertTo-SecureString -AsPlainText -Force)
$privateKey = "$home\Documents\Test1.pfx"
$publicKey = "$home\Documents\Test1.cer"
# Export private key as PFX certificate, to use those Keys on different machine/user
Export-PfxCertificate -FilePath $privateKey -Cert $cert -Password $pwd
# Export Public key, to share with other users
Export-Certificate -FilePath $publicKey -Cert $cert
I have aso tried this to no avail:
$TestCertificate = New-SelfSignedCertificate -Subject 'TestCertificate' -KeyExportPolicy 'Exportable'
Export-PfxCertificate -Cert $TestCertificate -FilePath .\TestCertificate.pfx -Password (ConvertTo-SecureString 'TestPassword' -AsPlainText -Force)
I am then trying to import the private pfx certificate on windows 7 using the following:
$PfxFilePath = "C:\Users\user\Desktop\Test1.pfx"
$pwd = ("P#ssword" | ConvertTo-SecureString -AsPlainText -Force)
$Password = $pwd
$absolutePfxFilePath = Resolve-Path -Path $PfxFilePath
Write-Output "Importing store certificate '$absolutePfxFilePath'..."
Add-Type -AssemblyName System.Security
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($absolutePfxFilePath, $Password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")
$Store = New-Object System.Security.Cryptography.X509Certificates.X509Store(
[System.Security.Cryptography.X509Certificates.StoreName]::My,
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::"ReadWrite")
$store.Add($cert)
$store.Close()
All ideas welcome!
The key is stored in Key Storage Provider which is not supported by PrivateKey property which is completely obsolete. Instead you need to use newer syntax to obtain private key:
$key = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)

PowerShell Install .exe application with Credentials stored in Clixml

Trying to create a Powershell script that installs an application (.exe) with stored credentials (Clixml).
Everything works fine when using:
Start-Process -FilePath "C:\Users\$($env:USERNAME)\Downloads\Software\Software.exe" -ArgumentList '/s' -Credential $credentials
But I would like a more elegant solution:
$startprocessParams = #{
FilePath = "C:\Users\$($env:USERNAME)\Downloads\Software\Software.exe"
ArgumentList = '/s'
Credential = $credentials
Verb = 'RunAs'
PassThru = $true
Wait = $true
}
$proc = Start-Process #startprocessParams
if ($proc.ExitCode -eq 0) {
'Software installed!'
}
else {
"Fail! Exit code: $($Proc.ExitCode)"
}
This works perfectly without the Credential parameter, you then get the "enter credentials/UAC" popup that I would like to avoid. With the Credential parameter I get this error:
Start-Process : Parameter set cannot be resolved using the specified name parameters.
What am I missing here? Appreciate any advice and/or guidance.
EDIT:
I use the following line to import the credentials:
$credentials = Import-Clixml "C:\Users\$Env:USERNAME\AppData\Local\Apps\SOFTWARE\cred.xml"
The credentials is created with a standard:
Get-Credential | Export-Clixml "C:\Users\$Env:USERNAME\AppData\Local\Apps\SOFTWARE\cred.xml"
This works as it should.
you need to set the credentials as PSCredential.
have a look at this solution:
$username = "username"
$password = "password"
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Start-Process dnscrypt-proxy.exe -WorkingDirectory path_here -Credential ($credentials)
is it stored in PSCredential in the first place?
Start-Process : Parameter set cannot be resolved using the specified name parameters.
The error tells us the set of parameters used is incorrect. Checking the MSDN doc or Get-Help for Start-Process will show that -Credential can not be used with -Verb.

Powershell: `GetNetworkCredential().Password` is not displaying all the characters of the password after `AppendChar()`

I have a cmdlet Append-SecureString.ps1 which provides padding of a desired length/size to a SecureString with a particular character('o' just for demonstration sake). And I am using another cmdlet Decode-SecureString.ps1 which obtains the plaintext from the SecureString.
The cmdlet Decode-SecureString.ps1
#Decode-SecureString.ps1
param([SecureString]$SecureString)
Write-Information -MessageData "Retrieving string..." -Verbose -InformationAction Continue
try{
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
$length = [Runtime.InteropServices.Marshal]::ReadInt32($bstr, -4)
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
}
finally{
if ( $bstr -ne [IntPtr]::Zero ) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
}
}
The cmdlet Append-SecureString.ps1
#Append-SecureString.ps1
param(
[Parameter(mandatory=$true)]
[System.Management.Automation.PSCredential]$Credential,
[Parameter(mandatory=$false)]
[int]$Length
)
while($Credential.Password.Length -lt $Length){
$Credential.Password.AppendChar('o')
}
$Credential.Password.Length
$Credential.GetNetworkCredential().Password
.\Decode-SecureString.ps1 -SecureString $Credential.Password #Custom cmdlet provided above.
And the result is:
$cred=Get-Credential -Message "Enter the credentials."
$cred.UserName
picachu
$cred.Password.Length
14
$cred.GetNetworkCredential().Password
THISISPASSWORD
.\AppendTo-SecureString.ps1 -Credential $cred -Length 64
64
THISISPASSWORD
Retrieving string...
THISISPASSWORDoooooooooooooooooooooooooooooooooooooooooooooooooo
So, as we see, $Credential.GetNetworkCredential().Password didnot display the complete string of the $Credential.Password which is a SecureString by the way. But my custom cmdlet Decode-SecureString successfully obtained the complete padded string from the $Credential.Password which is the SecureString.
So, can anybody pin out why GetNetworkCredential().Password didnot displayed the complete string, and if possible, how do you exactly make GetNetworkCredential().Password display the string behind the $Credential.Password without using my custom cmdlet Decode-SecureString.ps1 ?
I have edited the cmdlet AppendTo-SecureString.ps1 to workaround as below. It doesn't require Decode-SecureString.ps1 to display the characters anymore. The problem was that as #PetSerAl pointed out, the GetNetworkCredential() doesnot rebuild the cache for an already existing PSCredential object. So I decided to build another credential using the new SecureString and return it.
param(
[Parameter(mandatory=$true)]
[System.Management.Automation.PSCredential]$Credential,
[Parameter(mandatory=$false)]
[int]$Length
)
$secureString=$Credential.Password
while($secureString.Length -lt $Length){
$secureString.AppendChar('#')
}
$tempCred=New-Object System.Management.Automation.PSCredential -ArgumentList $Credential.UserName,$secureString
#Comment out below for returning the new credential.
$tempCred.Password.Length
#Comment out below for returning the new credential.
$tempCred.GetNetworkCredential().Password
#UnComment out below for returning the new credential.
###Return $tempCred
Or, you can skip rebuilding a new PSCredential object and use NetworkCredential as below:
$tempCred=([System.Net.NetworkCredential]::new($Credential.UserName,$secureString))
#Comment out below for returning the new credential.
$tempCred.Password.Length
#Comment out below for returning the new credential.
$tempCred.Password
#UnComment out below for returning the new credential.
###Return $tempCred