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.

—————————————————-

CallSignGen.sh

#!/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.)

——————————————————

PasswordGen.sh

#!/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.

——————————————————

1-WayAuthentication.sh

#!/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.

—————————————————-

CodeTableGenerator.sh

#!/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