Replace Encryption methods #32

Closed
opened 2018-12-17 11:35:19 +01:00 by OCram85 · 0 comments
Owner

🔩

Due to PowerShell Core limits / issue we can't use ConvertFrom-SecureString to retrieve the passwords from the Credential Store for the Core variant of this module.

🥇 Alternate Password Encryption

A while ago I stumbled upon an interesting article about using certificates for encrypting the keys:

So unfortunately there is no Certificate PSProvider in for PowerShell Core. But luckily the used decrypt and encrypt methods are still available if we use the Get-PfxCertificate.

🔎 Protoyping

Meanwhile I plumbed up a quick prototype which evaluates this workflow:

  1. Creating a self signed PFX certificate manually with openssl
  2. Creating a secure string with the above mentioned procedure.
  3. Transfering the encrypted string onto a windows machine
  4. try to connect to a VMware vcenter using the SecureString

Encrypt

try {
    $secureString = 'This is my password.  There are many like it, but this one is mine.' | 
                    ConvertTo-SecureString -AsPlainText -Force  
    $key = New-Object byte[](32)
    $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()
    $rng.GetBytes($key)
    $encryptedString = ConvertFrom-SecureString -SecureString $secureString -Key $key
    $cert = Get-PfxCertificate -FilePath './certificate.pfx'
    $encryptedKey = $cert.PublicKey.Key.Encrypt($key,[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1)
    $object = New-Object psobject -Property @{
        Key = $encryptedKey
        Payload = $encryptedString
    }
    $object | Export-Clixml './encryptionTest.xml'
}
finally {
    if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) }
}

Decrypt

try {
    $object = Import-Clixml -Path './encryptionTest.xml'
    $cert = Get-PfxCertificate -FilePath './certificate.pfx'
    $key = $cert.PrivateKey.Decrypt($object.Key, [System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1)
    $secureString = $object.Payload | ConvertTo-SecureString -Key $key
    Import-Module -Name Vmware*
    $creds = [PSCredential]::new('myUser', $SecureString)
    Connect-VIServer -Server 'vcenter01' -Credential $creds
    Get-VM -Name 'testvm'
}
finally {
    if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) }
}

Credits

  • Already a huge thanks to @dlwyatt for the template and inspiration!
## :nut_and_bolt: Due to [PowerShell Core limits / issue](https://github.com/PowerShell/PowerShell/issues/1654) we can't use `ConvertFrom-SecureString` to retrieve the passwords from the _Credential Store_ for the Core variant of this module. ## :1st_place_medal: Alternate Password Encryption A while ago I stumbled upon an interesting article about using certificates for encrypting the keys: - [Part1](https://powershell.org/2013/11/24/saving-passwords-and-preventing-other-processes-from-decrypting-them/) - [Part2](https://powershell.org/2014/02/01/revisited-powershell-and-encryption/) So unfortunately there is no `Certificate PSProvider` in for PowerShell Core. But luckily the used `decrypt` and `encrypt` methods are still available if we use the `Get-PfxCertificate`. ## :mag_right: Protoyping Meanwhile I plumbed up a quick prototype which evaluates this workflow: 1. Creating a self signed PFX certificate manually with `openssl` 2. Creating a secure string with the above mentioned procedure. 3. Transfering the encrypted string onto a windows machine 4. try to connect to a VMware vcenter using the SecureString ### Encrypt ```powershell try { $secureString = 'This is my password. There are many like it, but this one is mine.' | ConvertTo-SecureString -AsPlainText -Force $key = New-Object byte[](32) $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create() $rng.GetBytes($key) $encryptedString = ConvertFrom-SecureString -SecureString $secureString -Key $key $cert = Get-PfxCertificate -FilePath './certificate.pfx' $encryptedKey = $cert.PublicKey.Key.Encrypt($key,[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1) $object = New-Object psobject -Property @{ Key = $encryptedKey Payload = $encryptedString } $object | Export-Clixml './encryptionTest.xml' } finally { if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) } } ``` ### Decrypt ```powershell try { $object = Import-Clixml -Path './encryptionTest.xml' $cert = Get-PfxCertificate -FilePath './certificate.pfx' $key = $cert.PrivateKey.Decrypt($object.Key, [System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1) $secureString = $object.Payload | ConvertTo-SecureString -Key $key Import-Module -Name Vmware* $creds = [PSCredential]::new('myUser', $SecureString) Connect-VIServer -Server 'vcenter01' -Credential $creds Get-VM -Name 'testvm' } finally { if ($null -ne $key) { [array]::Clear($key, 0, $key.Length) } } ``` ## Credits - Already a huge thanks to @dlwyatt for the template and inspiration!
Sign in to join this conversation.
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: OCram85/PSCredentialStore#32
No description provided.