Skip to content

Protect Data and Unprotect Data (the basics)

Dave Wyatt edited this page Apr 11, 2015 · 5 revisions

Overview


The Protect-Data and Unprotect-Data commands are what you use to encrypt and decrypt something that you want to keep secret. The current syntax of these commands looks like this:

Protect-Data [-InputObject] <Object> [[-Certificate] <Object[]>] 
[[-Password] <securestring[]>] [[-PasswordIterationCount] <int>] [-UseLegacyPadding] 
[<CommonParameters>]


Unprotect-Data -InputObject <Object> -Certificate <X509Certificate2> 
[<CommonParameters>]

Unprotect-Data -InputObject <Object> -Password <securestring> [<CommonParameters>]

The -InputObject parameter of the Protect-Data command is the piece of secret data that you want to encrypt. This may only be one of the types specified by the Get-ProtectedDataSupportedTypes command; currently, these are String, SecureString, PSCredential, and Byte[] . If you want to encrypt a type of data other than strings / secure strings / pscredentials, you will need to handle the serialization to and from a byte array yourself, and the ProtectedData module will take care of encrypting that byte array. Protect-Data will output a custom object containing the encrypted payload, and enough other information to decrypt it when a user with a valid certificate or password requests to do so.

The -InputObject parameter of Unprotect-Data, on the other hand, is the object that was produced by the Protect-Data command, and the output of Unprotect-Data will be whatever object was originally encrypted (string, SecureString, PSCredential, or byte array.)

The Certificates referred to by the -Certificate parameter can be either RSA certificates or ECDH (Elliptic Curve Diffie-Hellman) certificates. They must have, at a minimum, the Key Encipherment usage extension (for RSA) or the Key Agreement usage extension (for ECDH). You can encrypt the data using multiple certificates, if you like; any one of them can be used to decrypt the data later. You may pass these certificates to the -Certificate parameter in several ways: as an X509Certificate2 object, as a path to a certificate file on disk, as a path in PowerShell's Cert:\ drive, or as a certificate thumbprint (in which case the entire Cert:\ drive will be searched for a certificate with that thumbprint.)

As a backup mechanism, you may also pass in one or more SecureString objects to the Password parameter. This allows you to decrypt the data later by specifying the same password(s). While this does not help you to protect secret data without user interaction, it does give you a way to recover data later should you somehow lose the certificate or its private key.

The other optional parameters modify the behavior in the following ways:

  • -UseLegacyPadding: When you encrypt data using an RSA certificate, by default, it uses the OAEP (Optional Asymmetric Encryption Padding) algorithm. Some certificates will allow you to encrypt data successfully using this scheme, but for some reason, will not decrypt the data. I don't yet know how to identify ahead of time whether this is going to be the case, but in those situations, you may use the -UseLegacyPadding switch to tell the module to use PKCS#1 v1.5 padding instead, which should work.

  • -PasswordIterationCount: When using the -Password parameter, an encryption key is derived from that password using the PBKDF2 algorithm. You can tweak the iteration count of this algorithm, if desired; a higher iteration count makes the key derivation take longer, making it harder to crack by brute force. The default number of iterations is 50000.

Examples


$secretString = 'This is my secret'
$thumbprint = '26C4800B0B39DF1B06CEEA30DEB546AFFA62D464'

# Using an X509Certificate2 object
$cert = Get-Item Cert:\CurrentUser\My\$thumbprint
$protectedData = $secretString | Protect-Data -Certificate $cert
$decryptedString = $protectedData | Unprotect-Data -Certificate $cert

# Using a path to a file on disk.  (This will only work if the file is not password-protected;
# otherwise you need to load it up first to an X509Certificate2 object, as shown here in the
# example for Unprotect-Data.)

$protectedData = $secretString | Protect-Data -Certificate C:\MyCertificate.cer

# Note:  passwords may also be passed to the X509Certificate2 constructor as SecureString objects.
$cert = New-Object System.Security.Cryptography.X509Certificate2('C:\MyCertificate.pfx', 'MyPassword')

$decryptedString = $protectedData | Unprotect-Data -Certificate $cert

# Using a path in the PowerShell Cert:\ drive.
$protectedData = $secretString | Protect-Data -Certificate Cert:\CurrentUser\My\$thumbprint
$decryptedString = $protectedData | Unprotect-Data -Certificate Cert:\CurrentUser\My\$thumbprint

# Using a thumbprint.  (Note:  This option can be rather slow, particularly in PowerShell v2.)

$protectedData = $secretString | Protect-Data -Certificate $thumbprint
$decryptedString = $protectedData | Unprotect-Data -Certificate $thumbprint
Clone this wiki locally