PoshBytes: Encrypting secrets with Protect-CmsMessage (without summoning eldritch IT beings)

PoshBytes: Encrypting secrets with Protect-CmsMessage (without summoning eldritch IT beings)

Learn how to secure sensitive data in PowerShell using Protect-CmsMessage and Unprotect-CmsMessage. This PoshBytes episode covers how to encrypt, decrypt, and share secrets safely for real-world automation and configuration scenarios.

This post is a companion for the video embedded below. Scroll down to see the code from the video.

Create and share a team encryption certificate

Create a self‑signed Document Encryption cert (CurrentUser store)

$SSCertParams = @{
	Type              = 'DocumentEncryptionCert'
	Subject           = 'CN=TeamKey'
	KeyExportPolicy   = 'ExportableEncrypted'
	CertStoreLocation = 'Cert:\CurrentUser\My'
	NotAfter          = (Get-Date).AddYears(2)
}
$cert = New-SelfSignedCertificate @SSCertParams
$cert

Export the public cert to share with senders (encrypt-only)

Export-Certificate -Cert $cert -FilePath .\TeamKey.cer

Back up the private key

Back up the private key for yourself (decrypt); protect it with a password

$pw = Read-Host "PFX password" -AsSecureString
Export-PfxCertificate -Cert $cert -FilePath .\TeamKey.pfx -Password $pw

Restore the key where you need to decrypt

Later, import the PFX on a machine that should be able to decrypt

Import-PfxCertificate -FilePath .\TeamKey.pfx -CertStoreLocation Cert:\CurrentUser\My -Password $pw

Encrypt and decrypt a simple secret

Encrypt a simple secret and write a .cms file

Protect-CmsMessage -To "CN=TeamKey" -Content "DB_PASS=p@ssw0rd-please-don't-judge" -OutFile .\secret.env.cms

Show contents of protected file

Get-Content .\secret.env.cms

Decrypt when you have the private key

Returns plaintext to the pipeline; write as needed

Unprotect-CmsMessage -Path .\secret.env.cms

Extra handy demos

Decrypt .cms at runtime and set an env var for the current process

$kv = (Unprotect-CmsMessage -Path .\secret.env.cms) -split "=",2
[Environment]::SetEnvironmentVariable($kv[0], $kv[1])
$ENV:DB_PASS

• Protect-CmsMessage = Encrypt with Public key
• Unprotect-CmsMessage = Decrypt with Private key
• Great for configs, pipelines, logs, and team secrets
• No 3rd party apps or external modules required
• Back up your private key or kiss your data goodbye