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"