Skip to content

Instantly share code, notes, and snippets.

@dindoliboon
Last active August 12, 2020 22:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dindoliboon/9c23391a93d57f17e31dedcb999f1738 to your computer and use it in GitHub Desktop.
Save dindoliboon/9c23391a93d57f17e31dedcb999f1738 to your computer and use it in GitHub Desktop.
Encrypt and decrypt with PowerShell
function Get-PlaintextFromSecureString([SecureString]$SecureString) {
return (New-Object -TypeName System.Net.NetworkCredential('fake-user', $SecureString, 'fake-domain')).Password
}
function EncryptStringToBytes([String]$Plaintext, [System.Security.SecureString]$Password) {
# C# code from:
# https://gist.github.com/mark-adams/87aa34da3a5ed48ed0c7
# https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=netframework-4.8
$Aes = $null
$Encryptor = $null
$StreamWriter = $null
$CryptoStream = $null
$MemoryStream = $null
try {
$PlaintextPassword = Get-PlaintextFromSecureString -SecureString $Password
$Aes = [System.Security.Cryptography.Aes]::Create()
$Aes.Key = [System.Security.Cryptography.HashAlgorithm]::Create('SHA256').ComputeHash([System.Text.Encoding]::UTF8.GetBytes($PlaintextPassword))
$Aes.GenerateIV()
$Aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
# Create an encryptor to perform the stream transform.
$Encryptor = $Aes.CreateEncryptor($Aes.Key, $Aes.IV)
# Create the streams used for encryption.
$MemoryStream = [System.IO.MemoryStream]::new()
$CryptoStream = [System.Security.Cryptography.CryptoStream]::new($MemoryStream, $Encryptor, [System.Security.Cryptography.CryptoStreamMode]::Write)
$StreamWriter = [System.IO.StreamWriter]::new($CryptoStream)
# Write all data to the stream.
$StreamWriter.Write($Plaintext)
$StreamWriter.Close()
$CryptoStream.Close()
$EncryptedBytes = $MemoryStream.ToArray()
$MemoryStream.Close()
# Append the initialization vector to the encrypted bytes.
$CipherTextWithIv = New-Object -TypeName Byte[] -ArgumentList ($Aes.IV.Length + $EncryptedBytes.Length)
[Array]::Copy($Aes.IV, 0, $CipherTextWithIv, 0, $Aes.IV.Length)
[Array]::Copy($EncryptedBytes, 0, $CipherTextWithIv, $Aes.IV.Length, $EncryptedBytes.Length)
# Return the encrypted bytes with initialization vector.
Write-Output -InputObject $CipherTextWithIv
}
finally {
if ($null -ne $StreamWriter) { $StreamWriter.Dispose() }
if ($null -ne $CryptoStream) { $CryptoStream.Dispose() }
if ($null -ne $MemoryStream) { $MemoryStream.Dispose() }
if ($null -ne $Encryptor) { $Encryptor.Dispose() }
if ($null -ne $Aes) { $Aes.Dispose() }
}
}
function DecryptStringFromBytes([byte[]]$Ciphertext, [System.Security.SecureString]$Password) {
# C# code from:
# https://gist.github.com/mark-adams/87aa34da3a5ed48ed0c7
# https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=netframework-4.8
$Aes = $null
$Decryptor = $null
$StreamReader = $null
$CryptoStream = $null
$MemoryStream = $null
try {
$PlaintextPassword = Get-PlaintextFromSecureString -SecureString $Password
# Use the SHA256 hash of the password as the key.
$Aes = [System.Security.Cryptography.Aes]::Create()
$Aes.Key = [System.Security.Cryptography.HashAlgorithm]::Create('SHA256').ComputeHash([System.Text.Encoding]::UTF8.GetBytes($PlaintextPassword))
# Extract the initialization vector and encrypted bytes.
$BitsInByte = 8
$InitializationVector = New-Object -TypeName Byte[] -ArgumentList ($Aes.BlockSize / $BitsInByte)
$EncryptedBytes = New-Object -TypeName Byte[] -ArgumentList ($Ciphertext.Length - $InitializationVector.Length)
[Array]::Copy($Ciphertext, $InitializationVector, $InitializationVector.Length)
[Array]::Copy($Ciphertext, $InitializationVector.Length, $EncryptedBytes, 0, $EncryptedBytes.Length)
$Aes.IV = $InitializationVector
$Aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
# Create a decryptor to perform the stream transform.
$Decryptor = $Aes.CreateDecryptor($Aes.Key, $Aes.IV)
# Create the streams used for decryption.
$MemoryStream = [System.IO.MemoryStream]::new($EncryptedBytes)
$CryptoStream = [System.Security.Cryptography.CryptoStream]::new($MemoryStream, $Decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)
$StreamReader = [System.IO.StreamReader]::new($CryptoStream)
# Read the decrypted bytes from the decrypting stream
# and place them in a string.
$Plaintext = $StreamReader.ReadToEnd()
$StreamReader.Close()
$CryptoStream.Close()
$MemoryStream.Close()
Write-Output -InputObject $Plaintext
}
finally {
if ($null -ne $StreamReader) { $StreamReader.Dispose() }
if ($null -ne $CryptoStream) { $CryptoStream.Dispose() }
if ($null -ne $MemoryStream) { $MemoryStream.Dispose() }
if ($null -ne $Decryptor) { $Decryptor.Dispose() }
if ($null -ne $Aes) { $Aes.Dispose() }
}
}
@dindoliboon
Copy link
Author

Example using text files.

$Password = Read-Host -Prompt 'Enter a password' -AsSecureString

# Create a plaintext file then read the contents.
Out-File -Path 'plaintext.txt' -Encoding utf8 -InputObject "this is my plaintext message`r`n`r`nLine 3"
$Plaintext = [System.IO.File]::ReadAllText('plaintext.txt')

# Encrypt file contents and save to a new file.
$EncryptedBytes = EncryptStringToBytes -Plaintext $Plaintext -Password $Password
[System.IO.File]::WriteAllBytes('ciphertext.txt', $EncryptedBytes)

# Read encrypted bytes from a file, then decrypt to a string.
$EncryptedBytes = [System.IO.File]::ReadAllBytes('ciphertext.txt')
DecryptStringFromBytes -Ciphertext $EncryptedBytes -Password $Password

@dindoliboon
Copy link
Author

Example using a string.

$Password = Read-Host -Prompt 'Enter a password' -AsSecureString

# Encrypt a string and save as a BASE64 encoded string.
$EncryptedBytes = EncryptStringToBytes -Plaintext 'this is my plaintext message' -Password $Password
$EncryptedBytesBase64 = [Convert]::ToBase64String($EncryptedBytes)

$EncryptedBytesBase64 would have a value similar to neVhMpKHsxDsDYhdfCygTD46yc/7AGNYQNlKACCDrrcW0RGG8N5xf1xmZXLDJNzX

# Convert a BASE64 string to a byte array, then decrypt to a string.
$EncryptedBytes = [Convert]::FromBase64String($EncryptedBytesBase64)
DecryptStringFromBytes -Ciphertext $EncryptedBytes -Password $Password

With the correct password, DecryptStringFromBytes should print this is my plaintext message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment