Database, Software, and System Engineering

Asymmetric Encryption of Text using x.509 Certificates in PowerShell

I’ve been requested to encryption sections of my script (user name/password) using a certificate issued by a trusted CA.  No problem.

To do this in the blog, I’ll I created a self-signed x.509 certificate and a CN of “PowerShellCert”.  I will use the public portion of the certificate in a file that’s base64 .cer to encrypt the sections. That certificate I’ll place in the Windows key store and referenced by thumbprint for decryption.  For the actual work, I’ll import the CA trusted certificate into the same key store, replace the thumbprint with that CA trusted one and make sure the certificate is trusted either by the user or machine the script is running.

Here’s the command used with the makecert utility to create a 2048 length cert:

C:\Program Files\Microsoft SDKs\Windows\v7.1>makecert.exe -r -pe -n "CN=PowerShellCert" -ss my -sr localmachine -eku -len 2048 -e 01/01/2030 C:\Scripts\PowerShell\Asymmetrical-Encryption\PowerShellAsymmetrical.cer

Here’s the encryption function:

Function Encrypt-Asymmetric {
		[Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
		[Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][ValidateScript({Test-Path $_ -PathType Leaf})][System.String]
    # 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)
	$Base64String = [Convert]::ToBase64String($EncryptedByteArray)

	Return $Base64String 

…here’s the decryption function:

Function Decrypt-Asymmetric
		[Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
		[Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
    # Decrypts cipher 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

To Encrypt clear text:

PS C:\>Encrypt-Asymmetric -ClearText "CLEAR TEXT DATA" -PublicCertFilePath "C:\Scripts\PowerShell\Asymmetrical-Encryption\PowerShellAsymmetricalTest.cer"

To Decrypt clear text:

PS C:\>Decrypt-Asymmetric -EncryptedBase64String $Base64String -CertThumbprint "83D2D68907681EF3D823B23DEE24B0CBB3FA3C51"

To find your Certificate’s thumbprint (assuming you gave it the same name as I did above):

PS C:\> Get-ChildItem cert:\LocalMachine\My | where { $_.Subject -eq "CN=PowerShellCert" } | select Thumbprint

Now, encryption keys can be garded under the Windows key store.

, ,

One thought on “Asymmetric Encryption of Text using x.509 Certificates in PowerShell

  •' Dan says:

    Hi Jeff,

    Great script and functions!
    Unfortunately your decrypt Function doesn’t work with the certificate you were creating in the step before. You must add “-sky Exchange” to your makecert.exe command to ensure this certificate can be used for key exchange.
    Instead you will receive the following error: “Exception calling “Decrypt” with “2″ argument(s): “Bad Key”.

    Thanks to Joe Clancy from stackoverflow for this hint:

    Hopefully it will help some people. I struggled with this problem a few hours ;-)


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>