2
\$\begingroup\$

I wanted to make some simple functions that would be used in the encryption and decryption using a Vigenere square.

# Define the alphabet used in the cipher once so as to not define in memory for every encrypt/decrypt action
$global:alphabet = "abcdefghijklmnopqrstuvwxyz"
function Encrypt-VigenereCipherCharacter{
 [CmdletBinding()]
 param(
 [parameter(Mandatory=$true)]
 [char]$Character,
 [parameter(Mandatory=$true)]
 [char]$Key
 )
 # This function will encrypt an alphabetic character using a Vigenere Cipher and the key passed. 
 # Set the characters to lower case for baseline calculation. 
 $CharacterIndex = $global:alphabet.IndexOf(([string]$Character).ToLower())
 $KeyIndex = $global:alphabet.IndexOf(([string]$Key).ToLower())
 Write-Verbose "The character/index to $($PSCmdlet.ParameterSetName.ToLower()) is :'$Character/$CharacterIndex' and we are using the key/index: '$Key/$KeyIndex'"
 # Get the index of the encrypted character to return.
 $ShiftedCharacterIndex = $CharacterIndex + $KeyIndex
 # If this shift goes past Z we need to roll back the index to "wrap around" the alphabet to the be.
 if($ShiftedCharacterIndex -ge $global:alphabet.Length){$ShiftedCharacterIndex -= $global:alphabet.Length}
 # Return the shifted character
 return $global:alphabet[$ShiftedCharacterIndex] 
}
function Decrypt-VigenereCipherCharacter{
 [CmdletBinding()]
 param(
 [parameter(Mandatory=$true)]
 [char]$Character,
 [parameter(Mandatory=$true)]
 [char]$Key
 )
 # This function will decrypt an alphabetic character using a Vigenere Cipher and the key passed. 
 # Set the characters to lower case for baseline calculation. 
 $CharacterIndex = $global:alphabet.IndexOf(([string]$Character).ToLower())
 $KeyIndex = $global:alphabet.IndexOf(([string]$Key).ToLower())
 Write-Verbose "The character/index to decrypt is :'$Character/$CharacterIndex' and we are using the key/index: '$Key/$KeyIndex'"
 # Decrypt the character based on the positional difference of the character and key
 if($KeyIndex -le $CharacterIndex){
 $ShiftedCharacterIndex = $CharacterIndex - $KeyIndex
 } else {
 $ShiftedCharacterIndex = $global:alphabet.Length - $KeyIndex + $CharacterIndex
 }
 # Return the shifted character
 return $global:alphabet[$ShiftedCharacterIndex] 
}
function Encrypt-PlainTextString{
 [CmdletBinding()]
 param(
 [parameter(Mandatory=$true)]
 [alias("Text")]
 [string]$PlainText,
 [parameter(Mandatory=$true)]
 [string]$Key
 )
 # This function will encrypt a scrubbed character string using a Vigenere Cipher and the key passed.
 # Scrub all the repeated characters from the key so that it is just all unique characters in their original sequence
 Write-Verbose "The key requested is : $key"
 $Key = -join([char[]]$Key | Select-Object -Unique)
 Write-Verbose "The key being used is: $key"
 # Remove all alphabetic character from the plain text string.
 Write-Verbose "The text requested to encrypt is: $Plaintext"
 $PlainText = $PlainText -replace "\W"
 Write-Verbose "The text that will be encrypted is: $Plaintext"
 # Build the key stream to be the exact length of the text being encrypted. 
 $keyStream = ($key * ([math]::Ceiling($PlainText.Length / $key.Length))).Substring(0,$PlainText.Length)
 Write-Verbose "The text that follows will be the plain text string and its keystream below it."
 Write-Verbose $PlainText
 Write-Verbose $keyStream
 # Encrypt the text
 return -join (0..($PlainText.length - 1) | ForEach-Object{
 Get-VigenereCipherCharacter -Character $PlainText[$_] -Key $keyStream[$_] -Encrypt
 })
}
function Decrypt-CipherText{
 [CmdletBinding()]
 param(
 [parameter(Mandatory=$true)]
 [alias("Text")]
 [string]$CipherText,
 [parameter(Mandatory=$true)]
 [string]$Key
 )
 # This function will decrypt a scrubbed character string using a Vigenere Cipher and the key passed.
 # Scrub all the repeated characters from the key so that it is just all unique characters in their original sequence
 Write-Verbose "The key requested is : $key"
 $Key = -join([char[]]$Key | Select-Object -Unique)
 Write-Verbose "The key being used is: $key"
 # Remove all alphabetic character from the plain text string.
 Write-Verbose "The text requested to decrypt is: $CipherText"
 $CipherText = $CipherText -replace "\W"
 Write-Verbose "The text that will be decrypted is: $CipherText"
 # Build the key stream to be the exact length of the text being decrypted. 
 $keyStream = ($key * ([math]::Ceiling($CipherText.Length / $key.Length))).Substring(0,$CipherText.Length)
 Write-Verbose "The text that follows will be the plain text string and its keystream below it."
 Write-Verbose $CipherText
 Write-Verbose $keyStream
 # Decrypt the text
 return -join (0..($CipherText.length - 1) | ForEach-Object{
 Get-VigenereCipherCharacter -Character $CipherText[$_] -Key $keyStream[$_] -Decrypt
 })
}
function Distribute-Spaces{
 [CmdletBinding()]
 param(
 [parameter(Mandatory=$true)]
 [string]$Text,
 [parameter(Mandatory=$false)]
 [alias("Spaces")]
 [int]$NumberOfSpaces = 0
 )
 # This function will randomly insert a number of spaces into the text passed.
 # If the number of space is not provided assume that we place about 1 every 5 characters. 
 if($NumberOfSpaces -le 0){$NumberOfSpaces = $Text.Length / 9}
 # Get positional values for these new spaces and ensure they are not at the beginning or end of the new string.
 $spacePositions = 1..$NumberOfSpaces | ForEach-Object{Get-Random -Minimum 1 -Maximum ($text.Length - 2)}
 # Rebuild the string with the inserted spaces.
 -join (0..($text.Length - 1) | ForEach-Object{
 if($spacePositions -contains $_){
 $text[$_] + " "
 } else {
 $text[$_]
 }
 })
}

The functions exists in two pairs. Encrypt-PlainTextString will take a string and key and encrypt each character with Encrypt-VigenereCipherCharacter using a Vigenere square. There are foil decryption functions as well. There is also a spaces distribution function called Distribute-Spaces which is meant to insert spaces into the encrypted text to "obfuscate" words.

I originally had the encryption and decryption functions as the same function and used switches to differentiate between the two actions. It made sense since they shared several lines. The do however to different things and names the functions with appropriate meaningful names was difficult. Therefore I split them up into their own functions.

Some example usage would be:

$plaintext = "The red fox trots quietly at midnight."
$key = "jamesbond"
$ciphertext = Distribute-Spaces -Text(Encrypt-PlainTextString -PlainText $plaintext -Key $key)
$ciphertext
Decrypt-CipherText -CipherText $ciphertext -Key $key

Which would generate the following output.

chqvwe tb acraxkrivhclkeln wqqrgtx
theredfoxtrotsquietlyatmidnight
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jun 27, 2016 at 19:41
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I originally had the encryption and decryption functions as the same function

I am guessing that function was named Get-VigenereCipherCharacter? You are still referencing it instead of Encrypt/Decrypt-VigenereCipherCharacter.


As you said, if you can find meaningful function names, combining functions can make sense. As well the as character rotation functions for encrypt and decrypt, you can combine everything. Ultimately all the functions are similar:

Function Use-VigenereEncryption {
 [CmdletBinding()]
 Param (
 [Parameter(ParameterSetName=’Decrypt’)][Switch]$Decrypt,
 [Parameter(ParameterSetName=’Encrypt’)][Switch]$Encrypt,
 [parameter(Mandatory=$true,ValueFromPipeline=$true)][string]$Text,
 [parameter(Mandatory=$true)][string]$Key
 )
 $alphabet = "abcdefghijklmnopqrstuvwxyz"
 # Remove all alphabetic character from the plain text string.
 Write-Verbose "The text requested to be encrypted/decrypted: $Text"
 $Text = ($Text -replace "\W").ToLower()
 Write-Verbose "The text that will be encrypted/decrypted: $Text"
 # Scrub all the repeated characters from the key so that it is just all unique characters in their original sequence
 Write-Verbose "The key provided: $key"
 $Key = -join([char[]]$Key | Select-Object -Unique)
 Write-Verbose "The key being used: $key"
 # Build the key stream to be the exact length of the text being decrypted. 
 $keyStream = ($key * ([math]::Ceiling($Text.Length / $key.Length))).Substring(0,$Text.Length)
 Write-Verbose "The resulting encryption/decryption string: $keyStream"
 -join (0..($Text.length - 1) | % {
 $CharacterIndex = $alphabet.IndexOf($Text[$_])
 $KeyIndex = $alphabet.IndexOf($keyStream[$_])
 Write-Verbose "The character/index to encrypt/decrypt is :'$($Text[$_])/$CharacterIndex' and we are using the key/index: '$Key/$KeyIndex'"
 Switch ($PsCmdlet.ParameterSetName) {
 "Decrypt" {
 If ($KeyIndex -le $CharacterIndex) {
 $alphabet[$CharacterIndex - $KeyIndex]
 } Else {
 $alphabet[$alphabet.Length - $KeyIndex + $CharacterIndex]
 }
 }
 "Encrypt" {
 If ($CharacterIndex + $KeyIndex -ge $alphabet.Length) {
 $alphabet[$CharacterIndex + $KeyIndex - $alphabet.Length]
 } Else {
 $alphabet[$CharacterIndex + $KeyIndex]
 }
 #randomly insert spaces:
 If ((Get-Random -Minimum 1 -Maximum ($Text.Length - 2)) -le ($Text.Length / 9)) {
 " "
 }
 }
 }
 })
}
$plaintext = "The red fox trots quietly at midnight."
$key = "jamesbond"
$ciphertext = Use-VigenereEncryption -Encrypt -Text $plaintext -Key $key
$ciphertext
$ciphertext | Use-VigenereEncryption -Decrypt -Key $key -Verbose
answered Jul 5, 2016 at 4:37
\$\endgroup\$
1
  • \$\begingroup\$ Yes. I didn't update the function names as they were still working in my ISE session so I didn't catch it. This is like one of my original drafts of this and you bring it together better than I did. Thanks. Only thing I am going to change on this is make the verbose text dependent on the parameter set so it always says the correct text. \$\endgroup\$ Commented Jul 5, 2016 at 14:46

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.