#!/usr/bin/perl # # pontifex.cgi # # Implement the Solitaire algorithm as outlined in the book Cryptonomicon. # Original code is by Ian Goldberg # Bug fixes and CGI by Jauder Ho # # # 090899 jauderho [dgaudet mentioned error messages all over the place about] # [uninitialized values in the log. This is due to how the] # [substitution stuff works. $& will always be unintialized] # [for the first pattern. There is no nice workaround and the] # [reason why the -w flag is missing. Feel free to correct me.] # 020200 jauderho [moved to carumba.org. updated to use HTML::CarumbaOrg] # # We need the following because we are using our spiffy HTML::CarumbaOrg use lib '/home/www/docroot/carumba/carumba.org/perl/'; use HTML::CarumbaOrg; use CGI qw(:standard); # Comment out the first 2 "use" lines and uncomment the next 2 for local use # sub printCarumbaHeader { print header; print start_html; } # sub printCarumbaFooter { print end_html; } my $multFactor; my $deck; my $key; my $keyPhrase; my $count; my $text; my $value; my $intro; sub printHTML; sub genKeystream; sub getValue; # Introductory text $intro = " Pontifex is the name used for the Solitaire algorithm devised by Bruce Schneier of Counterpane Systems in Neal Stephenson's novel Cryptonomicon. They have a more elaborate description available. There was some errors with the original script presented. Here is the cleaned up version in CGI form and it should be trivial to revert to a command line version. There are some limitations: relatively short message length and only letters are encrypted."; # Encrypt/decrypt text if there is text available to do so. if (param) { # Set up the deck in sorted order. chr(33) == '!' represents A of # clubs, chr(34) == '"' represents 2 of clubs, and so on in order # until chr(84) == 'T' represents K of spades. chr(85) == 'U' is # joker A and chr(86) == 'V' is joker B. $deck = pack('C*',33..86); # Load the key phrase, and turn it all into uppercase. $keyPhrase = param('key'); $keyPhrase =~ y/a-z/A-Z/; # For each letter in the key phrase, run the key setup routine (which # is the same as the keystream routine, except that $k is set to the # value of each successive letter in the key phrase). $keyPhrase =~ s/[A-Z]/$key=ord($&)-64,genKeystream/eg; # Stop setting up the key and switch to encrypting/decrypting mode. # $key = 0; # The code in genKeystream requires that this be changed. undef $key; # Collect all of the alphabetic characters (in uppercase) from the # input files (or stdin if none specified) into the variable $text. $text = param('cryptotext'); $text =~ y/a-z/A-Z/; # Change all lowercase to uppercase $text =~ y/A-Z//dc; # Remove any non-letters # Set the multiplication factor to -1 if decrypting else set it to 1. # This factor will be multiplied by the output of the keystream # generator and added to the input (this has the effect of doing # addition for encryption, and subtraction for decryption). If we're # encrypting, append X to the input until it's a multiple of 5 chars. if (param('crypt') eq "Encrypt") { $multFactor = 1; $text .= "X" while (length($text)%5); } else { $multFactor = -1; } # This next line does the crypto: # For each character in the input ($&), which is between 'A' and 'Z', # find its ASCII value (ord($&)), which is in the range 65..90, # subtract 13 (ord($&)-13), to get the range 52..77, add (or subtract # if decrypting) the next keystream byte (the output of the function # genKeystream) and take the result mod 26 # ((ord($&)-13+$multFactor*genKeystream)%26), to get the range 0..25, # add 65 to get back the range 65..90, and determine the character with # that ASCII value (chr((ord($&)-13+$multFactor*genKeystream)%26+65)), # which is between 'A' and 'Z'. Replace the original character with # this new one. $text =~ s/./chr((ord($&)-13+$multFactor*genKeystream)%26+65)/eg; # If we're decrypting, remove trailing X's from the newly found # plaintext. $text =~ s/X*$// unless ($multFactor == 1); # Put a space after each group of 5 characters and print the result. $text =~ s/.{5}/$& /g; # Insert the output back into the field param(-name=>'cryptotext',-value=>$text); } printHTML; # Print the results # The End # Generate the display code. sub printHTML { printCarumbaHeader("pontifex"); print "
", $intro, "
",
"",
start_form,
" ",
"Key Phrase ",
"Text ",
submit('crypt','Encrypt'), " ",
submit('crypt','Decrypt'), " ",
reset,
end_form,
"
",
textfield(-name=>'key',
-size=>'40'),
"
",
textarea(-name=>'cryptotext',
-wrap=>'soft',
-rows=>'10',
-columns=>'40'),
"