7
# This is an implementation of the Gronsfeld Cipher.
8
# It's essentially a stripped-down variant of the
9
#+ polyalphabetic Vigenère Tableau, but with only 10 alphabets.
10
# The classic Gronsfeld has a numeric sequence as the key word,
11
#+ but here we substitute a letter string, for ease of use.
12
# Allegedly, this cipher was invented by the eponymous Count Gronsfeld
13
#+ in the 17th Century. It was at one time considered to be unbreakable.
14
# Note that this is ###not### a secure cipher by modern standards.
17
Enc_suffix="29379" # Encrypted text output with this 5-digit suffix.
18
# This functions as a decryption flag,
19
#+ and when used to generate passwords adds security.
20
Default_key="gronsfeldk"
21
# The script uses this if key not entered below
23
# Change the above two values frequently
24
#+ for added security.
26
GROUPLEN=5 # Output in groups of 5 letters, per tradition.
27
alpha1=( abcdefghijklmnopqrstuvwxyz )
28
alpha2=( {A..Z} ) # Output in all caps, per tradition.
29
# Use alpha2=( {a..z} ) for password generator.
30
wraplen=26 # Wrap around if past end of alphabet.
31
dflag= # Decrypt flag (set if $Enc_suffix present).
32
E_NOARGS=76 # Missing command-line args?
33
DEBUG=77 # Debugging flag.
34
declare -a offsets # This array holds the numeric shift values for
35
#+ encryption/decryption.
37
########Keychain#########
38
key= ### Put key here!!!
40
#########################
46
{ # Encrypt or decrypt, depending on whether $dflag is set.
47
# Why ": ()" as a function name? Just to prove that it can be done.
49
local idx keydx mlen off1 shft
51
local mlen=${#plaintext}
53
for (( idx=0; idx<$mlen; idx++ ))
55
let "keydx = $idx % $keylen"
56
shft=${offsets[keydx]}
60
let "off1 = $(expr index "${alpha1[*]}" ${plaintext:idx:1}) - $shft"
61
# Shift backward to decrypt.
63
let "off1 = $(expr index "${alpha1[*]}" ${plaintext:idx:1}) + $shft"
64
# Shift forward to encrypt.
65
test $(( $idx % $GROUPLEN)) = 0 && echo -n " " # Groups of 5 letters.
66
# Comment out above line for output as a string without whitespace,
67
#+ for example, if using the script as a password generator.
70
((off1--)) # Normalize. Why is this necessary?
73
then # Catch negative indices.
74
let "off1 += $wraplen"
77
((off1 %= $wraplen)) # Wrap around if past end of alphabet.
79
echo -n "${alpha2[off1]}"
86
# echo "$Enc_suffix" # For password generator.
90
} # End encrypt/decrypt function.
96
# Check for command-line args.
99
echo "Usage: $0 TEXT TO ENCODE/DECODE"
103
if [ ${!#} == "$Enc_suffix" ]
104
# ^^^^^ Final command-line arg.
107
echo -n "+" # Flag decrypted text with a "+" for easy ID.
112
key="$Default_key" # "gronsfeldk" per above.
117
for (( idx=0; idx<$keylen; idx++ ))
118
do # Calculate shift values for encryption/decryption.
119
offsets[idx]=$(expr index "${alpha1[*]}" ${key:idx:1}) # Normalize.
120
((offsets[idx]--)) # Necessary because "expr index" starts at 1,
121
#+ whereas array count starts at 0.
122
# Generate array of numerical offsets corresponding to the key.
123
# There are simpler ways to accomplish this.
126
args=$(echo "$*" | sed -e 's/ //g' | tr A-Z a-z | sed -e 's/[0-9]//g')
127
# Remove whitespace and digits from command-line args.
128
# Can modify to also remove punctuation characters, if desired.
131
# echo "$args"; exit $DEBUG
133
: "$args" # Call the function named ":".
134
# : is a null operator, except . . . when it's a function name!
136
exit $? # } End-of-script
139
# ************************************************************** #
140
# This script can function as a password generator,
141
#+ with several minor mods, see above.
142
# That would allow an easy-to-remember password, even the word
143
#+ "password" itself, which encrypts to vrgfotvo29379
144
#+ a fairly secure password not susceptible to a dictionary attack.
145
# Or, you could use your own name (surely that's easy to remember!).
146
# For example, Bozo Bozeman encrypts to hfnbttdppkt29379.
147
# ************************************************************** #