script/encryption/public/Get-DecryptedString.ps1

Function Get-DecryptedString {
    Param(
        [Parameter(Mandatory)][SecureString]$Passphrase,
        [Parameter(Mandatory, ValueFromPipeline)][string]$CipherText
    )

    Process {
        $derivationIterations = 1000

        # Get the complete stream of bytes that represent:
        # [32 bytes of Salt] + [16 bytes of IV] + [n bytes of CipherText]
        $cipherTextBytesWithSaltAndIv = [Convert]::FromBase64String($CipherText)
        # Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
        $saltStringBytes = $cipherTextBytesWithSaltAndIv | Select-Object -First 32
        # Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
        $ivStringBytes = $cipherTextBytesWithSaltAndIv | Select-Object -Skip 32 -First 16
        # Get the actual cipher text bytes by removing the first 48 bytes
        # from the cipherText string.
        $cipherTextBytes = $cipherTextBytesWithSaltAndIv | Select-Object -Skip 48

        try {
            $password = [System.Security.Cryptography.Rfc2898DeriveBytes]::new(
                ($Passphrase | ConvertFrom-SecureString -AsPlainText),
                $saltStringBytes,
                $derivationIterations)

            $keyBytes = $password.GetBytes(32);

            $symmetricKey = [System.Security.Cryptography.RijndaelManaged]::new()
            $symmetricKey.BlockSize = 128
            $symmetricKey.Mode = [System.Security.Cryptography.CipherMode]::CBC
            $symmetricKey.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7

            $decryptor = $symmetricKey.CreateDecryptor($keyBytes, $ivStringBytes)

            $memoryStream = [System.IO.MemoryStream]::new($cipherTextBytes)
            $cryptoStream = [System.Security.Cryptography.CryptoStream]::new(
                $memoryStream,
                $decryptor,
                "Read")

            $plainTextBytes = [byte[]]::new($cipherTextBytes.Length)

            $decryptedByteCount = $cryptoStream.Read($plainTextBytes, 0, $plainTextBytes.Length);
            $memoryStream.Close();
            $cryptoStream.Close();

            return [System.Text.Encoding]::Utf8.GetString($plainTextBytes, 0, $decryptedByteCount)
        }
        finally {
            $password ? $password.Dispose() : $null
            $symmetricKey ? $symmetricKey.Dispose() : $null
            $encryptor ? $encryptor.Dispose() : $null
            $memoryStream ? $memoryStream.Dispose() : $null
            $cryptoStream ? $cryptoStream.Dispose() : $null
        }
    }
}