New stuff for the R-Pi OTP/DRYAD – CEOI ADDITIONS, Jefferson Thomas
This paper provides additional tools pertaining to implementing a CEOI to my previously presented R-PI/DRYAD True Hardware RNG How-To at https://www.americanpartisan.org/2020/01/r-pi-otp-dryad-true-hardware-rng-how-to/ . Please review that as necessary. I will present the suggested hardware changes, scripts with descriptions, and also instructions regarding the creation of a complete and secure CodeBook.
Having had some time thrust upon me I started catching up on some reading. I finally read “The Partisan Operator Journals, Vol. 1” by John Jacob Schmidt of AmRRON and found it a fast and informative read. I enjoyed it and have recommended it to others. For those who don’t know, JJS was an 18E. While the book is fiction, it is something of a how-to in that it describes one way to create and implement a CEOI (Communications Electronic Operating Instruction) from the perspective of a partisan/guerrilla. (Coincidentally, shortly after reading this and writing preliminary scripts, Scout also mentioned the CEOI in a podcast. I have since tuned-up the scripts and present them here.) Keep in mind that there is no “one way” or “one system” for creating a CEOI. It will depend on your unit’s logistics, training and experience. I’m not going to go into any detail regarding JJS’s CEOI system in this book, as you should read it to get a better understanding of the concept and use of the CEOI, and realize that as presented it is not even complete – he says so also. His work is also worthy of support, and I don’t want to take away from or rob him of what he is due. Also understand that the CEOI as presented is not the same as you may have used in .gov. Our equipment now is different and more varied in .civ and therefore we have to adapt our TTPs and OIs to fit. We need to know how to adapt what we have (and can acquire) to our present and upcoming situation.
Hardware/OS:
A big change is the handling of the ramdisk. The previous method turned out to have a limit of only 4Meg, which while it worked with the previous scripts, is not nearly big enough for the Code Table Generator and associated scripts. Fortunately, there is a different way to set this up that is much more capable. Unless you will be using any of these scripts on another computer for testing, etc., do the following procedure. If you will be using these on another system (in particular the Code Book scripts) then leave the scripts as they are and do not set up the ramdisk under tis following procedure
In the previous scripts (OTP.sh, DRYAD.sh and Split-OTP.sh) and the follwoing scripts here remove the following lines:
mkfs -q /dev/ram1/ xxxxx
mkdir -p /ramdisk
mount /dev/ram1 /ramdisk
After this, set up a new ramdisk using the following procedure:
At the command line in a terminal type:
sudo mkdir /ramdisk
sudo leafpad
( this will open up a graphical text editor with su privileges ) – open /etc/fstab and add the following:
tmpfs /ramdisk tmpfs nodev,nosuid,size=64M 0 0
At the command line type:
mount -a
This will mount the ramdisk right now. You can verify it mounted correctly by entering:
df -h
You should see a table with a bunch entries that should include one line that looks like:
tmpfs 64M 0 64M 0% /ramdisk
There, now a 64Meg ramdisk will be set up every time you boot.
As mentioned in the previous paper, I am not a fan of the R-Pi 7″ touchscreen. However it does work as far as the the previous scope is concerned (OTP/DRYAD creation.) For this updated system, I am scrapping the touchscreen and instead using a larger 12V monitor. It will reduce portability, but then it wasn’t like a laptop or tablet before anyway. This will also require more power, so a larger battery may be in order. The larger monitor will make it MUCH easier to edit the CEOI/SOI documents, particularly if you also include the previously presented SOI Helper Spreadsheet (Revised) at https://www.americanpartisan.org/2020/11/soi-helper-spreadsheet-revised-by-jefferson-thomas/ . I also recommend finding a backlit keyboard and not use a compact roll-up keyboard that is slow to use and flaky. (I REALLY wish my Toughbooks had the backlit keyboards, especially instead of the stupid crappy touchscreens that I don’t use…) Also, you may want to consider trying to use a fully-encrypted SD card for the Pi’s OS for security purposes. As far as my other systems go, I use fully-encrypted systems. On the Pi, though, I have been…cautious…considering the inherent filesystem/card issues the Pi is infamous for. YMMV. I plan on testing that in the future, but haven’t yet. Until then I will always run and hold files in a ramdisk to keep from writing to the SD card. Lastly, as before, all scripts require to be run via ‘sudo’ and the Codebook Generator may require a much larger ramdisk then I previously set in the prior files depending on your selections during the codebook KEY creation. That is a simple adjustment, just edit the line ‘mkfs -q /dev/ram1 1024’ to read ‘mkfs -q /dev/ram1 49152’ . If you’re going to generate the maximimum size table you will need a big(ger) ramdisk. While the generated file is a little under 5 Meg, the initial file created is 15.2 Meg and then temporary “holding” files are required for the sorting and character substitution commands that are otherwise flaky when writing to the files they are operating on (sed in particular.) 32 Meg turns out to be just a hair too small…
Side note: these scripts will run on other linux hardware besides the Pi. However, you won’t get the added security of using a true hardware random number generator UNLESS you have one installed and implemented on your system. (Keep in mind that the currently-presented system is also designed as an air-gapped system for security WITHOUT any BT/Wifi hardware.) If you want to run the various tools on a different system you will likely have to select urandom or random (not hwrng) and will still likely have to run via “sudo” (required on the Pi for hwrng and use of the ramdisk.) If you select “random” it may seem that the script isn’t running, in particular if you have a SSD and not a HDD. That’s because your system is not building entropy. See the previous paper for more details.
The scripts:
The scripts are mostly variations on a theme: generating random things for use to secure radio communications, changed from one script to another to meet general requirements.
As previously, all scripts are written in the Bash scripting language. This is for the following reasons:
1) I don’t know Python (or anything else, for that matter.) – The biggest reason. If a Python guru would like to convert these over to Python, please do and publish!
2) Bash is considered the simplest language and so the largest number of people should be able to check it for issues, and modify it as they wish.
I’m sure there are many more elegant ways to have written these scripts, but then nobody has ever accused me of being elegant (or a programmer.) So all of you elegant programmers can…fix them yourselves and then put them out for the rest of us.
Callsign Alias Generator – CallSignGen.sh
This script generates alias callsigns for each “permanent” callsign for every period (time rotations, e.g., 24-hour) to help minimize opfor’s ability to collect useful information from your communications. You choose how many permanent callsigns and periods to generate for. It automatically checks for duplicates, discards them and regenerates should one occur. The resulting table is both displayed in the terminal window, and is copied to the clipboard.
—————————————————-
#!/bin/bash
#
# Non-Duplicating Alias Callsign Generator Program
#
# This determines how many characters to generate at a time for the callsigns
blocksize=1
# This determines how many periods to generate callsigns for
read -p “How many Periods to generate for?” blockrow
# This determines how many “permanent” callsigns to generate for
read -p “How many Callsigns? ” pagecount
# Have user pick algorithm to use for picking numbers or letters
read -p “Which RNG Device? hwrng-(1), urandom-(2) or random-(3). Default is 1 ” DEVICE
case $DEVICE in
3)
RNGAlg=random
;;
2)
RNGAlg=urandom
;;
*)
RNGAlg=hwrng
;;
esac
# where to generate the files – putting it in a ramdisk
# Alias Callsigns to print
CSs=’/ramdisk/CSs.txt’
# temporary callsign holding place while building callsign
tempCS=’/ramdisk/tempCS.txt’
# assembled temp callsign for duplicate checking
PreTemp=’/ramdisk/PreTemp.txt’
# hold Previous PreTemp
PreTempHold=’/ramdisk/PreTempHold.txt’
#length of Duplicate
DupCheck=’/ramdisk/DupCheck.txt’
# Create a ramdisk to put the tables in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
echo
echo “$RNGAlg it is…”
echo
echo
echo ” grinding away…”
echo
# Generate a row of Callsigns
echo -n “” >> $PreTempHold
echo -n “” >> $PreTemp
for ((x=1; x<=$pagecount; x++))
do
counter=1
while [ $counter -le $blockrow ]
do
randnum1=$(base32 /dev/$RNGAlg | tr -dc ‘A-Z’ | head -c $blocksize)
echo -n $randnum1 > $tempCS
echo -n “” >> $tempCS
randnum2=$(xxd -p /dev/$RNGAlg | tr -dc [:digit:] | head -c $blocksize)
echo -n $randnum2 >> $tempCS
echo -n “” >> $tempCS
randnum3=$(base32 /dev/$RNGAlg | tr -dc ‘A-Z’ | head -c $blocksize)
echo -n $randnum3 >> $tempCS
echo -n ” ” >> $tempCS
cat /ramdisk/PreTemp.txt > $PreTempHold
cat /ramdisk/tempCS.txt >> $PreTemp
sort /ramdisk/PreTemp.txt | uniq -D >> $DupCheck
Duplicate=$(</ramdisk/DupCheck.txt)
if [ ${#Duplicate} -gt 0 ]
then
rm $tempCS
rm $DupCheck
rm $PreTemp
cat /ramdisk/PreTempHold.txt > $PreTemp
else
echo “” >> $PreTemp
echo -n $randnum1 >> $CSs
echo -n $randnum2 >> $CSs
echo -n $randnum3 >> $CSs
if [ $counter -lt $blockrow ]
then
echo -n ” ” >> $CSs
fi
((counter++))
fi
done
echo “” >> $CSs
done
xclip -i /ramdisk/CSs.txt -sel clip
cat /ramdisk/CSs.txt
echo
echo “The Callsign table is now in X’s clipboard.”
echo
echo
# Prepare to erase the table from the ramdisk
read -p “Press (return) to delete the Callsign table from the ramdisk…” dumpit
rm $CSs
rm $PreTemp
rm $tempCS
rm $DupCheck
rm $PreTempHold
echo
echo “Don’t forget to clear X’s clipboard when you are done!!!”
——————————————————
Password Generator – PasswordGen.sh
This script generates passwords for use with (primarily) symmetric digital encryption methods. For example, it can be used to generate keys for use with DMR radios that have encryption available (and subsequently entered into the SOI Helper Spreadsheet.) Options are length (including a random length,) uppercase letters, lowercase letters, numbers, or any combination of these. Also, a trailing underscore (_) is available if desired. Other than that there are no symbols available. I did not implement those as symbols just become a big pain when included in many password programs and applications as to which ones are allowed varies greatly, not to mention the extra key-presses/button-pushes required. If you want a stronger password, use a longer one. (Try using symbols on your Anytone/Motorola with 64 characters and let me know how much fun that is.)
——————————————————
#!/bin/bash
#
# Password Generator Program
#
# Have user pick algorithm to use for picking numbers or letters
read -p “Which RNG Device? hwrng-(1), urandom-(2) or random-(3). Default is 1 ” DEVICE
case $DEVICE in
3)
RNGAlg=random
;;
2)
RNGAlg=urandom
;;
*)
RNGAlg=hwrng
;;
esac
# This determines how many columns per line (period) of the PWs
read -p “How many passwords per period?” blockrow
# This determines how many Periods (rows) to print down the page
read -p “How many Periods? ” pagecount
# This determines how many characters in the Passwords
read -p “How many characters in passwords? Enter # or (r)andom (1-99). Default=16. Limit=99.” CHARACTERS
case $CHARACTERS in
[$(($CHARACTERS))]*)
blocksize=$CHARACTERS
;;
r*)
randnum=$(xxd -p /dev/$RNGAlg | tr -dc [:digit:] | head -c 2)
blocksize=$randnum
;;
*)
blocksize=16
;;
esac
if [ $blocksize -lt 1 ]
then
blocksize=16
fi
if [ $blocksize -gt 99 ]
then
blocksize=16
fi
read -p “Types of characters: (u)ppercase only, (l)owercase only, (b)oth cases, (n)umbers only, (ua/la/ba/)add numbers to letters (default ba).” TYPE
case $TYPE in
u)
KEY=’A-Z’
;;
l)
KEY=’a-z’
;;
b)
KEY=”‘A-Z”a-z'”
;;
n)
KEY=’0-9′
;;
ua)
KEY=”‘A-Z”0-9′”
;;
la)
KEY=”‘a-z”0-9′”
;;
*)
KEY=”‘A-Z”a-z”0-9′”
;;
esac
read -p “Append underscore (_) to passwords? y or n(default).” UNDERSCORE
# where to generate the page of PWs – putting it in a ramdisk
PWpath=’/ramdisk/PW.txt’
# Create a ramdisk to put the tables in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
echo
echo “$RNGAlg it is…”
echo
echo
echo ” grinding away…”
echo
# Generate a row of Callsigns
for ((x=1; x<=$pagecount; x++))
do
for ((y=1; y<=$blockrow; y++))
do
randnum=$(base64 /dev/$RNGAlg | tr -dc $KEY | head -c $blocksize)
echo -n $randnum >> $PWpath;
if [ $UNDERSCORE == y ]
then
echo -n “_” >> $PWpath
fi
if [ $y -lt $blockrow ]
then
echo -n ” ” >> $PWpath
fi
done
echo “” >> $PWpath
echo “” >> $PWpath
done
# Send the table to X’s clipboard
xclip -i /ramdisk/PW.txt -sel clip
echo
echo “The Password table is now in X’s clipboard.”
echo
echo
# Prepare to erase the table from the ramdisk
read -p “Press (return) to delete the OTP table from the ramdisk…” dumpit
rm $PWpath
echo
echo “Don’t forget to clear X’s clipboard when you are done!!!”
——————————————————
1-Way Authentication Generator – 1-WayAuthentication.sh
This script generates a table for use between two parties (e.g., TOC to Patrol) for a single period. Selectable options are the length of the authentication code generated, number of codes per period and number of columns of codes. I’m not crazy about the usual implementation of the 1-Way Authorization and so have added some extra options should you wish to vary your implementation of it. More options are better, IMHO. You can opt to have the rows and/or columns numbered. If both are numbered, and the (number of rows) X (number of columns) <= 26, then a chart is printed out so that the combination can be reduced to a single letter. (e.g., Row1Col1=A. If the code in that position is ER, then it can be referred to specifically as AER. ) This can help tighten up the security and keep the number of characters to transmit down.
——————————————————
#!/bin/bash
#
# 1-Way Authentication Generator Program
# This generator creates a table for a single Unit/Callsign for One Period. Run multiple times for each Unit and/or Period.
#
echo
read -p “How many periods to generate for? Default=10 ” PerNums
case $PerNums in
[$((PerNums))]*)
NumOfPERIODS=$PerNums
;;
*)
NumOfPERIODS=10
;;
esac
echo
# This determines how many characters per authentication group
read -p “How many letters per authentication group? 1-9. Default=2.” LETTERS
case $LETTERS in
[$(($LETTERS))]*)
SIZE=$LETTERS
;;
*)
SIZE=2
;;
esac
if [ $SIZE -lt 1 ]
then
SIZE=2
fi
if [ $SIZE -gt 9 ]
then
SIZE=2
fi
# This determines how many Columns of Codes per Period
read -p “How many Columns of codes per period? Default/Limit=9 ” COLS
case $COLS in
[$(($COLS))]*)
COLUMNS=$COLS
if [ $COLS -gt 9 ]
then
COLUMNS=9
fi
;;
*)
COLUMNS=$( expr 9 )
;;
esac
read -p “Would you like Column Numbers? Default=n ” ColNums
# This determines how many Codes per Period to print down the page
read -p “How many rows of Codes per Period? Default/Limit=9 ” RS
case $RS in
[$(($RS))]*)
ROWS=$RS
if [ $RS -gt 9 ]
then
ROWS=9
fi
;;
*)
ROWS=$( expr 9 )
;;
esac
read -p “Would you like Row Numbers? Default=n ” RowNums
# Have user pick algorithm to use for picking numbers or letters
read -p “Which RNG Device? hwrng-(1), urandom-(2) or random-(3). Default is 1 ” DEVICE
case $DEVICE in
3)
RNGAlg=random
;;
2)
RNGAlg=urandom
;;
*)
RNGAlg=hwrng
;;
esac
# where to generate the page of 1-Way Authentications – putting it in a ramdisk
AUTHpath=’/ramdisk/AUTH.txt’
# Create a ramdisk to put the tables in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
echo “” > $AUTHpath
echo
echo “$RNGAlg it is…”
echo
echo
echo ” grinding away…”
echo
PERIOD=1
while [ $PERIOD -le $NumOfPERIODS ]
do
# Generate a row of 1-Way Authentications
# Start with row of column headers
if [ “$ColNums” == “y” ]
then
if [ “$RowNums” == “y” ]
then
SPACING=$SIZE/2+3
for ((a=1; a<=$SPACING; a++))
do
echo -n ” ” >> $AUTHpath
done
fi
for ((y=1; y<=$COLUMNS; y++))
do
echo -n $y >> $AUTHpath
SPACING=$SIZE
for ((a=1; a<=$SPACING; a++))
do
if [ $y -lt $COLUMNS ]
then
echo -n ” ” >> $AUTHpath
fi
done
done
fi
echo “” >> $AUTHpath
echo “” >> $AUTHpath
# Now the Codes
for ((x=1; x<=$ROWS; x++))
do
for ((y=1; y<=$COLUMNS; y++))
do
if [ “$RowNums” == “y” ]
then
if [ $y = 1 ]
then
echo -n $x” ” >> $AUTHpath
fi
fi
randnum=$(base32 /dev/$RNGAlg | tr -dc ‘A-Z’ | head -c $SIZE)
echo -n $randnum >> $AUTHpath
if [ $y -lt $COLUMNS ]
then
echo -n ” ” >> $AUTHpath
fi
done
echo “” >> $AUTHpath
echo “” >> $AUTHpath
done
((PERIOD++))
echo “” >> $AUTHpath
done
# Print the Coordinate Chart if applicable
TableSize=$( expr $COLUMNS \* $ROWS )
if [ $( expr $TableSize ) -lt 27 ]
then
alphabet=ABCDEFGHIJKLMNOPQRSTUVWXYZ
counter=0
for ((x=0; x<=$ROWS; x++))
do
if [ $x -eq 0 ]
then
echo -n ” ” >> $AUTHpath
for ((y=1; y<=$COLUMNS; y++))
do
echo -n $y >> $AUTHpath
if [ $y -lt $COLUMNS ]
then
echo -n ” ” >> $AUTHpath
else
echo “” >> $AUTHpath
echo “” >> $AUTHpath
fi
done
else
echo -n $x” ” >> $AUTHpath
for ((y=1; y<=$COLUMNS; y++))
do
echo -n ${alphabet:$counter:1} >> $AUTHpath
if [ $y -lt $COLUMNS ]
then
echo -n ” ” >> $AUTHpath
else
echo “” >> $AUTHpath
echo “” >> $AUTHpath
fi
((counter++))
done
fi
done
fi
# Send the table to X’s clipboard
xclip -i /ramdisk/AUTH.txt -sel clip
echo
echo “The 1-Way Authentication table is now in X’s clipboard.”
echo
# Prepare to erase the table from the ramdisk
read -p “Press (return) to delete the OTP table from the ramdisk…” dumpit
rm $AUTHpath
echo
echo “Don’t forget to clear X’s clipboard when you are done!!!”
—————————————————–
DRYAD update
The previously supplied script only used the HWRNG. It now allows urandom and random so you can use it on other systems. Note that you may want to change the ramdisk size to 49152 to be consistent with the other scripts now.
Instead of reposting the entire script I’ll just post the edit:
replace:
dryad=$( echo ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’ | sed ‘s/./&\n/g’ | shuf –random-source=/dev/hwrng | tr -d “\n” )
with:
dryad=$( echo ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’ | sed ‘s/./&\n/g’ | shuf –random-source=/dev/$RNGAlg | tr -d “\n” )
Then and add below (read -p “How many DRYAD Tables to generate? ” tables):
# Have user pick algorithm to use for picking numbers or letters
read -p “Which RNG Device? hwrng-(1), urandom-(2) or random-(3). Default is 1 ” DEVICE
case $DEVICE in
3)
RNGAlg=random
;;
2)
RNGAlg=urandom
;;
*)
RNGAlg=hwrng
;;
esac
—————————————————–
CodeBook Creation Tools
This is a set of scripts: the Codetable Key and Mutilation Table Generator, Codetable Key Shuffler, and Index Generator.
The first script generates what is called a “mutilation table” and a list of codes that correlate to it for use in assembling a secure codebook. Don’t worry – detailed instructions follow this preliminary information. (Instructions are also built into the scripts.)
A good codebook should use codes that include some form of integral error correction. I’m not going to re-hash this, instead pointing you to basic information to read:
http://users.telenet.be/d.rijmenants/papers/one_time_pad.pdf – Chapter 6
http://www.quadibloc.com/crypto/mi0602.htm – Just the first section on error-correcting codes.
There are others if you’re so inclined, but these two are enough AND required.
Many are familiar with trigrams (also called trigraphs depending on your source) – a set of 3 seemingly random letters that stand for something as listed in a codetable or codebook. Properly implemented, the codes should be constructed so that an error in copying, transmission, etc., can be detected and corrected easily whether a character is corrupted, dropped or two characters transposed. This is done by adding extra “data” to the code, similar to how computers handle data (e.g., a parity bit.) This is how it was done prior to the computer age. (Remember, when faced with a hi-tech threat, go low-tech.) With the best implementation there are only 126 codes using the English alphabet that result in such a self-error-correcting system. Any two of the three letters, in any order, enables you to correctly decode the trigraph/trigram. The DIANA system utilizes one version of these trigraphs for OTP encryption. The next best system using three letters results in over 600 possible codes but is not nearly as robust with regards to error correction. Rijmenant’s paper (mentioned above) includes numeral-based tables (ideal for using numerical One Time Pads) but are still woefully undersized if a full codebook is desired. In days-gone-by, creating a full codebook was a giant undertaking, requiring thousands of man-hours to create and assemble. Additionally, it was only available via hardcopy. Today, the task is trivial by comparison. Additionally, the codebook can be made as secure as a OTP. Here’s how: (Ensure you have read at least the two mentioned articles.)
The Codebook Key Generator script will ask for the size of the table you want to create. Initially I allowed for options other than 10 or 26. In my opinion, there is little point in selecting anything other than 10 or 26, 10 for the largest table of digits, 26 for the largest table of letters. Because of of the scramble feature I later updated the script with, that became too cumbersome. Note that other options can be added by editing the scripts (both the Generator and the Shuffler would need to be edited.) I have left some commented lines in those scripts that I used for testing so if you want to do so, you can see what needs to be done. Anything less than either just reduces the size of the codebook but still requires the same “overhead” when encrypting with a OTP or transmitting via radio. It will then generate a table of all available 5-character codes (pentagrams/pentagraphs) along with the correlating mutilation table to enable you to determine the correction of any errors committed during the transmission process. For this system to work an odd number of characters is required, therefore if an even number of characters is chosen (like the English alphabet – 26) then the table must add 1, with the resulting mutilation table having *s in it. Those entries indicate that that particular permutation is unavailable, so disregard it. The list of codes generated automatically disregards those codes. A full table of 5-character alphabetic codes results in 440,051 self-correcting codes.
Another option in the Table Generator relates to the use of position 3 in the codes. Technically, position 3 is not needed and it can be eliminated, however the position 3 character is required for error-correction to work. Realize that if you wish to shorten the codes from 5 characters to 4 characters for brevity sake you can do so by just disregarding the character in position 3. (e.g., SHRIJ becomes SHIJ.) You will lose almost all error-correction capability, but retain the full number of usable codes. I have included a column of the 4-character codes (position 3 eliminated) in case you want to sacrifice the error correction for a shorter code. Another option with position 3 is the offset. Technically, the actual value of position 3 is not important (for error-correction) as long as the table retains the same basic structure. Realize that the individual characters have no actual value. e.g., 4 is not necessarily 1 more than 3, it is actually just a place-holder just like 3. Therefore, an “offset” is available that results in the starting character of the position 3 table changing (the bottom-left table.) This can help with obfuscation, and also was used in the old times to keep all code sets (of the same size) from being equivalent to those created by others – which then results in up to 26 different tables. (That last one honestly matters nothing at all, and is easily nullified. I just included it for completeness. A cryptographer of even dismal abilities would be able to see what was used.) Never fear, with the wonders of the microprocessor age, we can fix this. The un-completed code table is held as OrderedCodeTable.txt.
The Mutilation Table is saved to MT.txt. Both files reside in the ramdisk ( /ramdisk/ ). Neither of these files are really a security risk should they get out into the wild but realize they WILL disappear from the ramdisk once you shutdown. As it can take a while to generate the code table – especially on the Pi – I separated the codebook creation steps into a couple scripts. This way you can run the Generator on a fast machine (it does not require the TRNG) and then save it and copy to the ramdisk you will use on the Pi. Copy both files to an encrypted drive first (like a Veracrypt container.) If you created a large code table you will be irritated if you don’t save it as it can a long time for the larger ones – hours.
The next script you will run is “The Shuffler script” which will give you the option to “scramble” the characters used in the codes, and then it will shuffle the assembled OrderedCodeTable codes. Use of a “seed” could probably be used should you want to make a shuffled list of codes that is predictable for use in distribution. That’s on you if you do that though. It’s not the right way to do things, e.g. transmit a codebook key.
The Shuffler script will take both the MT.txt and the OrderedCodeTable.txt file from within the ramdisk and perform a few operations on them. Don’t bother looking at those files as they are in a preliminary form depending on options that were previously selected – the Shuffler script will clean them up. First is the option to scramble the codes. This is actually a variation of the “shuffle” function but is applied to the character set used for the codetable and associated mutilation table. This then makes the actual codetable unique (not now just one of up to 26 variations based on the Offset mentioned above. Instead, for a 26-character codetable there are now 26! (26 factorial) different codetables for any original codetable set. (That’s over 4×10^26 possibilities.) I hope it’s obvious that you should do this, but it’s your option. The script then shuffles all the 5/4-character codes so that they are now in a random order, and not the originally derived order, and places the resulting file as KEY.txt in the ramdisk. Make sure to copy this file to an encrypted drive also. (The 5-character and 4-character codes are matched and kept together.)
Next we create the Index. The system for creating the Index file/column is as follows:
Obviously, you will need both (or all) parties to the codebook to possess either a hardcopy or softcopy of all word-sources. Word sources can be dictionaries, phrase books, word lists, and/or other codebooks. Electronic versions are obviously the easiest to use and handle.
After all word-sources are chosen, they should be identified and listed by number. For instance, Webster’s Dictionary of English Usage – 1989 (https://list-english.ru/img/newpdf/dictpdf/6.pdf) at 994 pages is word-source #1. “DOD Dictionary of Military and Associated Terms” – 2004 (https://www.jcs.mil/Portals/36/Documents/Doctrine/pubs/dictionary.pdf) 366 pages is word-source #2. Others can be added, but this is just an example of assembly so we’ll only use these two for now. Words or phrases (or whatever) in the sources can be indexed by the following format: “wordsource#-page#-column#-entry#” , just like the old book-codes many of you should be familiar with. E.g., with these two sources, “1-106-2-2” correlates to “any other” in Webster’s. “2-225-1-5” correlates to “tradecraft” in the DoD Dictionary. If you happen to have an actual codebook, this system can be easily adapted for it’s numerical entries, just give it a little thought.
To help create the Index file, a simple script to generate the Index file is included. It starts by asking if you will be starting with a new list, or want to add to the previous list you created (Make sure that the previous INDEX.txt is in the ramdisk.) It then asks for the Source name, word-source number, it’s number of pages, its number of columns per page, and a limit on the number of words per column. It will then ask if you want to add another source, allowing you to do so until you are done. It will then generate a numbered list of the Sources (SOURCELIST.txt) and the INDEX.txt file – both in the ramdisk. You are then presented with the option to have the INDEX.txt file repeatedly multiplied so you don’t have to do multiple manual copy/paste operations into the Codebook spreadsheet (depending on the file’s size and the computer system’s copy/paste ability.) It automatically stops the growth before growing past the size of Key.txt. It also checks to see that you have not created an Index that without being multiplied is still larger than the KEY file. It will then look at the size of the KEY.txt file and that of the Index and ask you how much to “pad” the Index at the beginning before integrating into the final KEY.txt. (see below.) I suggest leaving some “padding” at the beginning and end for adding special things you may want to add that do not “fit” with the normal word-source format. Leaving extra blanks at Index positions at the end (or beginning) can also be filled in with modifications to words (declensions, etc.) to enhance your ability to communicate with the codebook. For instance, having a batch of codes with “-ing”, “-ution”, “-ed” and so on. When done the script will combine the KEY and Index into one file that matches up the randomized codes with the Index entries. The Index creation script also generates a file that lists the word-sources used for creating the Index. You should maybe guard this file from release though…(cough-cough.) Save it to the encrypted drive.
Just FYI – large tables take a long time to generate. A 26-character table on my old 2GHz Laptop took almost 3 hours and 17 minutes to generate the two basic files. The list contains 440,051 codes. The Pi2 will take…longer. On the laptop the 10-character digit Codes took about 5-1/2 mimute. On the Pi it over 37 minutes. You have been warned. That’s a major reason I separated out the functions into multiple scripts. As the first table does not have to be guarded, it can be created on any linux machine with the appropriate dependencies/functions (like Bash.)
Also note that clipboard copy/paste does have limits should you decide to use that at some point. On my 2GHz laptop running Mint 18.3 with 8G ram I still could only copy 1/2 of an INDEX.txt (sized for the 26-character KEY) at a time, and it took about 12 minutes each time. (This was before I figured out how to do within the script almost instaneously.) A Pi2 will be more painful.
Open the final KEY.txt in a spreadsheet (like LIBRE Calc). Once a Key code is used – whether in transmission or reception – then it should be noted on the spreadsheet in an appropriate place (like the next column) and NEVER be used again. Instead, look for a synonymous Index number entry (remember they have been multiplied during the Index expansion earlier if you chose to do so) and use the associated Key code for that. With this system, it is not necessarily required to encrypt the Key code with a OTP (but if the Codebook has “escaped” then, well, you’ve got no security with the Codebook other than OTP encryption…) Encrypting will increase the security of the message, though. Decoding is done through a simple search/find of the Key code in the spreadsheet, reading the Index number corresponding, and looking it up in the word-source(s) (see below.) Encoding is done by looking up what you want to send in the appropriate word-source, determining its Index value, searching the Index value in the Codebook spreadsheet, and selecting one of the entries using its corresponding Key code.
Just FYI, these scripts also try to clue you in on what needs to be done next. Remember, again, run all scripts with ‘sudo’ as in: “sudo ./CodeTableGenerator.sh” .
There – now you have something the Russkies would have killed you for 30 years ago.
—————————————————-
#!/bin/bash
#
# Codebook Key Generator with Mutilation Table
#
# Create a ramdisk to put the tables in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
# where to generate the Tables – putting them in a ramdisk
CodeTable=’/ramdisk/CodeTable.txt’
OrderedCodeTable=’/ramdisk/OrderedCodeTable.txt’
PreSort1=’/ramdisk/PreSort1.txt’
PreSort2=’/ramdisk/PreSort2.txt’
MT=’/ramdisk/MT.txt’
MT1=’/ramdisk/MT1.txt’
MT2=’/ramdisk/MT2.txt’
echo -n “” > $CodeTable
echo -n “” > $OrderedCodeTable
echo -n “” > $PreSort1
echo -n “” > $PreSort2
echo -n “” > $MT
echo -n “” > $MT1
echo -n “” > $MT2
read -p “How many different characters/letters? 10/26 (Default=10.) ” CHAR
case $CHAR in
# 5)
# SIZE=5
# ;;
# 6)
# SIZE=6
# ;;
# 9)
# SIZE=9
# ;;
# 11)
# SIZE=11
# ;;
# 12)
# SIZE=12
# ;;
26)
SIZE=26
;;
*)
SIZE=10
;;
esac
# Determine if odd or even number of characters
if [ $(expr $SIZE % 2) != “0” ]
then
EVEN=0
else
EVEN=1
fi
OFFSET=0
read -p “Offset 3rd character? (# for offset) Must be less than # of characters. (Default is 0.) ” P3
case $P3 in
[$((P3))]*)
OFFSET=$P3
;;
*)
OFFSET=0
;;
esac
if [ $( expr $OFFSET ) -gt $( expr $SIZE – 1 ) ]
then
OFFSET=0
fi
# determine actual number of characters adjusted for odd/even required for mutilation table
S=$( expr $SIZE + $EVEN – 1 )
# Reset BASH time counter
SECONDS=0
for ((AColumn=0; AColumn<=$( expr $S ); AColumn++))
do
for ((ARow=0; ARow<=$( expr $S ); ARow++))
do
# determine value of poistion #1
A=$( expr $ARow + 0 )
B1=$( expr $A + $AColumn )
# determine value of position #2
if [ $( expr $B1 + 0 ) -gt $S ]
then
B=$( expr $B1 – $S – 1 )
else
B=$( expr $B1 + 0 )
fi
CRowCounter=0
while [ $( expr $CRowCounter + 0 ) -le $S ]
do
for (( Dc=0; Dc<=$( expr $S ); Dc++ ))
do
C1=$( expr $CRowCounter + $AColumn + $OFFSET )
if [ $( expr $C1 + 0 ) -gt $S ]
then
C2=$( expr $C1 – $S – 1 )
else
C2=$( expr $C1 )
fi
# Check it again as the CRowCounter + AColumn + OFFSET could send C1 >2x S
# determine value of position #3
if [ $( expr $C2 + 0 ) -gt $S ]
then
C=$( expr $C2 – $S – 1 )
else
C=$( expr $C2 )
fi
# determine value of position #4
D=$( expr $Dc + 0 )
# determine value of position #5
E=$( expr $D – $CRowCounter )
if [ $( expr $E + 0 ) -lt 0 ]
then
E=$( expr $E + $S + 1 )
fi
# print to screen to show its working
echo $A”-“$B”-“$C”-“$D”-“$E
At=$( expr $A ); Bt=$( expr $B ); Ct=$( expr $C ); Dt=$( expr $D ); Et=$( expr $E )
# if an even number of characters then check to see if it’s an invalid code (* in mutilation table.) If ok then add to codetable.
if [ $EVEN -eq 1 ] && [ $At != $S ] && [ $Bt != $S ] && [ $Ct != $S ] && [ $Dt != $S ] && [ $Et != $S ]
then
# Column 1 – the 5-character code and then the 4-character code#
echo -n “@”$A”@@”$B”@@”$C”@@”$D”@@”$E”@,” >> $CodeTable
echo “@”$A”@@”$B”@@”$D”@@”$E”@” >> $CodeTable
else
# if an odd number of characters then add code to codetable
if [ $EVEN -eq 0 ]
then
echo -n “@”$A”@@”$B”@@”$C”@@”$D”@@”$E”@,” >> $CodeTable
echo “@”$A”@@”$B”@@”$D”@@”$E”@” >> $CodeTable
fi
fi
done
((CRowCounter++))
done
done
done
ELAPSED=”$(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec”
echo “Time taken to generate the CodeList was $ELAPSED”
echo
# NOTE: sed is flaky when trying to write back to the same file. Must use holding files.
if [ $SIZE -le 10 ]
then
read -p “Will you be Scrambling the numerical-codes later? y/n (Default=y.) ” SCR
if [ $SCR != y ]
then
tr -d ‘@’ < $CodeTable > $PreSort2
else
cat $CodeTable > $PreSort2
fi
fi
if [ $SIZE -gt 10 ]
then
# (convert to letters)
sed ‘s:@25@:Z:g’ $CodeTable > $PreSort1
sed ‘s:@24@:Y:g’ $PreSort1 > $PreSort2
sed ‘s:@23@:X:g’ $PreSort2 > $PreSort1
sed ‘s:@22@:W:g’ $PreSort1 > $PreSort2
sed ‘s:@21@:V:g’ $PreSort2 > $PreSort1
sed ‘s:@20@:U:g’ $PreSort1 > $PreSort2
sed ‘s:@19@:T:g’ $PreSort2 > $PreSort1
sed ‘s:@18@:S:g’ $PreSort1 > $PreSort2
sed ‘s:@17@:R:g’ $PreSort2 > $PreSort1
sed ‘s:@16@:Q:g’ $PreSort1 > $PreSort2
sed ‘s:@15@:P:g’ $PreSort2 > $PreSort1
sed ‘s:@14@:O:g’ $PreSort1 > $PreSort2
sed ‘s:@13@:N:g’ $PreSort2 > $PreSort1
sed ‘s:@12@:M:g’ $PreSort1 > $PreSort2
sed ‘s:@11@:L:g’ $PreSort2 > $PreSort1
sed ‘s:@10@:K:g’ $PreSort1 > $PreSort2
sed ‘s:@9@:J:g’ $PreSort2 > $PreSort1
sed ‘s:@8@:I:g’ $PreSort1 > $PreSort2
sed ‘s:@7@:H:g’ $PreSort2 > $PreSort1
sed ‘s:@6@:G:g’ $PreSort1 > $PreSort2
sed ‘s:@5@:F:g’ $PreSort2 > $PreSort1
sed ‘s:@4@:E:g’ $PreSort1 > $PreSort2
sed ‘s:@3@:D:g’ $PreSort2 > $PreSort1
sed ‘s:@2@:C:g’ $PreSort1 > $PreSort2
sed ‘s:@1@:B:g’ $PreSort2 > $PreSort1
sed ‘s:@0@:A:g’ $PreSort1 > $PreSort2
fi
cat $PreSort2 > $OrderedCodeTable
ELAPSED=”$(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec”
echo “Time taken to clean and sort the Code Table was $ELAPSED”
echo
# Time to Build the Mutilation Table
echo “” > $MT
# Upper-Left Table
for ((A=0; A<=$( expr $S ); A++))
do
for ((B1=0; B1<=$( expr $S ); B1++))
do
B2=$( expr $A + $B1 )
if [ $B2 -gt $S ]
then
B=$( expr $A + $B1 – $S – 1 )
else
B=$( expr $A + $B1 )
fi
echo -n “@”$A”@@”$B”@ ” >> $MT
done
echo “” >> $MT
done
echo “” >> $MT
# Bottom-Left Table
for ((j1=0; j1<=$( expr $S ); j1++))
do
for ((j2=$j1; j2<=$( expr $S + $j1 ); j2++))
do
if [ $j2 -gt $S ]
then
j3=$( expr $j2 – $S – 1 + $OFFSET )
else
j3=$( expr $j2 + $OFFSET )
fi
if [ $j3 -gt $S ]
then
j4=$( expr $j3 – $S – 1 )
else
j4=$( expr $j3 )
fi
echo -n ” @”$j4″@ ” >> $MT
done
echo -n ” ” >> $MT
# Bottom-Right Table
row=$j1
for ((column=0; column<=$( expr $S ); column++))
do
X5=$( expr $column – $row )
if [ $X5 -lt 0 ]
then
X5=$( expr $X5 + $S + 1 )
fi
echo -n “@”$column”@@”$X5″@ ” >> $MT
done
echo “” >> $MT
done
# Convert Numbers to Letters
# NOTE: sed is flaky when trying to write back to the same file. Must use holding files.
# if 10 or less characters then option for digits instead of letters
if [ $SIZE -le 10 ]
then
if [ $EVEN -eq 1 ]
then
sed “s:@$S@:*:g” $MT > $MT2
else
cat $MT > $MT2
fi
fi
# if >10 characters then automatically use letters
if [ $SIZE -gt 10 ]
then
# (convert to letters)
if [ $EVEN -eq 1 ]
then
sed “s:@$S@:*:g” $MT > $MT1
else
cat $MT > $MT1
fi
sed ‘s:@26@:*:g’ $MT1 > $MT2
sed ‘s:@25@:Z:g’ $MT2 > $MT1
sed ‘s:@24@:Y:g’ $MT1 > $MT2
sed ‘s:@23@:X:g’ $MT2 > $MT1
sed ‘s:@22@:W:g’ $MT1 > $MT2
sed ‘s:@21@:V:g’ $MT2 > $MT1
sed ‘s:@20@:U:g’ $MT1 > $MT2
sed ‘s:@19@:T:g’ $MT2 > $MT1
sed ‘s:@18@:S:g’ $MT1 > $MT2
sed ‘s:@17@:R:g’ $MT2 > $MT1
sed ‘s:@16@:Q:g’ $MT1 > $MT2
sed ‘s:@15@:P:g’ $MT2 > $MT1
sed ‘s:@14@:O:g’ $MT1 > $MT2
sed ‘s:@13@:N:g’ $MT2 > $MT1
sed ‘s:@12@:M:g’ $MT1 > $MT2
sed ‘s:@11@:L:g’ $MT2 > $MT1
sed ‘s:@10@:K:g’ $MT1 > $MT2
sed ‘s:@9@:J:g’ $MT2 > $MT1
sed ‘s:@8@:I:g’ $MT1 > $MT2
sed ‘s:@7@:H:g’ $MT2 > $MT1
sed ‘s:@6@:G:g’ $MT1 > $MT2
sed ‘s:@5@:F:g’ $MT2 > $MT1
sed ‘s:@4@:E:g’ $MT1 > $MT2
sed ‘s:@3@:D:g’ $MT2 > $MT1
sed ‘s:@2@:C:g’ $MT1 > $MT2
sed ‘s:@1@:B:g’ $MT2 > $MT1
sed ‘s:@0@:A:g’ $MT1 > $MT2
fi
cat $MT2 > $MT
echo
echo
echo “The tables (OrderedCodeTable.txt and MT.txt) are NOT in X’s clipboard.”
echo “They are in /ramdisk/ . Save them to another drive for use later without having to re-generate them.”
echo “These are NOT SENSITIVE documents and need not be saved to an encrypted drive.”
echo “Run \” sudo (the shuffler script) \” next with these files in the /ramdisk/ .”
echo
echo
# Prepare to erase the supporting tables from the ramdisk
read -p “Press (return) to delete the temporary files from the ramdisk…” dumpit
rm $CodeTable
rm $PreSort1
rm $PreSort2
rm $MT1
rm $MT2
—————————————————-
#!/bin/bash
#
# Codebook Key Shuffler Generator
#
# Create a ramdisk to put the Key in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
# where to generate the shuffled Key – putting it in a ramdisk
OrderedCodeTable=’/ramdisk/OrderedCodeTable.txt’
KEY=’/ramdisk/KEY.txt’
INDEX=’/ramdisk/INDEX.txt’
ScrambledCharacters=’/ramdisk/ScrambledCharacters.txt’
ScHold1=’/ramdisk/ScHold1.txt’
ScHold2=’/ramdisk/ScHold2.txt’
MTHold1=’/ramdisk/MTHold1.txt’
MTHold2=’/ramdisk/MTHold2.txt’
MT=’/ramdisk/MT.txt’
echo -n “” > $ScrambledCharacters
echo -n “” > $ScHold1
echo -n “” > $ScHold2
echo -n “” > $MTHold1
echo -n “” > $MTHold2
echo
# Have user pick algorithm to use for picking numbers or letters
read -p “Which RNG Device? hwrng-(1), urandom-(2) or random-(3). (Default=1.) ” DEVICE
case $DEVICE in
3)
RNGAlg=random
;;
2)
RNGAlg=urandom
;;
*)
RNGAlg=hwrng
;;
esac
# Reset BASH time counter
SECONDS=0
# See if the code characters should be scrambled
read -p “Scramble the characters? y/n (Default=n.) ” SCRAMBLE
LINES=$( wc -l < $OrderedCodeTable )
# TOTALLINES is used to determine the size of the codetable as SIZE and S are not carried over from the Generator
TOTALLINES=$( expr $LINES )
if [ $SCRAMBLE = y ]
then
case $TOTALLINES in
# 14641)
# shuf -e @00@ @01@ @02@ @03@ @04@ @05@ @06@ @07@ @08@ @09@ @10@ | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
# ;;
# 19141)
# shuf -e @00@ @01@ @02@ @03@ @04@ @05@ @06@ @07@ @08@ @09@ @10@ @11@ | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
# ;;
440051)
shuf -e @00@ @01@ @02@ @03@ @04@ @05@ @06@ @07@ @08@ @09@ @10@ @11@ @12@ @13@ @14@ @15@ @16@ @17@ @18@ @19@ @20@ @21@ @22@ @23@ @24@ @25@ | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
;;
# 625)
# shuf -e A B C D E | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
# ;;
# 1111)
# shuf -e A B C D E F | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
# ;;
# 6561)
# shuf -e A B C D E F G H I| tr ‘\n’ ‘ ‘ > $ScrambledCharacters
# ;;
*)
shuf -e A B C D E F G H I J | tr ‘\n’ ‘ ‘ > $ScrambledCharacters
;;
esac
# Scramble the Tables
SWITCH=$( cat “$ScrambledCharacters” )
COUNTER=0
# For the Digit Tables
if [ $TOTALLINES == ‘9091’ ] || [ $TOTALLINES == ‘625’ ] || [ $TOTALLINES == ‘1111’ ] || [ $TOTALLINES == ‘6561’ ]
then
x=${SWITCH:$COUNTER:1}
sed “s:@0@:${x}:g” $OrderedCodeTable > $ScHold1
sed “s:@0@:${x}:g” $MT > $MTHold1
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@1@:${x}:g” $ScHold1 > $ScHold2
sed “s:@1@:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@2@:${x}:g” $ScHold2 > $ScHold1
sed “s:@2@:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@3@:${x}:g” $ScHold1 > $ScHold2
sed “s:@3@:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@4@:${x}:g” $ScHold2 > $ScHold1
sed “s:@4@:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@5@:${x}:g” $ScHold1 > $ScHold2
sed “s:@5@:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@6@:${x}:g” $ScHold2 > $ScHold1
sed “s:@6@:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@7@:${x}:g” $ScHold1 > $ScHold2
sed “s:@7@:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@8@:${x}:g” $ScHold2 > $ScHold1
sed “s:@8@:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+2))
x=${SWITCH:$COUNTER:1}
sed “s:@9@:${x}:g” $ScHold1 > $ScHold2
sed “s:@9@:${x}:g” $MTHold1 > $MTHold2
sed “s:A:0:g” $ScHold2 > $ScHold1
sed “s:A:0:g” $MTHold2 > $MTHold1
sed “s:B:1:g” $ScHold1 > $ScHold2
sed “s:B:1:g” $MTHold1 > $MTHold2
sed “s:C:2:g” $ScHold2 > $ScHold1
sed “s:C:2:g” $MTHold2 > $MTHold1
sed “s:D:3:g” $ScHold1 > $ScHold2
sed “s:D:3:g” $MTHold1 > $MTHold2
sed “s:E:4:g” $ScHold2 > $ScHold1
sed “s:E:4:g” $MTHold2 > $MTHold1
sed “s:F:5:g” $ScHold1 > $ScHold2
sed “s:F:5:g” $MTHold1 > $MTHold2
sed “s:G:6:g” $ScHold2 > $ScHold1
sed “s:G:6:g” $MTHold2 > $MTHold1
sed “s:H:7:g” $ScHold1 > $ScHold2
sed “s:H:7:g” $MTHold1 > $MTHold2
sed “s:I:8:g” $ScHold2 > $ScHold1
sed “s:I:8:g” $MTHold2 > $MTHold1
sed “s:J:9:g” $ScHold1 > $ScHold2
sed “s:J:9:g” $MTHold1 > $MTHold2
cat $ScHold2 > $OrderedCodeTable
cat $MTHold2 > $MT
else
# For the non-Digit Only Tables
x=${SWITCH:$COUNTER:4}
sed “s:A:${x}:g” $OrderedCodeTable > $ScHold1
sed “s:A:${x}:g” $MT > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:B:${x}:g” $ScHold1 > $ScHold2
sed “s:B:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:C:${x}:g” $ScHold2 > $ScHold1
sed “s:C:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:D:${x}:g” $ScHold1 > $ScHold2
sed “s:D:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:E:${x}:g” $ScHold2 > $ScHold1
sed “s:E:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:F:${x}:g” $ScHold1 > $ScHold2
sed “s:F:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:G:${x}:g” $ScHold2 > $ScHold1
sed “s:G:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:H:${x}:g” $ScHold1 > $ScHold2
sed “s:H:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:I:${x}:g” $ScHold2 > $ScHold1
sed “s:I:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:J:${x}:g” $ScHold1 > $ScHold2
sed “s:J:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:K:${x}:g” $ScHold2 > $ScHold1
sed “s:K:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:L:${x}:g” $ScHold1 > $ScHold2
sed “s:L:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:M:${x}:g” $ScHold2 > $ScHold1
sed “s:M:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:N:${x}:g” $ScHold1 > $ScHold2
sed “s:N:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:O:${x}:g” $ScHold2 > $ScHold1
sed “s:O:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:P:${x}:g” $ScHold1 > $ScHold2
sed “s:P:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:Q:${x}:g” $ScHold2 > $ScHold1
sed “s:Q:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:R:${x}:g” $ScHold1 > $ScHold2
sed “s:R:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:S:${x}:g” $ScHold2 > $ScHold1
sed “s:S:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:T:${x}:g” $ScHold1 > $ScHold2
sed “s:T:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:U:${x}:g” $ScHold2 > $ScHold1
sed “s:U:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:V:${x}:g” $ScHold1 > $ScHold2
sed “s:V:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:W:${x}:g” $ScHold2 > $ScHold1
sed “s:W:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:X:${x}:g” $ScHold1 > $ScHold2
sed “s:X:${x}:g” $MTHold1 > $MTHold2
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:Y:${x}:g” $ScHold2 > $ScHold1
sed “s:Y:${x}:g” $MTHold2 > $MTHold1
COUNTER=$((COUNTER+5))
x=${SWITCH:$COUNTER:4}
sed “s:Z:${x}:g” $ScHold1 > $ScHold2
sed “s:Z:${x}:g” $MTHold1 > $MTHold2
sed “s:@00@:A:g” $ScHold2 > $ScHold1
sed “s:@00@:A:g” $MTHold2 > $MTHold1
sed “s:@01@:B:g” $ScHold1 > $ScHold2
sed “s:@01@:B:g” $MTHold1 > $MTHold2
sed “s:@02@:C:g” $ScHold2 > $ScHold1
sed “s:@02@:C:g” $MTHold2 > $MTHold1
sed “s:@03@:D:g” $ScHold1 > $ScHold2
sed “s:@03@:D:g” $MTHold1 > $MTHold2
sed “s:@04@:E:g” $ScHold2 > $ScHold1
sed “s:@04@:E:g” $MTHold2 > $MTHold1
sed “s:@05@:F:g” $ScHold1 > $ScHold2
sed “s:@05@:F:g” $MTHold1 > $MTHold2
sed “s:@06@:G:g” $ScHold2 > $ScHold1
sed “s:@06@:G:g” $MTHold2 > $MTHold1
sed “s:@07@:H:g” $ScHold1 > $ScHold2
sed “s:@07@:H:g” $MTHold1 > $MTHold2
sed “s:@08@:I:g” $ScHold2 > $ScHold1
sed “s:@08@:I:g” $MTHold2 > $MTHold1
sed “s:@09@:J:g” $ScHold1 > $ScHold2
sed “s:@09@:J:g” $MTHold1 > $MTHold2
sed “s:@10@:K:g” $ScHold2 > $ScHold1
sed “s:@10@:K:g” $MTHold2 > $MTHold1
sed “s:@11@:L:g” $ScHold1 > $ScHold2
sed “s:@11@:L:g” $MTHold1 > $MTHold2
sed “s:@12@:M:g” $ScHold2 > $ScHold1
sed “s:@12@:M:g” $MTHold2 > $MTHold1
sed “s:@13@:N:g” $ScHold1 > $ScHold2
sed “s:@13@:N:g” $MTHold1 > $MTHold2
sed “s:@14@:O:g” $ScHold2 > $ScHold1
sed “s:@14@:O:g” $MTHold2 > $MTHold1
sed “s:@15@:P:g” $ScHold1 > $ScHold2
sed “s:@15@:P:g” $MTHold1 > $MTHold2
sed “s:@16@:Q:g” $ScHold2 > $ScHold1
sed “s:@16@:Q:g” $MTHold2 > $MTHold1
sed “s:@17@:R:g” $ScHold1 > $ScHold2
sed “s:@17@:R:g” $MTHold1 > $MTHold2
sed “s:@18@:S:g” $ScHold2 > $ScHold1
sed “s:@18@:S:g” $MTHold2 > $MTHold1
sed “s:@19@:T:g” $ScHold1 > $ScHold2
sed “s:@19@:T:g” $MTHold1 > $MTHold2
sed “s:@20@:U:g” $ScHold2 > $ScHold1
sed “s:@20@:U:g” $MTHold2 > $MTHold1
sed “s:@21@:V:g” $ScHold1 > $ScHold2
sed “s:@21@:V:g” $MTHold1 > $MTHold2
sed “s:@22@:W:g” $ScHold2 > $ScHold1
sed “s:@22@:W:g” $MTHold2 > $MTHold1
sed “s:@23@:X:g” $ScHold1 > $ScHold2
sed “s:@23@:X:g” $MTHold1 > $MTHold2
sed “s:@24@:Y:g” $ScHold2 > $ScHold1
sed “s:@24@:Y:g” $MTHold2 > $MTHold1
sed “s:@25@:Z:g” $ScHold1 > $ScHold2
sed “s:@25@:Z:g” $MTHold1 > $MTHold2
cat $ScHold2 > $OrderedCodeTable
cat $MTHold2 > $MT
fi
else
tr -d ‘@’ < $MT > $MTHold2
cat $MTHold2 > $MT
fi
# Shuffle the lines
shuf –random-source=/dev/$RNGAlg $OrderedCodeTable > $KEY
echo
ELAPSED=”$(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec”
echo “Time taken to shuffle the Key was $ELAPSED”
echo
echo
echo “The shuffled Key is now at /ramdisk/KEY.txt.”
echo “This is a SENSITIVE file and MUST be copied to an encrypted drive ONLY!”
echo “Create Index file next by \”sudo (Index Generator script)\””
echo
read -p “Hit enter to delete temporary files…”
rm $ScHold1
rm $ScHold2
rm $MTHold1
rm $MTHold2
rm $OrderedCodeTable
—————————————————-
#!/bin/bash
#
# Codebook Index Generator
#
# Create a ramdisk to put the tables in to keep them in memory and not write to SD card
#Un-remark these if you are using this script on a non-Pi (clear the #.)
#mkfs -q /dev/ram1 49152
#mkdir -p /ramdisk
#mount /dev/ram1 /ramdisk
# where to generate the Tables – putting them in a ramdisk
INDEX=’/ramdisk/INDEX.txt’
SOURCELIST=’/ramdisk/SOURCELIST.txt’
KEY=’/ramdisk/KEY.txt’
INDEXHOLD=’/ramdisk/INDEXHOLD.txt’
BEGINNINGFILLSPACE=’/ramdisk/BEGINNINGFILLSPACE.txt’
ENDINGFILLSPACE=’/ramdisk/ENDINGFILLSPACE.txt’
TempKEY=’/ramdisk/TempKEY.txt’
echo
echo “Clear previous Index and Sourcelist? y/n Default=n “
read -p “If adding then ensure /ramdisk/INDEX.txt and SOURCELIST.txt are present. ” CLEAR
case $CLEAR in
y)
echo -n “” > $INDEX
echo “Source List” > $SOURCELIST
echo -n “” >> $SOURCELIST
;;
*)
;;
esac
echo
CONT=y
while [ “$CONT” == “y” ]
do
read -p “Word-Source Name: ” Name
echo
read -p “Word-Source #?: ” WordSource
if ! [ “$WordSource” -eq “$WordSource” ] 2> /dev/null
then
echo “Sorry integers only”
exit
fi
echo
read -p “Pages in Word-Source? ” Pages
if ! [ “$Pages” -eq “$Pages” ] 2> /dev/null
then
echo “Sorry integers only”
exit
fi
echo
read -p “Columns per Page? ” Columns
if ! [ “$Columns” -eq “$Columns” ] 2> /dev/null
then
echo “Sorry integers only”
exit
fi
echo
read -p “Word Limit per Column? ” Words
if ! [ “$Words” -eq “$Words” ] 2> /dev/null
then
echo “Sorry integers only”
exit
fi
echo
echo -n $WordSource >> $SOURCELIST
echo -n “—” >> $SOURCELIST
echo $Name >> $SOURCELIST
for (( p=1; p<=Pages; p++ ))
do
for (( c=1; c<=Columns; c++ ))
do
for (( w=1; w<=Words; w++ ))
do
echo $WordSource”-“$p”-“$c”-“$w >> $INDEX
done
done
done
read -p “Add another Source? y/n (Default=n.) ” CONT
done
echo -n “” > $INDEXHOLD
KEYCOUNT=$( wc -l < $KEY )
INDEXCOUNT=$( wc -l < $INDEX )
if [ $( expr $INDEXCOUNT ) -gt $( expr $KEYCOUNT ) ]
then
echo “Index is too large for the Key. You must start over creating a new Index.”
exit
fi
echo “SOURCELIST.txt is in /ramdisk/”
echo
echo “Multiply/Expand INDEX to fill KEY? y/n (Default=n.) “
read -p “(Ensure KEY.txt in /ramdisk/ prior to expansion.) ” ME
echo
case $ME in
y)
cat $INDEX > $INDEXHOLD
INDEXHOLDCOUNT=$( wc -l < $INDEXHOLD )
ROOMLEFT=$( expr $KEYCOUNT – $INDEXCOUNT )
while [ $INDEXHOLDCOUNT -lt $ROOMLEFT ]
do
cat $INDEXHOLD >> $INDEX
INDEXCOUNT=$( wc -l < $INDEX )
ROOMLEFT=$( expr $KEYCOUNT – $INDEXCOUNT )
done
;;
*)
echo “exiting then…”
exit
;;
esac
OPENPADSPACE=$( expr $KEYCOUNT – $INDEXCOUNT )
echo “Room left over for Padding= “$OPENPADSPACE
echo
echo “How many entries at the beginning of KEY.txt do you wish to Pad with empty entries?”
echo “Enter no more than the number indicated above. The remainder will be at the end.”
read -p “(Default=0.) ” PAD
if [ $( expr $PAD + 0 ) -le $OPENPADSPACE ]
then
FILL=$PAD
else
FILL=0
fi
echo -n “” > $BEGINNINGFILLSPACE
echo -n “” > $ENDINGFILLSPACE
ENDFILL=$( expr “$OPENPADSPACE” – “$FILL” )
PADCOUNTER=0
while [ $PADCOUNTER -lt $FILL ]
do
echo ” ” >> $BEGINNINGFILLSPACE
((PADCOUNTER++))
done
PADCOUNTER=0
while [ $PADCOUNTER -lt $ENDFILL ]
do
echo ” ” >> $ENDINGFILLSPACE
((PADCOUNTER++))
done
cat $INDEX >> $BEGINNINGFILLSPACE
cat $ENDINGFILLSPACE >> $BEGINNINGFILLSPACE
cat $BEGINNINGFILLSPACE > $INDEX
paste -d “,” $KEY $INDEX > $TempKEY
tr ‘,’ ‘\t’ < $TempKEY > $KEY
echo
echo “INDEX Expanded and added to KEY.txt.”
echo “Copy /ramdisk/KEY.txt and SOURCELIST.txt to an ENCRYPTED drive before deleting!”
echo “Copy INDEX.txt if you may be adding to it later. Keep in mind if you expanded it.”
echo “All will be erased automatically at system shutdown, but not until them.”
echo
rm $TempKEY
rm $ENDINGFILLSPACE
rm $BEGINNINGFILLSPACE
rm $INDEXHOLD
rm $INDEX
exit
Share This Story, Choose Your Platform!
One Comment
Comments are closed.
Not sure what happened in the page formatting – all the lines for the “case” statement options that end the individual choices had a “;” removed. All the scripts with “case” options” (which is most of them) will need to be edited and each of the lines that is only “;” needs to be “;;” – “find and replace” in a text editor will work as these are the only times a “;” is present.