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
Source | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
Cipher | x | y | z | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w |
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:
- The
create_shifted_char
function takes two arguments:char
andshift
. It calculates the ASCII value of the character by usingprintf
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. - Add the number in variable shift to ascii_val and obtain a new value in variable ‘shifted_ascii_val’.
- Depending on the value of
uppercase
, the function calculates the shifted character accordingly. Ifuppercase
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]. - The function uses
printf
with the%03o
format specifier to get the octal representation of the shifted ASCII value. It then uses an additionalprintf
command with the\\
prefix to interpret the octal value as a character and obtain the shifted character. - The
create_shifted_char
function returns the shifted character as its result. - The script starts by setting
uppercase
to false. - 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 setsuppercase
to true. Parameters –k and –u can be given in any order. - The script initializes the
start
,end
, andpattern
variables. - Depending on the value of
uppercase
, the script setsstart
andend
to the appropriate ASCII characters: ‘A’ and ‘Z’ for uppercase, or ‘a’ and ‘z’ for lowercase. - 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 tocreate_shifted_char
for the shifted start character, and"$end"
and"$shift_value"
for the shifted end character. - 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. - The resulting pattern is stored in the
pattern
variable. - The script echoes the pattern, enclosed in square brackets, using
echo "[$pattern]"
. - 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:
- The script starts by setting the
shift_pattern_script
variable to the path of theshift_pattern
script, which is assumed to be in the same directory. - The
uppercase
variable is set tofalse
by default, indicating that the pattern should be generated for lowercase letters. - The
shift_value
variable is initialized as an empty string. - 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 setsuppercase
to true. - If
uppercase
is set to “true,” the script setspattern1
to[A-Z]
, indicating the pattern for uppercase letters. It then calls theshift_pattern_script
with the-k
and-u
options, passing theshift_value
for the shift amount. The output of theshift_pattern_script
is stored in thepattern2
variable. - If
uppercase
is set to “false,” the script setspattern1
to[a-z]
, indicating the pattern for lowercase letters. It then calls theshift_pattern_script
with only the-k
option, passing theshift_value
. The output of theshift_pattern_script
is again stored in thepattern2
variable. - The script uses a
while
loop to read input line by line until the end of the input (EOF) is reached. - Within the loop, each line is encoded using the
tr
command with thepattern1
andpattern2
variables. Thetr
command replaces characters matchingpattern1
with the corresponding characters frompattern2
, effectively performing the Caesar cipher encoding. - The encoded line is then echoed to standard output.
- Make sure the script file has execute permissions using the
chmod
command “chmod +x caesar _encrypt”. - In the terminal, type ./caesar_encrypt -k 5 -u and the shift pattern is shown.
- 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:
- The script starts by setting the
shift_pattern_script
variable to the path of theshift_pattern
script, which is assumed to be in the same directory. - 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. - The script assigns the value of the first command line argument (
$1
) to thefilename
variable, which represents the name of the file to be processed. - 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. - The script then enters a loop that iterates from
shift=1
toshift=25
. This loop represents the different shift values to be tested. - Within the loop, the script prints the current shift value using the
echo
command. - The
pattern
variable is set by executing theshift_pattern
script with the-k
option set to the current shift value ($shift
) and the-u
option to indicate uppercase encoding. - The script uses a
while
loop and input redirection (<
) to read each line of the specified file ($filename
). - 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 thepattern
variable, effectively performing the Caesar cipher decoding. - The decoded line is then echoed to standard output.
- The inner loop continues to process each line of the file until there are no more lines to read.
- 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.
- Make sure the script file has execute permissions using the
chmod
command “chmod +x caesar_decrypt”. - 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