Last active
June 2, 2022 21:33
-
-
Save bruceoutdoors/0685335d30ed9b10c77e633f3b98ad26 to your computer and use it in GitHub Desktop.
Hill Cipher - use via "hill-decrypt.sh" and "hill-encrypt.sh"
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
#!/bin/bash | |
. matrix.sh | |
. mods.sh | |
. translator.sh | |
function hill_decrypt { | |
key=${1// /} # clear spaces from key | |
if [ ${#key} -lt 4 ]; | |
then | |
echo "ERROR: Key needs to be 4 characters and above!" | |
return | |
fi | |
if [ ${#key} -gt 4 ]; | |
then | |
key=${key:0:4} # truncate string to 4 characters | |
fi | |
key=($(letters_to_numbers $key)) | |
ciphertext=${2// /} # clear spaces from plaintext | |
ciphertext=($(letters_to_numbers $ciphertext)) | |
if [ $((${#ciphertext[@]}%2)) -ne 0 ]; then | |
echo "ERROR: Cipher text length must be even number!!" | |
return | |
fi | |
det=$(getdet ${key[@]}) | |
if ! (( $(hasmatrixinverse $det) )) | |
then | |
echo "ERROR: Key has no matrix inverse!!" | |
return | |
fi | |
if ! (( $(hasmodinverse $det) )) | |
then | |
echo "ERROR: Key has no modular inverse!!" | |
return | |
fi | |
det=$(mod $det 26) | |
det=$(frac_mod $det 26) | |
#~ echo "frac mod determinant is" $det | |
inverse=( \ | |
$(mod $((${key[3]} * $det)) 26) \ | |
$(mod $((-${key[1]} * $det)) 26) \ | |
$(mod $((-${key[2]} * $det)) 26) \ | |
$(mod $((${key[0]} * $det)) 26) \ | |
) | |
#~ echo "inverse of the key is" ${inverse[@]} | |
plaintext=($(multiply ${inverse[@]} ${ciphertext[@]})) | |
#~ echo "Decrypted numbers: "${plaintext[@]} | |
echo $(numbers_to_letters ${plaintext[@]}) | |
} | |
# Hill Cipher Encrypt | |
# Appends "X" to the end of the input if the input is odd-numbered | |
function hill_encrypt { | |
K=${1// /} # clear spaces from key | |
if [ ${#K} -lt 4 ]; | |
then | |
echo "ERROR: Key needs to be 4 characters and above!" | |
return | |
fi | |
if [ ${#K} -gt 4 ]; | |
then | |
K=${K:0:4} # truncate string to 4 characters | |
fi | |
K=($(letters_to_numbers $K)) | |
PLAINTEXT=${2// /} # clear spaces from plaintext | |
det=$(getdet ${K[@]}) | |
if ! (( $(hasmatrixinverse $det) )) | |
then | |
echo "ERROR: Key has no matrix inverse!!" | |
return | |
fi | |
if ! (( $(hasmodinverse $det) )) | |
then | |
echo "ERROR: Key has no modular inverse!!" | |
return | |
fi | |
if (( ${#PLAINTEXT} % 2 )) | |
then | |
PLAINTEXT+=X | |
fi | |
P=($(letters_to_numbers "$PLAINTEXT")) | |
E=($(multiply ${K[@]} ${P[@]})) | |
echo $(numbers_to_letters ${E[@]}) | |
} | |
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
# usage: | |
# ./hill-decrypt.sh FIRD MIMJSU | |
# MONDAY | |
# | |
#!/bin/bash | |
. hill-cipher.sh | |
if (( $# != 2 )); then | |
echo "ERROR! 2 arguments are required: The key, followed by the cipher text." | |
echo "Usage: ./hill-decrypt.sh 'FIRD' 'MIMJSU'" | |
exit 1 | |
fi | |
echo $(hill_decrypt "$1" "$2") |
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
# usage: | |
# ./hill-encrypt.sh FIRD MONDAY | |
# MIMJSU | |
# | |
#!/bin/bash | |
. hill-cipher.sh | |
if (( $# != 2 )); then | |
echo "ERROR! 2 arguments are required: The key, followed by the plaintext." | |
echo "Usage: ./hill-decrypt.sh 'FIRD' 'MONDAY'" | |
exit 1 | |
fi | |
echo $(hill_encrypt "$1" "$2") |
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
#!/bin/bash | |
# Gets the determinant of a 2 x 2 matrix and returns the value | |
# The matrix is indexed as follows: | |
# _ _ | |
# | 0 2 | | |
# |_1 3 _| | |
# | |
function getdet { | |
# local MATRIX=( 5 5 5 5 ) | |
# local MATRIX=( 5 8 17 13 ) | |
local MATRIX=("$@") | |
det=$(( ${MATRIX[0]} * ${MATRIX[3]} - ${MATRIX[2]} * ${MATRIX[1]} )) | |
echo "$det" | |
} | |
# Matrix multiplication, with ARRAY1[] = 2 x 2 matrix | |
# ARRAY2[] = 2 x anything matrix | |
# RESULT[] = Resultant matrix | |
# The (2 x n) matrices are indexed into arrays as follows: | |
# _ _ | |
# | 0 2 4 6 ... n-1 | | |
# |_1 3 5 7 ... n _| | |
# | |
function multiply { | |
# local ARRAY1=( 5 8 17 3 ) | |
# local ARRAY2=( 12 14 13 3 0 24 ) | |
local ARRAY=($@) | |
ARRAY1=( ${ARRAY[0]} ${ARRAY[1]} ${ARRAY[2]} ${ARRAY[3]} ) | |
#~ echo ${ARRAY1[@]} | |
COUNT=4 #Start reading from index after key | |
while [[ $COUNT -lt ${#ARRAY[@]} ]] | |
do | |
ARRAY2[$(( $COUNT - 4 ))]=${ARRAY[$COUNT]} | |
(( COUNT++ )) | |
done | |
#~ echo ${ARRAY2[@]} | |
COUNT=0 | |
while [[ $COUNT -lt ${#ARRAY2[@]} ]] | |
do | |
RESULT[$COUNT]=$(( $(( ${ARRAY1[0]} * ${ARRAY2[$COUNT]} + ${ARRAY1[2]} * ${ARRAY2[(( $COUNT + 1 ))]} )) % 26 )) | |
RESULT[$(( $COUNT + 1 ))]=$(( $(( ${ARRAY1[1]} * ${ARRAY2[$COUNT]} + ${ARRAY1[3]} * ${ARRAY2[(( $COUNT + 1 ))]} )) % 26 )) | |
COUNT=$(( $COUNT + 2 )) | |
done | |
echo "${RESULT[@]}" | |
} | |
function hasmatrixinverse { | |
local DET=$1 | |
if (( $DET != 0 )) | |
then | |
echo "1" | |
else | |
echo "0" | |
fi | |
} |
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
#!/bin/bash | |
. mods.sh | |
echo $(mod 0 26) | |
echo $(mod 27 26) | |
echo $(mod -121 26) | |
echo $(frac_mod 9 26) | |
echo $(frac_mod 7 26) |
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
#!/bin/bash | |
# mod, factors both negative and positive values | |
function mod { | |
local a=$1 | |
local b=$2 | |
if [ $a -ge 0 ]; then # if positive values | |
while [ $a -ge $b ]; do | |
let a=a-b | |
done | |
else # negative values | |
while [ $a -le $b ] && [ $a -lt 0 ]; do | |
let a=a+b | |
done | |
fi | |
echo $a | |
} | |
# fractional mod, assuming numerator is 1, and only takes positive fracs | |
function frac_mod { | |
local a=$1 | |
local b=$2 | |
local x=-1 | |
local r=-1 # remainder | |
while [ $r -ne 1 ]; do | |
let x=x+2 | |
let ax=a*x | |
r=$(mod $ax $b) | |
done | |
echo $x | |
} | |
function hasmodinverse { | |
local DET=$1 | |
if (( $DET % 2 && $DET % 13 )) # 2 and 13 are not relatively prime to 26, | |
then # and so has no modulo inverse | |
echo "1" | |
else | |
echo "0" | |
fi | |
} |
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
#!/bin/bash | |
. translator.sh | |
LETTERS=({a..z}) # it will convert to uppercase | |
for le in "${LETTERS[@]}" | |
do | |
echo $(letter_to_number $le) | |
done | |
NUMBERS=({0..25}) | |
for nu in "${NUMBERS[@]}" | |
do | |
echo $(number_to_letter $nu) | |
done |
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
#!/bin/bash | |
function letter_to_number { | |
local uppercase=$(echo $1 | tr '[a-z]' '[A-Z]') | |
local ascii=$(LC_CTYPE=C printf '%d' "'$uppercase") | |
let num=ascii-65 | |
echo $num | |
} | |
function number_to_letter { | |
local LETTERS=({A..Z}) | |
echo ${LETTERS[$1]} | |
} | |
function numbers_to_letters { | |
local letters=( $@ ) | |
for nu in "${letters[@]}" | |
do | |
echo -n $(number_to_letter $nu) | |
done | |
} | |
function letters_to_numbers { | |
for nu in $(seq 1 ${#1}) | |
do | |
echo -n $(letter_to_number ${1:$nu-1:1})" " | |
done | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment