By: Brenton Blawat
The encryption and decryption of strings is essential when creating an enterprise product that has clear text passwords. This function displays how to encrypt and decrypt a string using Powershell using Richard’s code located at http://poshcode.org/116. While I found his code very useful, he didn’t explain the syntax and is why I am reposting this with the proper information.
I also decided to make this into an endless loop for an administrator to use to encrypt multiple passwords in a row. I found this to be useful as I never had to encrypt just one password.
In order to ensure your application is safe from an attacker be certain to perform each of the following:
1. Change the $salt variable and $init variables. These variables should be at least 8 characters long but should be changed or your application is subject to a brute force attack if someone determines you are using my code!
function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput)
function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput)
2. Change the Passphrase that is passed into the function. I suggest a 12-18 character Passphrase to prevent the above brute force attack.
$encrypted = Encrypt-String $string "MyStrongPassword"
$encrypted = Encrypt-String $string "MyStrongPassword"
To use this Function:
Start > Run > Type powershell.exe –noexit c:\location\EncryptDecryptString.ps1
** When you are done close the window.
You will notice that I changed the Passphrase for both the username and the password. This is not necessary, however, it adds another layer of security. Try not to encrypt everything with the same passphrase. If one item gets compromised, everything encrypted under that passphrase is compromised.
#################
# Powershell Allows The Loading of .NET Assemblies
# Load the Security assembly to use with this script
#################
[Reflection.Assembly]::LoadWithPartialName("System.Security")
#################
# This function is to Encrypt A String.
# $string is the string to encrypt, $passphrase is a second security "password" that has to be passed to decrypt.
# $salt is used during the generation of the crypto password to prevent password guessing.
# $init is used to compute the crypto hash -- a checksum of the encryption
#################
function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput)
{
# Create a COM Object for RijndaelManaged Cryptography
$r = new-Object System.Security.Cryptography.RijndaelManaged
# Convert the Passphrase to UTF8 Bytes
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
# Convert the Salt to UTF Bytes
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
# Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
# Create the Intersecting Vector Cryptology Hash with the init
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
# Starts the New Encryption using the Key and IV
$c = $r.CreateEncryptor()
# Creates a MemoryStream to do the encryption in
$ms = new-Object IO.MemoryStream
# Creates the new Cryptology Stream --> Outputs to $MS or Memory Stream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"
# Starts the new Cryptology Stream
$sw = new-Object IO.StreamWriter $cs
# Writes the string in the Cryptology Stream
$sw.Write($String)
# Stops the stream writer
$sw.Close()
# Stops the Cryptology Stream
$cs.Close()
# Stops writing to Memory
$ms.Close()
# Clears the IV and HASH from memory to prevent memory read attacks
$r.Clear()
# Takes the MemoryStream and puts it to an array
[byte[]]$result = $ms.ToArray()
# Converts the array from Base 64 to a string and returns
return [Convert]::ToBase64String($result)
}
function Decrypt-String($Encrypted, $Passphrase, $salt="SaltCrypto", $init="IV_Password")
{
# If the value in the Encrypted is a string, convert it to Base64
if($Encrypted -is [string]){
$Encrypted = [Convert]::FromBase64String($Encrypted)
}
# Create a COM Object for RijndaelManaged Cryptography
$r = new-Object System.Security.Cryptography.RijndaelManaged
# Convert the Passphrase to UTF8 Bytes
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
# Convert the Salt to UTF Bytes
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
# Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
# Create the Intersecting Vector Cryptology Hash with the init
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
# Create a new Decryptor
$d = $r.CreateDecryptor()
# Create a New memory stream with the encrypted value.
$ms = new-Object IO.MemoryStream @(,$Encrypted)
# Read the new memory stream and read it in the cryptology stream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read"
# Read the new decrypted stream
$sr = new-Object IO.StreamReader $cs
# Return from the function the stream
Write-Output $sr.ReadToEnd()
# Stops the stream
$sr.Close()
# Stops the crypology stream
$cs.Close()
# Stops the memory stream
$ms.Close()
# Clears the RijndaelManaged Cryptology IV and Key
$r.Clear()
}
# This clears the screen of the output from the loading of the assembly.
cls
# $me will never = 1, so It will run indefinately
$me = 0
write-host "To End This Application, Close the Window"
Write-host ""
do
{
# Prompt the user for the password
$ustring = read-host "(Case Sensitive) Please Enter Username"
$pstring = read-host "(Case Sensitive) Please Enter User Password"
# Encrypt the string and store it into the $encrypted variable
$uencrypted = Encrypt-String $ustring "U_MyStrongPassword"
$pencrypted = Encrypt-String $pstring "P_MyStrongPassword"
# Write result to the screen
write-host "Encrypted Username is: $uencrypted"
write-host ""
write-host "Encrypted Password is: $pencrypted"
write-host ""
write-host "Testing Decryption of Username / Password..."
write-host ""
# Decrypts the string and stores the decrypted value in $decrypted
$udecrypted = Decrypt-String $uencrypted "U_MyStrongPassword"
$pdecrypted = Decrypt-String $pencrypted "P_MyStrongPassword"
# Writes the decrpted value to the screen
write-host "Decrypted Password is: $udecrypted"
write-host ""
write-host "Decrypted Password is: $pdecrypted"
}
while ($me -ne 1)
################# # Powershell Allows The Loading of .NET Assemblies # Load the Security assembly to use with this script ################# [Reflection.Assembly]::LoadWithPartialName("System.Security") ################# # This function is to Encrypt A String. # $string is the string to encrypt, $passphrase is a second security "password" that has to be passed to decrypt. # $salt is used during the generation of the crypto password to prevent password guessing. # $init is used to compute the crypto hash -- a checksum of the encryption ################# function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput) { # Create a COM Object for RijndaelManaged Cryptography $r = new-Object System.Security.Cryptography.RijndaelManaged # Convert the Passphrase to UTF8 Bytes $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) # Convert the Salt to UTF Bytes $salt = [Text.Encoding]::UTF8.GetBytes($salt) # Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 # Create the Intersecting Vector Cryptology Hash with the init $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] # Starts the New Encryption using the Key and IV $c = $r.CreateEncryptor() # Creates a MemoryStream to do the encryption in $ms = new-Object IO.MemoryStream # Creates the new Cryptology Stream --> Outputs to $MS or Memory Stream $cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write" # Starts the new Cryptology Stream $sw = new-Object IO.StreamWriter $cs # Writes the string in the Cryptology Stream $sw.Write($String) # Stops the stream writer $sw.Close() # Stops the Cryptology Stream $cs.Close() # Stops writing to Memory $ms.Close() # Clears the IV and HASH from memory to prevent memory read attacks $r.Clear() # Takes the MemoryStream and puts it to an array [byte[]]$result = $ms.ToArray() # Converts the array from Base 64 to a string and returns return [Convert]::ToBase64String($result) } function Decrypt-String($Encrypted, $Passphrase, $salt="SaltCrypto", $init="IV_Password") { # If the value in the Encrypted is a string, convert it to Base64 if($Encrypted -is [string]){ $Encrypted = [Convert]::FromBase64String($Encrypted) } # Create a COM Object for RijndaelManaged Cryptography $r = new-Object System.Security.Cryptography.RijndaelManaged # Convert the Passphrase to UTF8 Bytes $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) # Convert the Salt to UTF Bytes $salt = [Text.Encoding]::UTF8.GetBytes($salt) # Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 # Create the Intersecting Vector Cryptology Hash with the init $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] # Create a new Decryptor $d = $r.CreateDecryptor() # Create a New memory stream with the encrypted value. $ms = new-Object IO.MemoryStream @(,$Encrypted) # Read the new memory stream and read it in the cryptology stream $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" # Read the new decrypted stream $sr = new-Object IO.StreamReader $cs # Return from the function the stream Write-Output $sr.ReadToEnd() # Stops the stream $sr.Close() # Stops the crypology stream $cs.Close() # Stops the memory stream $ms.Close() # Clears the RijndaelManaged Cryptology IV and Key $r.Clear() } # This clears the screen of the output from the loading of the assembly. cls # $me will never = 1, so It will run indefinately $me = 0 write-host "To End This Application, Close the Window" Write-host "" do { # Prompt the user for the password $ustring = read-host "(Case Sensitive) Please Enter Username" $pstring = read-host "(Case Sensitive) Please Enter User Password" # Encrypt the string and store it into the $encrypted variable $uencrypted = Encrypt-String $ustring "U_MyStrongPassword" $pencrypted = Encrypt-String $pstring "P_MyStrongPassword" # Write result to the screen write-host "Encrypted Username is: $uencrypted" write-host "" write-host "Encrypted Password is: $pencrypted" write-host "" write-host "Testing Decryption of Username / Password..." write-host "" # Decrypts the string and stores the decrypted value in $decrypted $udecrypted = Decrypt-String $uencrypted "U_MyStrongPassword" $pdecrypted = Decrypt-String $pencrypted "P_MyStrongPassword" # Writes the decrpted value to the screen write-host "Decrypted Password is: $udecrypted" write-host "" write-host "Decrypted Password is: $pdecrypted" } while ($me -ne 1)
To use this Function:
Start > Run > Type powershell.exe –noexit c:\location\EncryptDecryptStringUP.ps1
#################
# Powershell Allows The Loading of .NET Assemblies
# Load the Security assembly to use with this script
#################
[Reflection.Assembly]::LoadWithPartialName("System.Security")
#################
# This function is to Encrypt A String.
# $string is the string to encrypt, $passphrase is a second security "password" that has to be passed to decrypt.
# $salt is used during the generation of the crypto password to prevent password guessing.
# $init is used to compute the crypto hash -- a checksum of the encryption
#################
function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput)
{
# Create a COM Object for RijndaelManaged Cryptography
$r = new-Object System.Security.Cryptography.RijndaelManaged
# Convert the Passphrase to UTF8 Bytes
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
# Convert the Salt to UTF Bytes
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
# Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
# Create the Intersecting Vector Cryptology Hash with the init
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
# Starts the New Encryption using the Key and IV
$c = $r.CreateEncryptor()
# Creates a MemoryStream to do the encryption in
$ms = new-Object IO.MemoryStream
# Creates the new Cryptology Stream --> Outputs to $MS or Memory Stream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"
# Starts the new Cryptology Stream
$sw = new-Object IO.StreamWriter $cs
# Writes the string in the Cryptology Stream
$sw.Write($String)
# Stops the stream writer
$sw.Close()
# Stops the Cryptology Stream
$cs.Close()
# Stops writing to Memory
$ms.Close()
# Clears the IV and HASH from memory to prevent memory read attacks
$r.Clear()
# Takes the MemoryStream and puts it to an array
[byte[]]$result = $ms.ToArray()
# Converts the array from Base 64 to a string and returns
return [Convert]::ToBase64String($result)
}
function Decrypt-String($Encrypted, $Passphrase, $salt="SaltCrypto", $init="IV_Password")
{
# If the value in the Encrypted is a string, convert it to Base64
if($Encrypted -is [string]){
$Encrypted = [Convert]::FromBase64String($Encrypted)
}
# Create a COM Object for RijndaelManaged Cryptography
$r = new-Object System.Security.Cryptography.RijndaelManaged
# Convert the Passphrase to UTF8 Bytes
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
# Convert the Salt to UTF Bytes
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
# Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
# Create the Intersecting Vector Cryptology Hash with the init
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
# Create a new Decryptor
$d = $r.CreateDecryptor()
# Create a New memory stream with the encrypted value.
$ms = new-Object IO.MemoryStream @(,$Encrypted)
# Read the new memory stream and read it in the cryptology stream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read"
# Read the new decrypted stream
$sr = new-Object IO.StreamReader $cs
# Return from the function the stream
Write-Output $sr.ReadToEnd()
# Stops the stream
$sr.Close()
# Stops the crypology stream
$cs.Close()
# Stops the memory stream
$ms.Close()
# Clears the RijndaelManaged Cryptology IV and Key
$r.Clear()
}
# This clears the screen of the output from the loading of the assembly.
cls
# $me will never = 1, so It will run indefinately
$me = 0
write-host "To End This Application, Close the Window"
Write-host ""
do
{
# Prompt the user for the password
$string = read-host "Please Enter User Password"
# Encrypt the string and store it into the $encrypted variable
$encrypted = Encrypt-String $string "MyStrongPassword"
# Write result to the screen
write-host "Encrypted Password is: $encrypted"
write-host ""
write-host "Testing Decryption of Password..."
# Decrypts the string and stores the decrypted value in $decrypted
$decrypted = Decrypt-String $encrypted "MyStrongPassword"
# Writes the decrpted value to the screen
write-host "Decrypted Password is: $decrypted"
write-host ""
}
while ($me -ne 1)
################# # Powershell Allows The Loading of .NET Assemblies # Load the Security assembly to use with this script ################# [Reflection.Assembly]::LoadWithPartialName("System.Security") ################# # This function is to Encrypt A String. # $string is the string to encrypt, $passphrase is a second security "password" that has to be passed to decrypt. # $salt is used during the generation of the crypto password to prevent password guessing. # $init is used to compute the crypto hash -- a checksum of the encryption ################# function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput) { # Create a COM Object for RijndaelManaged Cryptography $r = new-Object System.Security.Cryptography.RijndaelManaged # Convert the Passphrase to UTF8 Bytes $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) # Convert the Salt to UTF Bytes $salt = [Text.Encoding]::UTF8.GetBytes($salt) # Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 # Create the Intersecting Vector Cryptology Hash with the init $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] # Starts the New Encryption using the Key and IV $c = $r.CreateEncryptor() # Creates a MemoryStream to do the encryption in $ms = new-Object IO.MemoryStream # Creates the new Cryptology Stream --> Outputs to $MS or Memory Stream $cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write" # Starts the new Cryptology Stream $sw = new-Object IO.StreamWriter $cs # Writes the string in the Cryptology Stream $sw.Write($String) # Stops the stream writer $sw.Close() # Stops the Cryptology Stream $cs.Close() # Stops writing to Memory $ms.Close() # Clears the IV and HASH from memory to prevent memory read attacks $r.Clear() # Takes the MemoryStream and puts it to an array [byte[]]$result = $ms.ToArray() # Converts the array from Base 64 to a string and returns return [Convert]::ToBase64String($result) } function Decrypt-String($Encrypted, $Passphrase, $salt="SaltCrypto", $init="IV_Password") { # If the value in the Encrypted is a string, convert it to Base64 if($Encrypted -is [string]){ $Encrypted = [Convert]::FromBase64String($Encrypted) } # Create a COM Object for RijndaelManaged Cryptography $r = new-Object System.Security.Cryptography.RijndaelManaged # Convert the Passphrase to UTF8 Bytes $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) # Convert the Salt to UTF Bytes $salt = [Text.Encoding]::UTF8.GetBytes($salt) # Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 # Create the Intersecting Vector Cryptology Hash with the init $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] # Create a new Decryptor $d = $r.CreateDecryptor() # Create a New memory stream with the encrypted value. $ms = new-Object IO.MemoryStream @(,$Encrypted) # Read the new memory stream and read it in the cryptology stream $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" # Read the new decrypted stream $sr = new-Object IO.StreamReader $cs # Return from the function the stream Write-Output $sr.ReadToEnd() # Stops the stream $sr.Close() # Stops the crypology stream $cs.Close() # Stops the memory stream $ms.Close() # Clears the RijndaelManaged Cryptology IV and Key $r.Clear() } # This clears the screen of the output from the loading of the assembly. cls # $me will never = 1, so It will run indefinately $me = 0 write-host "To End This Application, Close the Window" Write-host "" do { # Prompt the user for the password $string = read-host "Please Enter User Password" # Encrypt the string and store it into the $encrypted variable $encrypted = Encrypt-String $string "MyStrongPassword" # Write result to the screen write-host "Encrypted Password is: $encrypted" write-host "" write-host "Testing Decryption of Password..." # Decrypts the string and stores the decrypted value in $decrypted $decrypted = Decrypt-String $encrypted "MyStrongPassword" # Writes the decrpted value to the screen write-host "Decrypted Password is: $decrypted" write-host "" } while ($me -ne 1)
Happy Coding!