4

I wasn't able to find good powershell functions to utilize asymmetric encryption so I created the following. Would like any feedback in terms of improvement as I'm a crypto noob. With the caveat that these functions are very basic. There isn't error checking and the write-host after a decrypt is hardly necessary. Just want to establish the core functionality before adding things like protected memory and such.

This has been successfully tested on two systems: Win8 w/Powershell v3 & Win2008R2 w/Powershell v2.

Function Encrypt-Asymmetric([string]$Encrypt,[string]$CertPath,[string]$XmlExportPath)
{
    # Encrypts a string with a public key
    $pubcer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertPath)
    $byteval = [System.Text.Encoding]::UTF8.GetBytes($Encrypt)
    $pubcer.PublicKey.Key.Encrypt($byteval,$true) | Export-Clixml -Path $XmlExportPath    
}

Function Decrypt-Asymmetric([string]$XmlPath,[string]$CertThumbprint)
{
    # Decrypts cipher text using the private key
    # Assumes the certificate is in the LocalMachine store
    $store = new-object System.Security.Cryptography.X509Certificates.X509Store([System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
    $store.open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
    $cer = $store.Certificates | %{if($_.thumbprint -eq $CertThumbprint){$_}}
    $ciphertext = Import-Clixml -Path $XmlPath
    $decryptedBytes = $cer.PrivateKey.Decrypt($ciphertext,$true)
    $ClearText = [System.Text.Encoding]::UTF8.GetString($decryptedBytes)
    Write-Host $ClearText
}
tshepang
  • 12,111
  • 21
  • 91
  • 136
user2320464
  • 359
  • 1
  • 5
  • 11
  • Do you have a specific question? Just asking for general feedback isn't a good fit for this site. – zdan Jun 08 '13 at 00:50
  • @zdan. Because I'm a crypto noob my concern is whether or not I'm using the crypto functions properly. When putting together the above lines I came across this post [http://stackoverflow.com/questions/7539984/asymetric-cryptography-example-in-c-sharp/7540173#7540173](http://stackoverflow.com/questions/7539984/asymetric-cryptography-example-in-c-sharp/7540173#7540173) which inspired me to take a similar approach. Also compared to the crypto functions in the prior link, I feel like there's something left out even though testing is successful. – user2320464 Jun 08 '13 at 02:26
  • Where are you getting your keys from? Are you making them yourself via powershell? – Samuel Meddows Jun 25 '13 at 00:57
  • In this case, the local certificate store. The public key was exported so Encrypt-Asymmetric can be used at other locations. – user2320464 Nov 05 '13 at 21:08

1 Answers1

7

I know this is old. I took the starting point you had here and added some items. I tried to clean where appropriate and use variable names that might help make things a little more easier for someonelse that reads this to understand.

Encryption:

Function Encrypt-Asymmetric {
[CmdletBinding()]
[OutputType([System.String])]
param(
    [Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
    $ClearText,
    [Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][ValidateScript({Test-Path $_ -PathType Leaf})][System.String]
    $PublicCertFilePath
)
# Encrypts a string with a public key
$PublicCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($PublicCertFilePath)
$ByteArray = [System.Text.Encoding]::UTF8.GetBytes($ClearText)
$EncryptedByteArray = $PublicCert.PublicKey.Key.Encrypt($ByteArray,$true)
$EncryptedBase64String = [Convert]::ToBase64String($EncryptedByteArray)

Return $EncryptedBase64String 
}

Decryption:

Function Decrypt-Asymmetric
{
[CmdletBinding()]
[OutputType([System.String])]
param(
    [Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
    $EncryptedBase64String,
    [Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
    $CertThumbprint
)
# Decrypts text using the private key
# Assumes the certificate is in the LocalMachine\My (Personal) Store
$Cert = Get-ChildItem cert:\LocalMachine\My | where { $_.Thumbprint -eq $CertThumbprint }
if($Cert) {
    $EncryptedByteArray = [Convert]::FromBase64String($EncryptedBase64String)
    $ClearText = [System.Text.Encoding]::UTF8.GetString($Cert.PrivateKey.Decrypt($EncryptedByteArray,$true))
}
Else {Write-Error "Certificate with thumbprint: $CertThumbprint not found!"}

Return $ClearText
}

http://grokgarble.com/blog/?p=228

Jeff
  • 536
  • 6
  • 8