[PowerShell] Cmdlets per proteggere i dati con DPAPI

Le DPAPI, per chi non le conoscesse, sono una manciata di API (CryptProtectData/CryptUnprotectData e CryptProtectMemory/CryptUnprotectMemory) con l'obiettivo di cryptare dati senza caricare l'utente o l'applicazione delle problematiche non banali associate allo gestione di una chiave.

Senza entrare nei dettagli, per i quali rimando al link precedente, la chiave usata da CryptProtectData è dipendente dalla password dell'account utente, per cui, in caso di reset della password, i dati precedentemente cryptati diventano inaccessibili. Questo livello di privacy è tipicamente considerato sufficiente in un'ampia gamma di applicazioni. Si pensi ad esempio alle password memorizzate da Internet Explorer per i siti web o da Explorer per accedere a risorse di rete (SMB, etc).

In .Net le DPAPI sono disponibili tramite P/Invoke, che ho wrappato in una piccola class library a sua volta referenziata da un assembly contenente un paio di cmdlets e uno snapin per l'installazione in PowerShell.  

Trovate binari e sorgenti qui: www.alessandropilotti.com/DPAPICmdlet-1.0.0.zip pubblicati con licenza MIT, ovvero fatene (quasi) ciò che vi pare. Leggete ReadMe.txt per installazione e utilizzo.

 Le cmdlets fornite sono 2 e sono di utilizzo a dir poco immediato:

  • Get-ProtectedData
  • Get-UnprotectedData

Ecco un semplice esempio. I dati, una volta cryptati vengono serializzati in un file temporaneo, dopodichè vengono deserializzati e decryptati.

# Simple Protect/Unprotect data sample.
# Encrypted data is persisted as xml
 
# Encrypt and export data
$d = [System.Text.Encoding]::UTF8.GetBytes("ciao")
@(,$d) | Get-ProtectedData | Export-CliXml $env:temp\test.xml
Remove-Variable d
 
# Import and decrypt data
$d = Import-CliXml $env:temp\test.xml | Get-UnprotectedData
$t = [System.Text.Encoding]::UTF8.GetString($d)
 
"Clear text: $t"

Riprendiamo l'esempio precedente, questa volta fornendo un'entropia aggiuntiva e definendo esplicitamente uno store (vi rimando alla documentazione su DPAPI per questi concetti).

# Simple Protect/Unprotect data sample using the given additional entropy 
# and assigned store. Encrypted data is persisted as xml
 
$e = [System.Text.Encoding]::UTF8.GetBytes("some additional entropy")
 
# Encrypt and export data
$d = [System.Text.Encoding]::UTF8.GetBytes("ciao")
@(,$d) | Get-ProtectedData -entropy $e -store Machine | Export-CliXml $env:temp\test.xml
 
# Import and decrypt data
$d = Import-CliXml $env:temp\test.xml | Get-UnprotectedData -entropy $e -store Machine
$t = [System.Text.Encoding]::UTF8.GetString($d)
 
"Clear text: $t"