Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of how to use the ProtectedData PowerShell module to encrypt and decrypt credentials using a certificate
<#
These are examples of the process flow of using the ProtectedData PowerShell Module to encrypt a credential using certificates
on two servers
https://github.com/dlwyatt/ProtectedData
This does not represent a recommended approach, per se, but it does offer another secure means of persisting credentials to
a file vs. using DPAPI (Data Protection API); it's mainly written to help people grasp some basic concepts of asymmetric
encryption, in action.
This method offers a few benefits over using DPAPI { Convert[To|From]-SecureString }:
1. Data can be encrypted and decrypted by more than one user account and on more than one system (any system that has the
cert(s).
2. As a result of the previous point, encrypted data can be shared across systems
These examples assume you have done the following on two different servers:
1. Downloaded the ProtectedData module and it exists in C:\ProgramFiles\WindowsPowerShell\Modules
2. Have the following dirs setup: C:\tmp (this can be changed, just go through the example code and change it)
#>
# exit, in case someone executes
Write-Warning -Message "This is a file that contains examples; it is not meant to be ran as a script; exiting."
exit
# ____ _
# / ___| ___ _ ____ _____ _ __ / |
# \___ \ / _ \ '__\ \ / / _ \ '__|____| |
# ___) | __/ | \ V / __/ | |_____| |
# |____/ \___|_| \_/ \___|_| |_|
#
# import test utils from ProtectedData module root
. 'C:\Program Files\WindowsPowerShell\Modules\ProtectedData\TestUtils.ps1'
# generate the proper cert and grab the output. which contains the thumbprint
$certThumbprint = New-TestCertificate -Subject "CN=PS Automation"
# check to see if the cert got created
Get-KeyEncryptionCertificate -CertificateThumbprint $certThumbprint
# save the cert
$cert = Get-KeyEncryptionCertificate -CertificateThumbprint $certThumbprint
# secure credential with generated cert and save to a file
$protectedCredential = Get-Credential -Message 'Enter credential you would like to encrypt' | Protect-Data -Certificate $cert
$protectedCredential | Export-CliXml 'c:\tmp\protectedCred.xml'
# decrypt credential
Import-CliXml -FilePath 'c:\tmp\protectedCred.xml' | Unprotect-Data -Certificate $cert # not specifying -Certificate should also work
# work with decrypted credential with a variable
$decryptedCredential = Import-CliXml -FilePath 'c:\tmp\protectedCred.xml' | Unprotect-Data -Certificate $cert
$decryptedCredential.GetNetworkCredential()|select username,password
# how to export the public cert
Export-Certificate -Cert $cert -FilePath 'C:\tmp\PS Automation.cer'
# how to export the private & public cert chain
$pfxPassword = Read-Host -Prompt 'Enter a password that will be used to secure your certificate' -AsSecureString
Export-PfxCertificate -Cert $cert -FilePath 'C:\tmp\PS Automation.pfx' -Password $pfxPassword
# ____ ____
# / ___| ___ _ ____ _____ _ __ |___ \
# \___ \ / _ \ '__\ \ / / _ \ '__|____ __) |
# ___) | __/ | \ V / __/ | |_____/ __/
# |____/ \___|_| \_/ \___|_| |_____|
#
<#
Two options when importing the cert:
1. Import the public key cert (.cer): You will only be able to encrypt data and send to SERVER-1; SERVER-1 can decrypt (it has the private key)
2. Import the private/public pfx cert (.pfx): You will be able to decrypt anything that was encrypted with the public key of the cert, in this
example, if you pick this option, you will be able to encrypt & decrypt on both systems, using the generated cert
In either case, copy the cert file(s) from SERVER-1 to SERVER-2
#>
# import public key cert; I find it easiest to CD to the CERT:\ PSDrive and perform the import, there.
cd cert:\currentuser\my
Import-Certificate -FilePath 'C:\tmp\PS Automation.cer'
cd c:\ # get back to C:\
# check to see if you have the cert
Get-KeyEncryptionCertificate | where subject -like "CN=PS Automation"
# import private/public pfx certificate (this can be done in place of the previous step, or after it; both will work)
$pfxPassword = Read-Host -Prompt 'Enter the password you used to secure the cert when exporting' -AsSecureString
cd cert:\currentuser\my # get back to CERT:\
Import-PfxCertificate -FilePath 'C:\tmp\PS Automation.pfx' -Password $pfxPassword
# check to see if you have the cert
Get-KeyEncryptionCertificate | where subject -like "CN=PS Automation"
# if the cert is there, let's save it
$cert = Get-KeyEncryptionCertificate | where subject -like "CN=PS Automation"
# I'll assume you copied the secure credential file over to SERVER-2, so, let's decrypt it
Import-CliXml -FilePath 'c:\tmp\protectedCred.xml' | Unprotect-Data -Certificate $cert
<#
Not specifying -Certificate should also work ONLY if you imported the .pfx cert. If you only imported the public cert,
you will get an error when trying this.
#>
# work with decrypted credential with a variable
$decryptedCredential = Import-CliXml -FilePath 'c:\tmp\protectedCred.xml' | Unprotect-Data -Certificate $cert
$decryptedCredential.GetNetworkCredential()|select username,password
<#
Note about exporting certs from SERVER-2:
• You will be able to export the public cert (.cer)
• You will NOT be able to export the private/public (.pfx) cert; you can only export this cert from SERVER-1,
where it was generated (this is at least true for these examples)
#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment