Az előző fejezetben láthattuk a ConvertTo-SecureSting cmdlet alkalmazását u.n. SecureString típusú adatok létrehozására. Erre minden olyan esetben szükség lehet, amikor egy cmdlet ilyen típusú paramétert vár, általában hitelesítési adatok jelszavának megadásához. De nem csak erre használható, hanem például jelszavak sima szövegként történő tárolásához képest kicsit biztonságosabb tárolására is. Erre szükségünk lehet olyan esetben, amikor az automatizáltan futtatott szkriptünknek valamilyen más felhasználó nevében kell egy tevékenységet elvégeznie és ilyenkor nincs lehetőségünk a jelszó megadására, hanem a szkriptnek kell valahonnan, például egy fájlból, ezt megszereznie.
A ConvertTo-SecureString amikor titkosítja a paraméterként átadott szöveget, akkor a titkosításhoz egy, az adott géphez kötődő kulcsot használ. Ezt azért fontos tudni, mert ha az így titkosított szöveget egy másik gépen akarjuk visszafejteni, akkor az a másik kulcs miatt nem fog sikerülni. Így, ha a hordozhatóság is szempont, akkor a -key paraméternek átadott valamilyen ismert kulccsal kell titkosítanunk. Ez a kulcs lehet 16, 24 vagy 32 bájtot tartalmazó tömb.
Az alábbi Encrypt-String függvényben a $key kulcsot 16 véletlen számból (bájtból) hoztam létre, amit Base64 kódolással szövegként történő tárolásra alkalmassá tettem ($keybase64string). Miután 16 byte hosszúságú adat Base64 kódolása után az utolsó két karakter két egyenlőségjel lesz, ezért azokat lecsippentem, hogy a végső titkosított szövegben ne legyen ennyire látható, hogy ott egy Base64 szöveg vége lapul.
Ezután a paraméterként átadott SecureString-é alakítom. Ez egy bináris adat, amit nem lehet szövegként kiírni fájlban, így használom a ConvertFrom-SecureString cmdletet, hogy ebből a bináris adatból szöveget állítsak elő.
A legvégén a kulcs base64 szövegét és a SecureString szövegét összefűzöm, ez lesz a függvényem kimenete:
function Encrypt-String ($string){
$key = 1..16 | ForEach-Object {[byte] (Get-Random -Minimum 1 -Maximum 256)}
$keybase64string = [System.Convert]::ToBase64String($key).Substring(0,22)
$ss = ConvertTo-SecureString $string -Force -AsPlainText
$encodedss = $ss | ConvertFrom-SecureString -Key $key
$keybase64string + $encodedss
}
A visszaalakító Decrypt-String függvényem ezeket a lépéseket visszafelé végzi el. Elsőként leválasztja a titkosított szöveg első 22 karakterét, majd visszapótolja a két egyenlőségjelet, ez a visszafejtéshez szükséges kulcs Base64 kódolt változata. A maradék lesz a titkosított szöveg.
A kulcsot visszakonvertálom Base64-ből, a titkosított szöveget meg a ConvertTo-SecureString-el visszaalakítom SecureString-é a kulcs segítségével. Ebből, az előző fejezet trükkjével megkapható az eredeti jelszó:
function Decrypt-String ($encryptedstring){
$keybase64 = $encryptedstring.substring(0,22) + "=="
$encryptedstring = $encryptedstring.substring(22,$encryptedstring.length-22)
$key = [System.Convert]::FromBase64String($keybase64)
$ss = Convertto-SecureString $encryptedstring -Key $key
(New-Object System.Management.Automation.PSCredential('dummy',$ss)).GetNetworkCredential().password
}
Természetesen ez a módszer távolról sem tökéletes módszer jelszavak biztonságos tárolására, de mindenképpen jobb annál, mintha szabad szövegként tárolnánk azokat. Ha a fenti módszerrel tároljuk a jelszót egy fájlban, érdemes még NTFS jogosultságokkal leszűkíteni, hogy ki az, aki ezt a fájlt olvasni tudja és ezzel a védelemmel kiegészítve a jelszó „elrejtését” már kellő biztonságot kaphatunk.