All of these examples are geared toward Unix-like systems, however they are specifically designed for use on Linux. In addition to providing sample techniques, these examples also serve as a demonstration of the versatility of this program.
This simple bash script shows how to combine several randomly-created keys into one file, then use them one at a time without actually extracting them into separate files.
In this example, we use dd to create a random 32B base for our key file, then we proceed to encode 3 user-input messages with 32B random keys which are added to the end of the key file. To decode the messages, we use 'dd' to extract the keys from the key file one at a time and display the messages on the console.
For each call to spiral during the input phase, we use the '-e' flag for encode, the '-i' flag for standard input, the '-V' flag to create a volatile random key, and the '-n' flag to send the key to standard output.
For each call to spiral during the output phase, we use the '-d' flag for decode, the '-o' flag for standard output, and the '-t' flag to extract the key from standard input.
#!/bin/bash #Create a random header for the key file dd if=/dev/urandom of=mask bs=32 count=1 2> /dev/null #Type in message number one echo "***INPUT MESSAGE 1 ([Enter] then [Ctrl]+D when done)***" spiral -ei -nV32 msg1 >> mask echo #Type in message number two echo "***INPUT MESSAGE 2 ([Enter] then [Ctrl]+D when done)***" spiral -ei -nV32 msg2 >> mask echo #Type in message number three echo "***INPUT MESSAGE 3 ([Enter] then [Ctrl]+D when done)***" spiral -ei -nV32 msg3 >> mask echo #Wait for the user echo "Press [Enter] to read messages" wait && line #Display message number one echo "***MESSAGE 1 TEXT***" dd if=mask bs=32 skip=1 count=1 2> /dev/null | spiral -dot msg1 echo #Display message number two echo "***MESSAGE 2 TEXT***" dd if=mask bs=32 skip=2 count=1 2> /dev/null | spiral -dot msg2 echo #Display message number three echo "***MESSAGE 3 TEXT***" dd if=mask bs=32 skip=3 count=1 2> /dev/null | spiral -dot msg3 echo #Clean up rm mask msg1 msg2 msg3 |
In this example, spiral deals with data from standard input and sends all processed data to standard output. Because we are using both standard input and output, we can implicitly select both options by not providing file names on the command line when using a data processing mode.
In order to determine the beginning and end of each message (since they will vary in length), we record each message's length and start point in a separate header file. For simplicity of the script, we won't combine the header file information with the actual message data.
#!/bin/bash #Create a key pipe if it isn't there if [ ! -e "spiral-key" ]; then mkfifo spiral-key fi #Check for the key pipe again if [ ! -p "spiral-key" ]; then echo "Could not make a pipe in the current directory." exit fi #Create a random header for the key file dd if=/dev/urandom of=mask bs=32 count=1 2> /dev/null #Create a random header for the data file dd if=/dev/urandom of=msg bs=32 count=1 2> /dev/null #Create a blank header for message info echo -n > header #Message input loop for I in 1 2 3; do echo "***INPUT MESSAGE $I ([Enter] then [Ctrl]+D when done)***" #Find the message location in the data file location="`stat -c%s msg`" #Enter the next message dd if=spiral-key >> mask 2> /dev/null & spiral -e -r32 spiral-key >> msg wait #Find the message length current="`stat -c%s msg`" length="`dc -e "$current $location - p"`" #Put the message info in the header echo $location $length $I >> header echo done #Wait for the user echo "Press [Enter] to read messages" wait && line #Message read loop cat header | while read message; do #Separate header parts location="`echo $message | sed "s/ .\+$//"`" length="`echo $message | sed "s/^.\+ \(.\+\) .\+$/\1/"`" number="`echo $message | sed "s/^.\+ //"`" echo "***MESSAGE $number TEXT***" #Display the next message dd if=mask of=spiral-key bs=32 skip=$number count=1 2> /dev/null & dd if=msg bs=1 skip=$location count=$length 2> /dev/null | \ spiral -d -k spiral-key wait echo done #Clean up rm spiral-key mask msg header |
This example shows how you can securely send messages from one user account to another without having access to that user's home directory. In this example, we will be sending encrypted messages to one user from other user accounts. While the messages are in transit "out in public", they are encrypted, therefore anyone or anything intercepting them will not be able to read them. Once the messages are received, they are placed in a file in the user's home directory; inaccessible by all other users.
This example consists of 3 scripts and a little bit of setup. The first thing you will need to do is set up the pipes which will be our message interface:
bash$ cd ~ bash$ mkdir user-messages bash$ cd user-messages bash$ mkdir users bash$ mkdir message-pipes bash$ cd message-pipes bash$ mkfifo incoming user check-sum bash$ chmod 622 * bash$ mkfifo ready bash$ chmod 644 ready bash$ cd .. |
At this point you need to decide where to place the pipes so that other users can get to them, then create a symlink in the original location. If you run your own system and you are logged in as root, this is easy; just place them in /usr/local/bin with the following commands:
bash$ mv message-pipes /usr/local/bin bash$ ln -s /usr/local/bin/message-pipes . |
The next thing you will need to do is place the following script in the same location as you moved the pipe folder to:
#!/bin/bash #Change directories to the path where the script is located cd `dirname \`readlink -f "$0"\`` #Make sure this user has a key to send messages with if [ ! -f ~/msg-key ]; then echo "You do not have a key to send secure messages." exit fi #Wait to see if the message script will accept out message echo "Waiting for message server..." #Waiting... (use [Ctrl]+C if nothing happens) if [ "`cat message-pipes/ready`" != "ready" ]; then echo "Message server busy; try again later." exit fi #Send our identity whoami > message-pipes/user echo echo "***ENTER MESSAGE***" #Send our encrypted message (and check sums for verification) spiral -eic -k ~/msg-key message-pipes/incoming > message-pipes/check-sum echo "***MESSAGE SENT***" |
Once you have the above script in place, you need to set up the message server script and the kill script. Save both of these in your '~/user-messages' directory:
#!/bin/bash #Change directories to the path where the script is located cd `dirname \`readlink -f "$0"\`` #Make sure there isn't another one running; that would be bad! if [ -e "running" ]; then echo "Message server already running." exit fi #Set the running indicator with the new process number ps | grep "`basename $0`" | head -n1 | egrep -o "^ [0-9]+" > running #Some regular expressions to parse check sums with half_sum="[0-9A-F]{16}" whole_sum="$half_sum $half_sum" #Start of the message loop while [ -e "running" ]; do #Let everyone know the server is ready to receive echo -n "ready" > message-pipes/ready #If the running indicator is gone then exit if [ ! -e "running" ]; then exit fi #Extract the user name of the responder user="`head -n1 message-pipes/user`" #Extract the check sum that the user sent over head -n1 message-pipes/check-sum >> new-sums & #If the user key exists, extract the message to a temp file #At the same time, extract the check sum of the decoded message if [ -r "users/$user" ]; then dd if=users/$user 2> /dev/null | spiral -dfct message-pipes/incoming \ new-message | tail -n 1 >> new-sums wait else cat message-pipes/incoming > /dev/null wait rm -f new-sums continue fi #Split the two check sums up into different variables sum1="`head -n1 new-sums | egrep -o "$whole_sum"`" sum2="`tail -n1 new-sums | egrep -o "$whole_sum"`" #If the sums match then add the message if [ "$sum1" = "$sum2" ]; then date +"*%Y-%m-%d %H:%M:%S $user" >> messages cat new-message >> messages echo >> messages fi #Delete the temporary message and sum files rm -f new-message new-sums done |
#!/bin/bash #Change directories to the path where the script is located cd `dirname \`readlink -f "$0"\`` #Extract the process number from the running indicator if [ -r running ]; then process="`cat running`" else exit fi #Remove the 'running' file so the server exits the loop after this rm -f running #Acknowledge the message server (use [Ctrl]+C if nothing happens) if [ -n "`ps $process`" ]; then cat message-pipes/ready &> /dev/null fi |
Once all of the infrastructure is in place, you then need to give the appropriate users encryption keys. To do this, you will create a random key, and (if possible) hard link the key into that user's home directory:
bash$ cd ~/user-messages/users bash$ dd if=/dev/urandom bs=256 count=1 > <other user> bash$ chmod 444 <other user> bash$ cp -l <other user> ~<other user>/msg-key bash$ cd .. |
If you can't make a hard link, just make a copy of the key. If you can't place it in their home directory, place it somewhere they can copy it from and then delete it after they copy it. The main reasons for making it a hard link are: 1) you can retain ownership of the key, 2) you can change the key at any time without telling the user.
Now that everything is set up, you can start the message server running in the background:
bash$ ./receive & |
Users with keys can now send messages to you by running the 'send' script, and the messages will be logged in a file in your 'user-messages' directory:
bash$ send Waiting for message server... ***ENTER MESSAGE*** <message text> [Ctrl]+D ***MESSAGE SENT*** |
Because we are running the 'receive' script in the background (like a daemon), we can't stop it directly; we have to convince it to stop using what is already built in to it. To do this we call the 'kill' script. This erases the file 'running' (which denotes continued processing) and then unpauses the receive loop by reading from the 'ready' pipe. If the 'kill' script hangs, that means that someone is typing in a message. [Ctrl]+C your way out if you don't want to wait for the message.
This is a simple example of a data I/O interface where data goes in one end unencrypted and comes out the other end encrypted.
(This example is executed from a bash shell.)
To start with, 'cd' to a directory which you have write access to. Next, make two pipes, one for input and one for output, and make sure you have read and write access:
bash$ mkfifo input output bash$ chmod 666 input output |
Next, call spiral in the background using a random encryption key and showing check sums:
bash$ spiral -efcL -r32 key input output & |
You should protect the encryption key in case you accidentally start spiral again with the same command line:
bash$ chmod a-w key |
All you need to do now is send your data in one end and extract it from the other end:
bash$ cat <file> > input bash$ cat output > <encrypted file> |
You can send as many non-empty files through as you want, and the output files can be decrypted with the random key that's been created. Once the key is created, spiral won't open it again, therefore you can move it while spiral is still running in the background. If the check sums don't show up when you extract your file, that means that it wasn't ever actually sent to the input pipe; there was probably an error reading the file. This will incidentally cause the background process to exit.
To stop the background process, send EOF (i.e. a null data set) to the input pipe:
bash$ echo -n > input |
To make a decryption interface, make sure the previous background process is stopped (or that you are using a separate set of pipes), and call spiral in decode mode in the background:
bash$ spiral -dfcL -k key input output & |
If you use the same input and output pipes for decryption and you fail to stop the encryption background process first, the decryption process will likely just exit because the encryption process will take the data from the input pipe before the decryption process can get to it.
This is a one-command-line example which allows you to make sure that a randomly-created key was successfully recorded to the output file specified. This can be very useful for making sure that you have a useable key before relying on encrypted files (especially when sending a random key to a pipe.)
(This example is executed from a bash shell.)
First, we encrypt the file using a random key (for safety, we save the output to a separate file) and send the key to standard output, which is then analyzed for its check sum. Finally, we find the check sum of the key which was recorded:
bash$ spiral -ef -nr32 <key> <file> <encrypted file> | spiral -ic && spiral -c <key> |
You should see two identical check sums. If they match, the key was recorded correctly. If not, the key was not recorded correctly.
This example shows how you can encrypt multiple files to be distributed as a set. What we will do here is create a header file to go with a file we intend to send to someone else. This header file will contain miscellaneous information which does not need to be a part of the real file, but the decoding of the real file will be dependent on the presence of the header file. This can be used to quickly test that a password or key is correct, and also to decode accompanying notes, etc. without decoding the contents of a sensitive file. This also comes in handy when working with very large files, and ensures that the real file cannot be decoded without the correct signature file. This adds security on top of the encryption key used because, not only does the encryption key effect the encryption of the real file, but so do the length and content of the header file.
Method 1.
To start with, we will create a signature file using 'cat':
bash$ cat > message.sig //signed// Kevin P. Barry [Ctrl]+D |
Next, we will create a message, also using 'cat':
bash$ cat > message This is the content that is of importance that we don't want anyone to see... [Ctrl]+D |
We then encrypt the two files using the '-M' command line option. The order of the files is very important when using the merged data option; they must be decrypted in the same order they are encrypted. Incidentally, latter files depend on all former files for encoding/decoding.
bash$ spiral -epM message.sig message enter password 12345 confirm password 12345 |
Method 2.
Another (faster and more secure) way to create the two files we need is with a single call to spiral. This can be used when neither file exists already:
bash$ spiral -epiM message.sig message enter password 12345 confirm password 12345 //signed// Kevin P. Barry [Ctrl]+D This is the content that is of importance that we don't want anyone to see... [Ctrl]+D |
We now have a pair of encrypted files; 'message' is the sensitive information, and 'message.sig' is the informational signature which accompanies it. We can show the signature independently of the message, however we cannot show the message independently of the signature:
bash$ spiral -dppo message.sig enter password 12345 //signed// Kevin P. Barry |
bash$ spiral -dppo message enter password 12345 (garbled output) |
There are several ways you can decode the sensitive file. The first will just reverse the process we used before and will show the data on the screen. Because we are using the standard output option, the '-M' option is implied:
bash$ spiral -dppo message.sig message enter password 12345 //signed// Kevin P. Barry This is the content that is of importance that we don't want anyone to see... |
The second way is to split the process into parts using pipes and a background process. Because we are using redirection, using the '-M' option forces the context to carry over into the next loop:
bash$ mkfifo input output key bash$ spiral -dfLM -k key input output & bash$ echo -n "12345" > key bash$ cat message.sig > input bash$ cat output //signed// Kevin P. Barry bash$ cat message > input bash$ cat output > message.out |
The sensitive message is now stored in 'message.out':
bash$ cat message.out This is the content that is of importance that we don't want anyone to see... |
Since the context is carried over to the next loop, any additional data will be considered a part of the data we've already processed. To reset the context of the loop, send EOF to the input location:
bash$ echo -n > input |
Now that the context is reset, you can send 'message.sig' and 'message' through again. To stop the loop, you must send EOF to the input location a second time after resetting the context:
bash$ echo -n > input |
Here is a simple example of how to convert encrypted data to and from a legible form. We will create a short message to store in a file. To prepare the message for storage, we will format it into a neat block of text with comments. We will then convert it back to the original message.
(This example is executed from a bash shell.)
Here is our original message:
Here is a simple example statement so that I can demonstrate what you can expect from this program. Here is another made up sentence so that I have enough data to make it a little more obvious what is going to happen, and also so I can show you how to format a block of output text. |
To encrypt the message, call spiral using the '-l' option to enable legibility conversion and '-f' to read from one file and store in another:
bash$ spiral -elpf open-message secret-message enter password 12345 confirm password 12345 |
This gives us an encrypted file 1/3 larger than the original data (because of the conversion), but all in legible characters:
IN2W_xQiI0W6Dbdk44JIKyRblTOOznNWygNy4lGNnZEqEwUq.fsrXRTmCCSbAzzvR4JWrqd6E2hYwSng JG837hbD1DRvyvn5IDSe6eutCErWICuJJhdIFjc5US2efr34r_z4I7t4XWXne0NksfuVkPejWxpdSiNb oYs9VBDFLWrQYOV_uTTzN9osFa.TwncgfnUslIPLWj4zpl21tAN61CoJaf2eA4kO6tKyUWRFFOr6.FpJ rlgMAKhd8SeIW8h9YSs3jAPPZ7J2mXPLXZjDdLfWxDt9IsY06u_Booy6RCjyxX_t_.JZ7QVrBCTxilsk AOBAn75KtJkZuBe5c4pnA19jtb.1wwumWFgrkMH30_5pgHuiwIEvSbTZk1 |
We can now format the output data without having to worry about removing the formatting before the recipient decodes the message. Within the actual encoded data (the blue text), we can use any characters which are not a part of the data set (in this case, letters, numbers, periods, and underscores.) Since we are using the default character set, we also have the option of enclosing comments in "[]"; this allows us to use letters and/or numbers in our comments.
[ BEGIN *Secret Message* ] |IN2W_xQiI0W6Dbdk44JIKyRblTOOznNWygNy4lGN| |nZEqEwUq.fsrXRTmCCSbAzzvR4JWrqd6E2hYwSng| |JG837hbD1DRvyvn5IDSe6eutCErWICuJJhdIFjc5| |US2efr34r_z4I7t4XWXne0NksfuVkPejWxpdSiNb| |oYs9VBDFLWrQYOV_uTTzN9osFa.TwncgfnUslIPL| |Wj4zpl21tAN61CoJaf2eA4kO6tKyUWRFFOr6.FpJ| |rlgMAKhd8SeIW8h9YSs3jAPPZ7J2mXPLXZjDdLfW| |xDt9IsY06u_Booy6RCjyxX_t_.JZ7QVrBCTxilsk| |AOBAn75KtJkZuBe5c4pnA19jtb.1wwumWFgrkMH3| |0_5pgHuiwIEvSbTZk1----------------------| [ END *Secret Message* ] |
Decoding is just as easy as encoding was. Here, we use the 'secret-message' file we've just formatted and commented:
bash$ spiral -dlppo secret-message enter password 12345 Here is a simple example statement so that I can demonstrate what you can expect from this program. Here is another made up sentence so that I have enough data to make it a little more obvious what is going to happen, and also so I can show you how to format a block of output text. |
This example shows how you can assemble an encrypted file from various components without ever having to store the individual (or collective) components on the file system in their unencrypted form. To do this, we use a background process with the '-L' and '-M' options to merge loops. We then send the individual components to an input pipe, and spiral extracts, encrypts, and appends the new data to the output file.
(This example is executed from a bash shell.)
To start with, create a pipe for input:
bash$ mkfifo input |
Next, create a background process. Since the previous examples haven't shown the actual output of a background process, we use the '-v' (for verbose output) option with the '-c' and '-s' options and redirect program output to a summary file (make sure the 'key' pipe doesn't exist from a previous example):
bash$ spiral -ecsfLMv -r32 key input composite-data &> summary & |
All we have to do now is send our data to the input pipe and spiral will encrypt and assemble it for us:
bash$ echo "[Begin Composite File]" > input bash$ echo > input bash$ echo "Directory Contents:" > input bash$ ls -l > input bash$ echo > input bash$ echo "Current Time:" > input bash$ date > input bash$ echo > input bash$ echo "Fortune:" > input bash$ fortune > input bash$ echo > input bash$ echo "[End Composite File]" > input bash$ echo -n > input #reset context bash$ echo -n > input #terminate loop |
To display the contents of the composite file, decrypt it to standard output like you would any other file:
bash$ spiral -do -k key composite-data |
The 'summary' file contains the program output during the process.
This is a one-line example which will tell you the composite data statistics of every file in a directory. This isn't a particularly useful example, however it does provide interesting information. Just be careful that the directory doesn't contain pipes, otherwise the program will wait for input to each of them.
bash$ spiral -sMv * |