-
-
Save Kagre/e8825af009d243542041a786230f4600 to your computer and use it in GitHub Desktop.
Convert the AESThenHMAC code example to script for best practice encrypting a string in PowerShell. It uses authenticated encryption. http://stackoverflow.com/a/10366194/637783
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
* This work (Modern Encryption of a String C#, by James Tuley), | |
* identified by James Tuley, is free of known copyright restrictions. | |
* https://gist.github.com/4336842 | |
* http://creativecommons.org/publicdomain/mark/1.0/ | |
#> | |
#using System; | |
#using System.IO; | |
#using System.Security.Cryptography; | |
#using System.Text; | |
#namespace Encryption | |
.{ class AESThenHMAC { | |
hidden static [System.Security.Cryptography.RandomNumberGenerator] $Random = ([System.Security.Cryptography.RandomNumberGenerator]::Create()); | |
#Preconfigured Encryption Parameters | |
static [int] $BlockBitSize = 128; | |
static [int] $KeyBitSize = 256; | |
#Preconfigured Password Key Derivation Parameters | |
static [int] $SaltBitSize = 64; | |
static [int] $Iterations = 10000; | |
static [int] $MinPasswordLength = 12; | |
# <summary> | |
# Helper that generates a random key on each call. | |
# </summary> | |
# <returns></returns> | |
static [byte[]] NewKey(){ | |
$key = new-object byte[] ([AESThenHMAC]::KeyBitSize / 8); | |
[AESThenHMAC]::Random.GetBytes($key); | |
return $key; | |
} | |
# <summary> | |
# Simple Encryption (AES) then Authentication (HMAC) for a UTF8 Message. | |
# </summary> | |
# <param name="secretMessage">The secret message.</param> | |
# <param name="cryptKey">The crypt key.</param> | |
# <param name="authKey">The auth key.</param> | |
# <param name="nonSecretPayload">(Optional) Non-Secret Payload.</param> | |
# <returns> | |
# Encrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">Secret Message Required!;secretMessage</exception> | |
# <remarks> | |
# Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize + HMac-Tag(32)) * 1.33 Base64 | |
# </remarks> | |
static [string] SimpleEncrypt( | |
[string]$secretMessage, | |
[byte[]]$cryptKey, | |
[byte[]]$authKey, | |
[byte[]]$nonSecretPayload = $null | |
){ | |
if([string]::IsNullOrEmpty($secretMessage)) | |
{throw [System.ArgumentException]::new("Secret Message Required!", "secretMessage")} | |
$plainText = [System.Text.Encoding]::UTF8.GetBytes($secretMessage); | |
$cipherText = [AESThenHMAC]::SimpleEncrypt($plainText, $cryptKey, $authKey, $nonSecretPayload); | |
return ([System.Convert]::ToBase64String($cipherText)) | |
} | |
# <summary> | |
# Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message. | |
# </summary> | |
# <param name="encryptedMessage">The encrypted message.</param> | |
# <param name="cryptKey">The crypt key.</param> | |
# <param name="authKey">The auth key.</param> | |
# <param name="nonSecretPayloadLength">Length of the non secret payload.</param> | |
# <returns> | |
# Decrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception> | |
static [string] SimpleDecrypt( | |
[string]$encryptedMessage, | |
[byte[]]$cryptKey, | |
[byte[]]$authKey, | |
[int]$nonSecretPayloadLength = 0 | |
){ | |
if([string]::IsNullOrWhiteSpace($encryptedMessage)) | |
{throw [System.ArgumentException]::new("Encrypted Message Required!", "encryptedMessage");} | |
$cipherText = [System.Convert]::FromBase64String($encryptedMessage); | |
$plainText = [AESThenHMAC]::SimpleDecrypt($cipherText, $cryptKey, $authKey, $nonSecretPayloadLength); | |
if($plainText -eq $null){return $null} | |
return ([System.Text.Encoding]::UTF8.GetString($plainText)) | |
} | |
# <summary> | |
# Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message | |
# using Keys derived from a Password (PBKDF2). | |
# </summary> | |
# <param name="secretMessage">The secret message.</param> | |
# <param name="password">The password.</param> | |
# <param name="nonSecretPayload">The non secret payload.</param> | |
# <returns> | |
# Encrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">password</exception> | |
# <remarks> | |
# Significantly less secure than using random binary keys. | |
# Adds additional non secret payload for key generation parameters. | |
# </remarks> | |
static [string] SimpleEncryptWithPassword( | |
[string]$secretMessage, | |
[string]$password, | |
[byte[]]$nonSecretPayload = $null | |
){ | |
if([string]::IsNullOrEmpty($secretMessage)) | |
{throw [System.ArgumentException]::new("Secret Message Required!", "secretMessage")} | |
$plainText = [System.Text.Encoding]::UTF8.GetBytes($secretMessage); | |
$cipherText = [AESThenHMAC]::SimpleEncryptWithPassword($plainText, $password, $nonSecretPayload); | |
return ([System.Convert]::ToBase64String($cipherText)) | |
} | |
# <summary> | |
# Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message | |
# using keys derived from a password (PBKDF2). | |
# </summary> | |
# <param name="encryptedMessage">The encrypted message.</param> | |
# <param name="password">The password.</param> | |
# <param name="nonSecretPayloadLength">Length of the non secret payload.</param> | |
# <returns> | |
# Decrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception> | |
# <remarks> | |
# Significantly less secure than using random binary keys. | |
# </remarks> | |
static [string] SimpleDecryptWithPassword( | |
[string]$encryptedMessage, | |
[string]$password, | |
[int]$nonSecretPayloadLength = 0 | |
){ | |
if([string]::IsNullOrWhiteSpace($encryptedMessage)) | |
{throw [System.ArgumentException]::new("Encrypted Message Required!", "encryptedMessage")} | |
$cipherText = [System.Convert]::FromBase64String($encryptedMessage); | |
$plainText = [AESThenHMAC]::SimpleDecryptWithPassword($cipherText, $password, $nonSecretPayloadLength); | |
if($plainText -eq $null){return $null} | |
return ([System.Text.Encoding]::UTF8.GetString($plainText)) | |
} | |
# <summary> | |
# Simple Encryption(AES) then Authentication (HMAC) for a UTF8 Message. | |
# </summary> | |
# <param name="secretMessage">The secret message.</param> | |
# <param name="cryptKey">The crypt key.</param> | |
# <param name="authKey">The auth key.</param> | |
# <param name="nonSecretPayload">(Optional) Non-Secret Payload.</param> | |
# <returns> | |
# Encrypted Message | |
# </returns> | |
# <remarks> | |
# Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize + HMac-Tag(32)) * 1.33 Base64 | |
# </remarks> | |
static [byte[]] SimpleEncrypt( | |
[byte[]]$secretMessage, | |
[byte[]]$cryptKey, | |
[byte[]]$authKey, | |
[byte[]]$nonSecretPayload = $null | |
){ | |
#User Error Checks | |
if($cryptKey -eq $null -or $cryptKey.Length -ne ([AESThenHMAC]::KeyBitSize / 8)) | |
{throw [System.ArgumentException]::new(("Key needs to be {0} bit!" -f [AESThenHMAC]::KeyBitSize), "cryptKey")} | |
if($authKey -eq $null -or $authKey.Length -ne ([AESThenHMAC]::KeyBitSize / 8)) | |
{throw [System.ArgumentException]::new(("Key needs to be {0} bit!" -f [AESThenHMAC]::KeyBitSize), "authKey")} | |
if($secretMessage -eq $null -or $secretMessage.Length -lt 1) | |
{throw [System.ArgumentException]::new("Secret Message Required!", "secretMessage")} | |
#non-secret payload optional | |
if($nonSecretPayload -eq $null){[byte[]]$nonSecretPayload = @()} | |
#byte[] cipherText; | |
#byte[] iv; | |
$aes = [System.Security.Cryptography.AesManaged]::new() | |
$aes.KeySize = [AESThenHMAC]::KeyBitSize | |
$aes.BlockSize = [AESThenHMAC]::BlockBitSize | |
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC | |
$aes.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 | |
#Use random IV | |
$aes.GenerateIV(); | |
$iv = $aes.IV; | |
$encrypter = $aes.CreateEncryptor($cryptKey, $iv) | |
$cipherStream = [System.IO.MemoryStream]::new() | |
$cryptoStream = [System.Security.Cryptography.CryptoStream]::new($cipherStream, $encrypter, [System.Security.Cryptography.CryptoStreamMode]::Write) | |
$binaryWriter = [System.IO.BinaryWriter]::new($cryptoStream) | |
#Encrypt Data | |
$binaryWriter.Write($secretMessage); | |
$cryptoStream.Dispose();$binaryWriter.Dispose(); | |
$cipherText = $cipherStream.ToArray(); | |
$encrypter.Dispose();$cipherStream.Dispose() | |
$aes.Dispose() | |
#Assemble encrypted message and add authentication | |
$hmac = [System.Security.Cryptography.HMACSHA256]::new($authKey) | |
$encryptedStream = [System.IO.MemoryStream]::new() | |
$binaryWriter = [System.IO.BinaryWriter]::new($encryptedStream) | |
#Prepend non-secret payload if any | |
$binaryWriter.Write($nonSecretPayload); | |
#Prepend IV | |
$binaryWriter.Write($iv); | |
#Write Ciphertext | |
$binaryWriter.Write($cipherText); | |
$binaryWriter.Flush(); | |
#Authenticate all data | |
$tag = $hmac.ComputeHash($encryptedStream.ToArray()); | |
#Postpend tag | |
$binaryWriter.Write($tag); | |
$ret = $encryptedStream.ToArray() | |
$binaryWriter.Dispose() | |
$hmac.Dispose();$encryptedStream.Dispose(); | |
return $ret | |
} | |
# <summary> | |
# Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message. | |
# </summary> | |
# <param name="encryptedMessage">The encrypted message.</param> | |
# <param name="cryptKey">The crypt key.</param> | |
# <param name="authKey">The auth key.</param> | |
# <param name="nonSecretPayloadLength">Length of the non secret payload.</param> | |
# <returns>Decrypted Message</returns> | |
static [byte[]] SimpleDecrypt( | |
[byte[]]$encryptedMessage, | |
[byte[]]$cryptKey, | |
[byte[]]$authKey, | |
[int]$nonSecretPayloadLength = 0 | |
){ | |
#Basic Usage Error Checks | |
if($cryptKey -eq $null -or $cryptKey.Length -ne ([AESThenHMAC]::KeyBitSize / 8)) | |
{throw [System.ArgumentException]::new(("Key needs to be {0} bit!" -f [AESThenHMAC]::KeyBitSize), "cryptKey")} | |
if($authKey -eq $null -or $authKey.Length -ne ([AESThenHMAC]::KeyBitSize / 8)) | |
{throw [System.ArgumentException]::new(("Key needs to be {0} bit!" -f [AESThenHMAC]::KeyBitSize), "authKey")} | |
if($encryptedMessage -eq $null -or $encryptedMessage.Length -eq 0) | |
{throw [System.ArgumentException]::new("Encrypted Message Required!", "encryptedMessage")} | |
$hmac = [System.Security.Cryptography.HMACSHA256]::new($authKey) | |
$sentTag = new-object byte[] ($hmac.HashSize / 8) | |
#Calculate Tag | |
$calcTag = $hmac.ComputeHash($encryptedMessage, 0, $encryptedMessage.Length - $sentTag.Length); | |
$ivLength = ([AESThenHMAC]::BlockBitSize / 8); | |
#if message length is to small just return null | |
if($encryptedMessage.Length -lt $sentTag.Length + $nonSecretPayloadLength + $ivLength) | |
{return $null} | |
#Grab Sent Tag | |
[Array]::Copy($encryptedMessage, $encryptedMessage.Length - $sentTag.Length, $sentTag, 0, $sentTag.Length); | |
#Compare Tag with constant time comparison | |
$compare = 0; | |
for($i = 0; $i -lt $sentTag.Length; $i++) | |
{$compare = $compare -bOr ($sentTag[$i] -bXor $calcTag[$i])} | |
#if message doesn't authenticate return null | |
if($compare -ne 0) | |
{return $null} | |
$aes = [System.Security.Cryptography.AesManaged]::new() | |
$aes.KeySize = [AESThenHMAC]::KeyBitSize | |
$aes.BlockSize = [AESThenHMAC]::BlockBitSize | |
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC | |
$aes.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 | |
#Grab IV from message | |
$iv = new-object byte[] $ivLength; | |
[Array]::Copy($encryptedMessage, $nonSecretPayloadLength, $iv, 0, $iv.Length); | |
$decrypter = $aes.CreateDecryptor($cryptKey, $iv) | |
$plainTextStream = [System.IO.MemoryStream]::new() | |
$decrypterStream = [System.Security.Cryptography.CryptoStream]::new($plainTextStream, $decrypter, [System.Security.Cryptography.CryptoStreamMode]::Write) | |
$binaryWriter = [System.IO.BinaryWriter]::new($decrypterStream) | |
#Decrypt Cipher Text from Message | |
$binaryWriter.Write( | |
$encryptedMessage, | |
$nonSecretPayloadLength + $iv.Length, | |
$encryptedMessage.Length - $nonSecretPayloadLength - $iv.Length - $sentTag.Length | |
); | |
$decrypterStream.Dispose();$binaryWriter.Dispose(); | |
#Return Plain Text | |
$ret = $plainTextStream.ToArray() | |
$decrypter.Dispose();$plainTextStream.Dispose() | |
$aes.Dispose() | |
$hmac.Dispose() | |
return $ret | |
} | |
# <summary> | |
# Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message | |
# using Keys derived from a Password (PBKDF2) | |
# </summary> | |
# <param name="secretMessage">The secret message.</param> | |
# <param name="password">The password.</param> | |
# <param name="nonSecretPayload">The non secret payload.</param> | |
# <returns> | |
# Encrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">Must have a password of minimum length;password</exception> | |
# <remarks> | |
# Significantly less secure than using random binary keys. | |
# Adds additional non secret payload for key generation parameters. | |
# </remarks> | |
static [byte[]] SimpleEncryptWithPassword( | |
[byte[]]$secretMessage, | |
[string]$password, | |
[byte[]]$nonSecretPayload = $null | |
){ | |
if($nonSecretPayload -eq $null){[byte[]]$nonSecretPayload = @()} | |
#User Error Checks | |
if([string]::IsNullOrWhiteSpace($password) -or $password.Length -lt [AESThenHMAC]::MinPasswordLength) | |
{throw [System.ArgumentException]::new(("Must have a password of at least {0} characters!" -f [AESThenHMAC]::MinPasswordLength), "password")} | |
if($secretMessage -eq $null -or $secretMessage.Length -eq 0) | |
{throw [System.ArgumentException]::new("Secret Message Required!", "secretMessage")} | |
$payload = new-object byte[] ((([AESThenHMAC]::SaltBitSize / 8) * 2) + $nonSecretPayload.Length); | |
[Array]::Copy($nonSecretPayload, $payload, $nonSecretPayload.Length); | |
[int]$payloadIndex = $nonSecretPayload.Length; | |
#byte[] cryptKey; | |
#byte[] authKey; | |
#Use Random Salt to prevent pre-generated weak password attacks. | |
$generator = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($password, ([AESThenHMAC]::SaltBitSize / 8), [AESThenHMAC]::Iterations) | |
$salt = $generator.Salt; | |
#Generate Keys | |
$cryptKey = $generator.GetBytes(([AESThenHMAC]::KeyBitSize / 8)); | |
#Create Non Secret Payload | |
[Array]::Copy($salt, 0, $payload, $payloadIndex, $salt.Length); | |
$payloadIndex += $salt.Length; | |
$generator.Dispose() | |
#Deriving separate key, might be less efficient than using HKDF, | |
#but now compatible with RNEncryptor which had a very similar wireformat and requires less code than HKDF. | |
$generator = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($password, ([AESThenHMAC]::SaltBitSize / 8), [AESThenHMAC]::Iterations) | |
$salt = $generator.Salt; | |
#Generate Keys | |
$authKey = $generator.GetBytes(([AESThenHMAC]::KeyBitSize / 8)); | |
#Create Rest of Non Secret Payload | |
[Array]::Copy($salt, 0, $payload, $payloadIndex, $salt.Length); | |
$generator.Dispose() | |
return ([AESThenHMAC]::SimpleEncrypt($secretMessage, $cryptKey, $authKey, $payload)) | |
} | |
# <summary> | |
# Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message | |
# using keys derived from a password (PBKDF2). | |
# </summary> | |
# <param name="encryptedMessage">The encrypted message.</param> | |
# <param name="password">The password.</param> | |
# <param name="nonSecretPayloadLength">Length of the non secret payload.</param> | |
# <returns> | |
# Decrypted Message | |
# </returns> | |
# <exception cref="System.ArgumentException">Must have a password of minimum length;password</exception> | |
# <remarks> | |
# Significantly less secure than using random binary keys. | |
# </remarks> | |
static [byte[]] SimpleDecryptWithPassword( | |
[byte[]]$encryptedMessage, | |
[string]$password, | |
[int]$nonSecretPayloadLength = 0 | |
){ | |
#User Error Checks | |
if([string]::IsNullOrWhiteSpace($password) -or $password.Length -lt [AESThenHMAC]::MinPasswordLength) | |
{throw [System.ArgumentException]::new(("Must have a password of at least {0} characters!" -f [AESThenHMAC]::MinPasswordLength), "password")} | |
if($encryptedMessage -eq $null -or $encryptedMessage.Length -eq 0) | |
{throw [System.ArgumentException]::new("Encrypted Message Required!", "encryptedMessage")} | |
$cryptSalt = new-object byte[] ([AESThenHMAC]::SaltBitSize / 8); | |
$authSalt = new-object byte[] ([AESThenHMAC]::SaltBitSize / 8); | |
#Grab Salt from Non-Secret Payload | |
[Array]::Copy($encryptedMessage, $nonSecretPayloadLength, $cryptSalt, 0, $cryptSalt.Length); | |
[Array]::Copy($encryptedMessage, $nonSecretPayloadLength + $cryptSalt.Length, $authSalt, 0, $authSalt.Length); | |
#byte[] cryptKey; | |
#byte[] authKey; | |
#Generate crypt key | |
$generator = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($password, $cryptSalt, [AESThenHMAC]::Iterations) | |
$cryptKey = $generator.GetBytes(([AESThenHMAC]::KeyBitSize / 8)); | |
$generator.Dispose() | |
#Generate auth key | |
$generator = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($password, $authSalt, [AESThenHMAC]::Iterations) | |
$authKey = $generator.GetBytes(([AESThenHMAC]::KeyBitSize / 8)); | |
$generator.Dispose() | |
return ([AESThenHMAC]::SimpleDecrypt($encryptedMessage, $cryptKey, $authKey, $cryptSalt.Length + $authSalt.Length + $nonSecretPayloadLength)); | |
} | |
}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Pester'ng the AESThenHMAC class library | |
.EXAMPLE | |
Invoke-Pester .\AESThenHMAC.Tests.ps1 | |
#>param() | |
. (join-path $PSScriptRoot 'AESThenHMAC.ps1') | |
$ProjectName = 'AESThenHMAC' | |
$DebugPreference = 'Continue' | |
$SkipSlowTests = $true | |
$ExceptionText = @{} | |
$ExceptionText.secretMessage = @' | |
System.ArgumentException: Secret Message Required! | |
Parameter name: secretMessage | |
'@ | |
$ExceptionText.encryptedMessage = @' | |
System.ArgumentException: Encrypted Message Required! | |
Parameter name: encryptedMessage | |
'@ | |
$ExceptionText.cryptKey = @' | |
System.ArgumentException: Key needs to be {0} bit! | |
Parameter name: cryptKey | |
'@ -f [AESThenHMAC]::KeyBitSize | |
$ExceptionText.authKey = @' | |
System.ArgumentException: Key needs to be {0} bit! | |
Parameter name: authKey | |
'@ -f [AESThenHMAC]::KeyBitSize | |
$ExceptionText.password = @' | |
System.ArgumentException: Must have a password of at least {0} characters! | |
Parameter name: password | |
'@ -f [AESThenHMAC]::MinPasswordLength | |
function get-exception{ | |
param([ScriptBlock]$code) | |
try{$null = & $code}catch {return $_.Exception} | |
} | |
################################################################# | |
Describe "$ProjectName Unit Tests" -Tag 'Unit' { | |
It 'the get-exception tool works' {get-exception {throw 'foo'} | out-string | should be "foo`r`n"} | |
Context 'Encryption Constants' { | |
It 'has KeyBitSize > 255' {[AESThenHMAC]::KeyBitSize | should BeGreaterThan 255} | |
It 'has BlockBitSize > 0' {[AESThenHMAC]::BlockBitSize | should BeGreaterThan 0} | |
It 'has SaltBitSize > 63' {[AESThenHMAC]::SaltBitSize | should BeGreaterThan 63} | |
It 'has Iterations > 9999' {[AESThenHMAC]::Iterations | should BeGreaterThan 9999} | |
It 'has MinPasswordLength > 10' {[AESThenHMAC]::MinPasswordLength | should BeGreaterThan 10} | |
} | |
Context 'When using the NewKey method' { | |
It 'provides a key' { | |
$res = [AESThenHMAC]::NewKey() | |
$res.GetType() | should be byte[] | |
$res.Length | should be ([AESThenHMAC]::KeyBitSize / 8) | |
} | |
It 'provides 1000 unique keys' { | |
$KeyDict = @{}; $Dupes = 0 | |
for($i=0;$i -lt 1000; $i++){ | |
$key = [System.Convert]::ToBase64String([AESThenHMAC]::NewKey()) | |
$KeyDict.$key++ | |
} | |
$KeyDict.Count | should BeGreaterThan 995 #over-kill, there's no way 1000 random keys has 5 dupes | |
} -Skip:$SkipSlowTests | |
} | |
[byte[]]$cryptKey = 1..([AESThenHMAC]::KeyBitSize / 8) | |
[byte[]]$authKey = ([AESThenHMAC]::KeyBitSize / 8)..1 | |
[byte[]]$nonSecretPayload = $null | |
[int]$nonSecretPayloadLength = 0 | |
[string]$password = 'a' * ([AESThenHMAC]::MinPasswordLength + 1) | |
$ogMessage = 'Text to be encrypted' | |
$ogNonSecretPayload = 'Clear Text' | |
Context 'When using the SimpleEncrypt(string,byte[],byte[],byte[]) method' { | |
[string]$secretMessage = $ogMessage | |
It 'throws on null and empty SecretMessage' { | |
[string]$secretMessage = '' | |
get-exception {[AESThenHMAC]::SimpleEncrypt($null,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
} | |
It 'encrypts secretMessage with nonSecretPayload' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
$locked = [AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload) | |
[AESThenHMAC]::SimpleDecrypt($locked,$cryptKey,$authKey,$nonSecretPayload.Length) | should be $ogMessage | |
} | |
It 'encrypts secretMessage without nonSecretPayload' { | |
$locked = [AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$null) | |
[AESThenHMAC]::SimpleDecrypt($locked,$cryptKey,$authKey,0) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleEncrypt(byte[],byte[],byte[],byte[]) method' { | |
[byte[]]$secretMessage = [char[]]$ogMessage | |
It 'throws on null and empty SecretMessage' { | |
[byte[]]$secretMessage = @() | |
get-exception {[AESThenHMAC]::SimpleEncrypt($null,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
} | |
It 'throws on null, empty, and wrong size cryptKey' { | |
[byte[]]$cryptKey = @() | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$null,$authKey,$nonSecretPayload)} | should be $ExceptionText.cryptKey | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.cryptKey | |
[byte[]]$cryptKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) - 1) | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.cryptKey | |
[byte[]]$cryptKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) + 1) | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.cryptKey | |
} | |
It 'throws on null, empty, and wrong size authKey' { | |
[byte[]]$authKey = @() | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$null,$nonSecretPayload)} | should be $ExceptionText.authKey | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.authKey | |
[byte[]]$authKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) - 1) | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.authKey | |
[byte[]]$authKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) + 1) | |
get-exception {[AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload)} | should be $ExceptionText.authKey | |
} | |
It 'encrypts secretMessage with nonSecretPayload' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
$locked = [AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$nonSecretPayload) | |
$AsBytes = [AESThenHMAC]::SimpleDecrypt($locked,$cryptKey,$authKey,$nonSecretPayload.Length) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
It 'encrypts secretMessage without nonSecretPayload' { | |
$locked = [AESThenHMAC]::SimpleEncrypt($secretMessage,$cryptKey,$authKey,$null) | |
$AsBytes = [AESThenHMAC]::SimpleDecrypt($locked,$cryptKey,$authKey,0) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleDecrypt(string,byte[],byte[],int) method' { | |
[string]$encryptedMessage = 'Good Base64 String' | |
It 'throws on null and empty encryptedMessage' { | |
[string]$encryptedMessage = '' | |
get-exception {[AESThenHMAC]::SimpleDecrypt($null,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
} | |
It 'decrypts encryptedMessage with nonSecretPayloadLength' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncrypt($ogMessage,$cryptKey,$authKey,$nonSecretPayload) | |
[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayload.Length) | should be $ogMessage | |
} | |
It 'decrypts encryptedMessage without nonSecretPayloadLength' { | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncrypt($ogMessage,$cryptKey,$authKey,$null) | |
[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,0) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleDecrypt(byte[],byte[],byte[],int) method' { | |
[byte[]]$encryptedMessage = [System.Convert]::FromBase64String('Good Base64 String') | |
It 'throws on null and empty encryptedMessage' { | |
[byte[]]$encryptedMessage = @() | |
get-exception {[AESThenHMAC]::SimpleDecrypt($null,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
} | |
It 'throws on null, empty, and wrong size cryptKey' { | |
[byte[]]$cryptKey = @() | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$null,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.cryptKey | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.cryptKey | |
[byte[]]$cryptKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) - 1) | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.cryptKey | |
[byte[]]$cryptKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) + 1) | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.cryptKey | |
} | |
It 'throws on null, empty, and wrong size authKey' { | |
[byte[]]$authKey = @() | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$null,$nonSecretPayloadLength)} | should be $ExceptionText.authKey | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.authKey | |
[byte[]]$authKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) - 1) | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.authKey | |
[byte[]]$authKey = @(0) * (([AESThenHMAC]::KeyBitSize / 8) + 1) | |
get-exception {[AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayloadLength)} | should be $ExceptionText.authKey | |
} | |
It 'decrypts encryptedMessage with nonSecretPayloadLength' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncrypt($ogMessage,$cryptKey,$authKey,$nonSecretPayload) | |
[byte[]]$encryptedMessage = [System.Convert]::FromBase64String($encryptedMessage) | |
$AsBytes = [AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,$nonSecretPayload.Length) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
It 'decrypts encryptedMessage without nonSecretPayloadLength' { | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncrypt($ogMessage,$cryptKey,$authKey,$null) | |
[byte[]]$encryptedMessage = [System.Convert]::FromBase64String($encryptedMessage) | |
$AsBytes = [AESThenHMAC]::SimpleDecrypt($encryptedMessage,$cryptKey,$authKey,0) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleEncryptWithPassword(string,string,byte[]) method' { | |
[string]$secretMessage = $ogMessage | |
It 'throws on null and empty SecretMessage' { | |
[string]$secretMessage = '' | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($null,$password,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
} | |
It 'encrypts secretMessage with nonSecretPayload' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
$locked = [AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload) | |
[AESThenHMAC]::SimpleDecryptWithPassword($locked,$password,$nonSecretPayload.Length) | should be $ogMessage | |
} | |
It 'encrypts secretMessage without nonSecretPayload' { | |
$locked = [AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$null) | |
[AESThenHMAC]::SimpleDecryptWithPassword($locked,$password,0) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleEncryptWithPassword(byte[],string,byte[]) method' { | |
[byte[]]$secretMessage = [char[]]$ogMessage | |
It 'throws on null and empty SecretMessage' { | |
[byte[]]$secretMessage = @() | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($null,$password,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload)} | should be $ExceptionText.secretMessage | |
} | |
It 'throws on null, empty, and short password' { | |
[string]$password = '' | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$null,$nonSecretPayload)} | should be $ExceptionText.password | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload)} | should be $ExceptionText.password | |
[string]$password = 'a' * ([AESThenHMAC]::MinPasswordLength - 1) | |
get-exception {[AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload)} | should be $ExceptionText.password | |
} | |
It 'encrypts secretMessage with nonSecretPayload' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
$locked = [AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$nonSecretPayload) | |
$AsBytes = [AESThenHMAC]::SimpleDecryptWithPassword($locked,$password,$nonSecretPayload.Length) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
It 'encrypts secretMessage without nonSecretPayload' { | |
$locked = [AESThenHMAC]::SimpleEncryptWithPassword($secretMessage,$password,$null) | |
$AsBytes = [AESThenHMAC]::SimpleDecryptWithPassword($locked,$password,0) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleDecryptWithPassword(string,string,int) method' { | |
[string]$encryptedMessage = 'Good Base64 String' | |
It 'throws on null and empty encryptedMessage' { | |
[string]$encryptedMessage = '' | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($null,$password,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
} | |
It 'decrypts encryptedMessage with nonSecretPayloadLength' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncryptWithPassword($ogMessage,$password,$nonSecretPayload) | |
[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayload.Length) | should be $ogMessage | |
} | |
It 'decrypts encryptedMessage without nonSecretPayloadLength' { | |
[string]$encryptedMessage = [AESThenHMAC]::SimpleEncryptWithPassword($ogMessage,$password,$null) | |
[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,0) | should be $ogMessage | |
} | |
} | |
Context 'When using the SimpleDecryptWithPassword(byte[],string,int) method' { | |
[byte[]]$encryptedMessage = [System.Convert]::FromBase64String('Good Base64 String') | |
It 'throws on null and empty encryptedMessage' { | |
[byte[]]$encryptedMessage = @() | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($null,$password,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayloadLength)} | should be $ExceptionText.encryptedMessage | |
} | |
It 'throws on null, empty, and short password' { | |
[string]$password = '' | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($null,$null,$nonSecretPayloadLength)} | should be $ExceptionText.password | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayloadLength)} | should be $ExceptionText.password | |
[string]$password = 'a' * ([AESThenHMAC]::MinPasswordLength - 1) | |
get-exception {[AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayloadLength)} | should be $ExceptionText.password | |
} | |
It 'decrypts encryptedMessage with nonSecretPayloadLength' { | |
[byte[]]$nonSecretPayload = [char[]]$ogNonSecretPayload | |
$encryptedMessage = [AESThenHMAC]::SimpleEncryptWithPassword(([byte[]][char[]]$ogMessage),$password,$nonSecretPayload) | |
$AsBytes = [AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,$nonSecretPayload.Length) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
It 'decrypts encryptedMessage without nonSecretPayloadLength' { | |
$encryptedMessage = [AESThenHMAC]::SimpleEncryptWithPassword(([byte[]][char[]]$ogMessage),$password,$null) | |
$AsBytes = [AESThenHMAC]::SimpleDecryptWithPassword($encryptedMessage,$password,0) | |
[System.Text.Encoding]::UTF8.GetString($AsBytes) | should be $ogMessage | |
} | |
} | |
} | |
################################################################# | |
Describe "$ProjectName Integration Tests" -Tag 'Integration','Automatic' { | |
It 'should test something' {} | |
} | |
################################################################# | |
Describe "$ProjectName Acceptance Tests" -Tag 'Acceptance' { | |
It 'should test something' {} | |
} | |
$DebugPreference = 'SilentlyContinue' | |
remove-variable ProjectName |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment