Caesar cipher by Bash scripts

Posted by:

|

On:

|

The Caesar Cipher, used by Julius Caesar around 58 BC, is a substitution cipher that shifts letters in a message to make it unreadable if intercepted. To decrypt, the receiver reverses the shift. To encrypt or decrypt text using the tr (translate) command in Bash, you can define a mapping of characters to new characters and apply it to the input text. For the following translation

Sourceabcdefghijklmnopqrstuvwxyz
Cipherxyzabcdefghijklmnopqrstuvw

we can encrypt the input text by entering the following script in the terminal

echo "hello world"  | tr '[a-z]' '[x-za-w]'   

result is – ebiil tloia  

To decrypt the encrypted text “ebiil tloia”, you can use a simple script that performs a character substitution.

echo "ebiil tloia"  | tr '[x-za-w]' '[a-z]'   

result is the original text – hello world  

We can do the encode and decode at the same time

echo "hello world"  | tr '[a-z]' '[x-za-w]' | tr '[x-za-w]' '[a-z]' 

Let’s walk through the step-by-step development of Caesar encryption and decryption using Bash scripts:

(A) Generate the shift pattern for tr command

To enhance the flexibility of the translation process, we can begin by creating a bash script called ‘shift_pattern’ that generates the mapping parameters for the ‘tr’ command, specifically ‘[x-za-w]’. This script will have two options: ‘-k’ followed by a number to determine the number of letters to shift, and ‘-u’ to determine whether the mapping parameters should be in uppercase or lowercase.

Here’s an implementation of the ‘shift_pattern’ script:

#!/bin/bash
create_shifted_char() {
  char=$1
  shift=$2
  ascii_val=$(printf '%d' "'$char'")
  shifted_ascii_val=$((ascii_val + shift))
  shifted_char=""
  if [[ $uppercase == "true" ]]; then  
    shifted_char=$(printf "\\$(printf '%03o' "$(( (shifted_ascii_val - 65) % 26 + 65 ))")")
  else
    shifted_char=$(printf "\\$(printf '%03o' "$(( (shifted_ascii_val - 97) % 26 + 97 ))")")
  fi
  echo "$shifted_char"
}

# program start here
uppercase=false
while getopts ":k:u" opt; do
    case ${opt} in
        k)
            shift_value=${OPTARG}
            ;;
        u)
            uppercase=true
            ;;
    esac
done

start=""
end=""
pattern="" 
if [[ $uppercase == "true" ]]; then
    start="A"
    end="Z"
else
    start="a"
    end="z"
fi

pattern=$(printf "%s-%s%s-%s" "$(create_shifted_char "$start" "$shift_value")" "$end" "$start" "$(create_shifted_char "$end" "$shift_value")")
echo "[$pattern]" 

Detailed explanation:

  1. The create_shifted_char function takes two arguments: char and shift. It calculates the ASCII value of the character by using printf with the %d format specifier and the "'$char'" syntax to get the ASCII value of the character itself and assigned to variable ‘ascii_val’, rather than its numeric equivalent.
  2. Add the number in variable shift to ascii_val and obtain a new value in variable ‘shifted_ascii_val’.
  3. Depending on the value of uppercase, the function calculates the shifted character accordingly. If uppercase is set to “true,” it uses the uppercase ASCII range (65-90) [A-Z]. Otherwise, it uses the lowercase ASCII range (97-122) [a-z].
  4. The function uses printf with the %03o format specifier to get the octal representation of the shifted ASCII value. It then uses an additional printf command with the \\ prefix to interpret the octal value as a character and obtain the shifted character.
  5. The create_shifted_char function returns the shifted character as its result.
  6. The script starts by setting uppercase to false.
  7. The script uses the getopts function to handle command line options. It specifies that the -k option requires an argument (OPTARG) to determine the shift value, and the -u option sets uppercase to true. Parameters –k and –u can be given in any order.
  8. The script initializes the startend, and pattern variables.
  9. Depending on the value of uppercase, the script sets start and end to the appropriate ASCII characters: ‘A’ and ‘Z’ for uppercase, or ‘a’ and ‘z’ for lowercase.
  10. The script calls the create_shifted_char function twice to obtain the shifted start and shifted end characters. It passes "$start" and "$shift_value" as arguments to create_shifted_char for the shifted start character, and "$end" and "$shift_value" for the shifted end character.
  11. The script uses printf to format the resulting characters into the desired pattern: "%s-%s%s-%s". It concatenates the shifted start, end, start, and shifted end characters.
  12. The resulting pattern is stored in the pattern variable.
  13. The script echoes the pattern, enclosed in square brackets, using echo "[$pattern]".
  14. Make sure the script file has execute permissions using the chmod command “chmod +x shift_pattern”.

Result:

./shift_pattern -k 5 -u generates [F-ZA-E]

./shift_pattern -k 3 generates [d-za-c]

(B) Encrypt text message

Another bash script named “caesar_encrypt” is created. Byrunning this script, you can pass input text to it, and it will apply the Caesar cipher encoding based on the specified shift value and uppercase option. The encoded output will be displayed on the terminal. The bash script “shift_pattern” is executed as nested script to generate the appropriate patterns for the tr command based on the shift value and uppercase option

Here’s an implementation of the ‘caesar_encrypt’ script:

#!/bin/bash
shift_pattern_script="./shift_pattern"
uppercase=false
shift_value=""

while getopts ":k:u" opt; do
    case ${opt} in
        k)
            shift_value=${OPTARG}
            ;;
        u)
            uppercase=true
            ;;
    esac
done

if [[ $uppercase == "true" ]]; then
    pattern1="[A-Z]"
    pattern2=$(bash "$shift_pattern_script" -k "$shift_value" -u) 
else
    pattern1="[a-z]"
    pattern2=$(bash "$shift_pattern_script" -k "$shift_value")
fi
echo "Shift pattern is" $pattern2

while IFS= read -r line; do
    encoded_line=$(echo "$line" | tr "$pattern1" "$pattern2")
    echo "$encoded_line"
done

Detailed explanation:

  1. The script starts by setting the shift_pattern_script variable to the path of the shift_pattern script, which is assumed to be in the same directory.
  2. The uppercase variable is set to false by default, indicating that the pattern should be generated for lowercase letters.
  3. The shift_value variable is initialized as an empty string.
  4. The script uses the getopts function to handle command line options. It specifies that the -k option requires an argument (OPTARG) to determine the shift value, and the -u option sets uppercase to true.
  5. If uppercase is set to “true,” the script sets pattern1 to [A-Z], indicating the pattern for uppercase letters. It then calls the shift_pattern_script with the -k and -u options, passing the shift_value for the shift amount. The output of the shift_pattern_script  is stored in the pattern2 variable.
  6. If uppercase is set to “false,” the script sets pattern1 to [a-z], indicating the pattern for lowercase letters. It then calls the shift_pattern_script  with only the -k option, passing the shift_value. The output of the shift_pattern_script  is again stored in the pattern2 variable.
  7. The script uses a while loop to read input line by line until the end of the input (EOF) is reached.
  8. Within the loop, each line is encoded using the tr command with the pattern1 and pattern2 variables. The tr command replaces characters matching pattern1 with the corresponding characters from pattern2, effectively performing the Caesar cipher encoding.
  9. The encoded line is then echoed to standard output.
  10. Make sure the script file has execute permissions using the chmod command “chmod +x caesar _encrypt”.
  11. In the terminal, type ./caesar_encrypt -k 5 -u and the shift pattern is shown.
  12. Enter your message and the encrypted version will be displayed immediately until you press Ctrl+C to stop the script.

Result:

./caesar_encrypt -k 5 -u
Shift pattern is [F-ZA-E]
WELCOME TO MY BLOG[Enter]
BJQHTRJ YT RD GQTL
NICE TO MEET YOU[Enter]
SNHJ YT RJJY DTZ[Ctrl+C]

(C) Decrypt a text file with Caesar encrypted message

Another bash script named “caesar_decrypt” is created. Byrunning this script with the filename of a text file as the command line argument, it will iterate through shift values from 1 to 25. For each shift value, it will decrypt the contents of the file using the corresponding shift pattern and display the decrypted lines. This can be used to analyze and identify the Caesar cipher shift used for the encrypted text.

The Caesar encrypted message in the text file “caesar_encrypted.txt” :

Bjqhtrj yt rd gqtl
Snhj yt rjjy dtz

Here’s an implementation of the ‘caesar_decrypt’ script:

#!/bin/bash
shift_pattern_script="./shift_pattern"

if [ $# -ne 1 ]; then  
    echo "incorrect filename"  
    exit 1 
fi

filename=$1
if [ ! -f "$filename" ]; then
    echo "File '$filename' not found."
    exit 1
fi

for ((shift=1; shift<=25; shift++)); do
    echo "Shift $shift"
    pattern_U=$(bash "$shift_pattern_script" -k "$shift" -u)
    pattern_L=$(bash "$shift_pattern_script" -k "$shift")
    while IFS= read -r line; do
        decoded_line1=$(echo "$line" | tr '[A-Z]' "$pattern_U")   
        decoded_line2=$(echo "$decoded_line1" | tr '[a-z]' "$pattern_L") 
        echo "$decoded_line2"
    done < "$filename"
done

Detailed explanation:

  1. The script starts by setting the shift_pattern_script variable to the path of the shift_pattern script, which is assumed to be in the same directory.
  2. The script checks if the number of command line arguments ($#) is not equal to 1. If this condition is true, it means that an incorrect number of arguments was provided. In that case, it prints an error message “incorrect filename” and exits with a status of 1.
  3. The script assigns the value of the first command line argument ($1) to the filename variable, which represents the name of the file to be processed.
  4. The script checks if the specified file ($filename) does not exist using the -f operator. If the file doesn’t exist, it prints an error message “File ‘$filename’ not found.” and exits with a status of 1.
  5. The script then enters a loop that iterates from shift=1 to shift=25. This loop represents the different shift values to be tested.
  6. Within the loop, the script prints the current shift value using the echo command.
  7. The pattern variable is set by executing the shift_pattern script with the -k option set to the current shift value ($shift) and the -u option to indicate uppercase encoding.
  8. The script uses a while loop and input redirection (<) to read each line of the specified file ($filename).
  9. Within the inner loop, each line is decoded using the tr command. It replaces uppercase letters [A-Z] first and then [a-z] with the corresponding characters from the pattern variable, effectively performing the Caesar cipher decoding.
  10. The decoded line is then echoed to standard output.
  11. The inner loop continues to process each line of the file until there are no more lines to read.
  12. Once the inner loop finishes processing the entire file, the outer loop moves to the next shift value, and the process repeats until all shift values from 1 to 25 have been tested.
  13. Make sure the script file has execute permissions using the chmod command “chmod +x caesar_decrypt”.
  14. In the terminal, type ./caesar_decrypt caesar_encrypted.txt and all possible decrypted pattern are echoed.

Result: (Shift 21 gives the correct original message)

Shift 1
Ckriusk zu se hrum
Toik zu skkz eua
Shift 2
Dlsjvtl av tf isvn
Upjl av tlla fvb
Shift 3
Emtkwum bw ug jtwo
Vqkm bw ummb gwc
Shift 4
Fnulxvn cx vh kuxp
Wrln cx vnnc hxd
Shift 5
Govmywo dy wi lvyq
Xsmo dy wood iye
Shift 6
Hpwnzxp ez xj mwzr
Ytnp ez xppe jzf
Shift 7
Iqxoayq fa yk nxas
Zuoq fa yqqf kag
Shift 8
Jrypbzr gb zl oybt
Avpr gb zrrg lbh
Shift 9
Kszqcas hc am pzcu
Bwqs hc assh mci
Shift 10
Ltardbt id bn qadv
Cxrt id btti ndj
Shift 11
Mubsecu je co rbew
Dysu je cuuj oek
Shift 12
Nvctfdv kf dp scfx
Eztv kf dvvk pfl
Shift 13
Owdugew lg eq tdgy
Fauw lg ewwl qgm
Shift 14
Pxevhfx mh fr uehz
Gbvx mh fxxm rhn
Shift 15
Qyfwigy ni gs vfia
Hcwy ni gyyn sio
Shift 16
Rzgxjhz oj ht wgjb
Idxz oj hzzo tjp
Shift 17
Sahykia pk iu xhkc
Jeya pk iaap ukq
Shift 18
Tbizljb ql jv yild
Kfzb ql jbbq vlr
Shift 19
Ucjamkc rm kw zjme
Lgac rm kccr wms
Shift 20
Vdkbnld sn lx aknf
Mhbd sn ldds xnt
Shift 21
Welcome to my blog
Nice to meet you

Shift 22
Xfmdpnf up nz cmph
Ojdf up nffu zpv
Shift 23
Ygneqog vq oa dnqi
Pkeg vq oggv aqw
Shift 24
Zhofrph wr pb eorj
Qlfh wr phhw brx
Shift 25
Aipgsqi xs qc fpsk
Rmgi xs qiix csy

Posted by

in