Cryptography has always been an interesting subject for me. Never really did much coding that involved it however. A little while back someone had asked for help writing a program that performs an Auto Key Cipher, so I figured I'd try my hand at making a proper cipher. I wrote two versions. One DLL, class based written in C# (with GUI). The other procedural based in Perl.
Here's the Perl code if you don't want to download it.
#!/usr/bin/perl -w
## This program is free software. It comes without any warranty, to
## the extent permitted by applicable law. You can redistribute it
## and/or modify it under the terms of the Do What The Fuck You Want
## To Public License, Version 2, as published by Sam Hocevar. See
## http://sam.zoy.org/wtfpl/COPYING for more details.
use strict;
use warnings;
use File::Basename;
my $inputString;
my $keyString;
my $type = 'e'; # Default is to encode.
my @flags; # For storing caps (1) and spaces (2).
if($#ARGV == 2) {
my $typeArg = shift @ARGV;
$inputString = shift @ARGV;
$keyString = shift @ARGV;
my $tString;
## Are we encoding or decoding?
if($typeArg eq '-e' || $typeArg eq '--encode') {
$tString = 'Encode';
$type = 'e';
} elsif( $typeArg eq '-d' || $typeArg eq '--decode' ) {
$tString = 'Decode';
$type = 'd';
## Default to encode.
} else {
print "[ERROR] Unknown switch '$typeArg'; Using '-e'.\n";
$tString = 'Encode';
}
print "==$tString==\nInput string: $inputString\nKey string: $keyString\n";
## Encode/Decode excluded in command line.
} elsif( $#ARGV == 1 ) {
$inputString = shift @ARGV;
$keyString = shift @ARGV;
print "[Encode] Input string: $inputString\nKey string: $keyString\n";
## Wrong number of arguments. Can only have 0, 2, or 3.
} elsif( $#ARGV == 0 || $#ARGV > 2) {
print "Usage: ".basename($0)." [-e|--encode|-d|--decode] [<input string> <key string>]\n";
exit;
}
## Input and Key strings not given in command line; Ask for them.
if( !$inputString || !$keyString ) {
print "Input string: ";
$inputString = <STDIN>;
chomp $inputString;
print "Key string: ";
$keyString = <STDIN>; # 'n' is rot13
chomp $keyString;
}
# Array of the alphabet. Everything revolves around this being correct.
my @letters = qw(a b c d e f g h i j k l m n o p q r s t u v w x y z);
# Make the key lowercase
$keyString = lc($keyString);
# Initilaze arrays to store offsets
my @inputOffsets;
my @keyOffsets;
my $x; # Current index
# Find the offsets for each letter in the key string
print "Key offsets: ";
foreach my $keyLetter (split(//, $keyString)) {
## Found something other than a letter.
if( $keyLetter !~ /[a-z]/i ) {
print "\n[FATAL ERROR] Key can only contain letters!";
exit 2;
}
## Find the current letter in the alphabet array
for($x = 0; $x <= $#letters; $x++) {
if( $keyLetter eq $letters[$x] ) {
# Store the offset we found
push(@keyOffsets, $x);
print "$x ";
}
}
}
# Find the offsets for each letter in the input string
print "\nInput offsets: ";
foreach my $inputLetter (split(//, $inputString)) {
## Found something other than a letter or a space.
if( $inputLetter !~ /[a-z ]/i ) {
print "\n[FATAL ERROR] Input can only contain letters and spaces!";
exit 3;
## Found a space.
} elsif( $inputLetter eq ' ' ) {
push(@flags, 2);
push(@inputOffsets, -1);
next;
}
# Find the current letter in the alphabet array
for($x = 0; $x <= $#letters; $x++) {
if( lc($inputLetter) eq $letters[$x] ) {
# Store the offset we found
push(@inputOffsets, $x);
## Found a capital letter.
if($inputLetter ne lc($inputLetter)) { push(@flags, 1); }
## Lowercase letter.
else { push(@flags, 0); }
print "$x ";
}
}
}
# Make the key string as long as the input string
my $z; # Current letter in the input string
my $y = 0; # Current letter in the key string
# Iterate once for each letter in the input string past the length of the key string
for( $z = $#keyOffsets; $z <= $#inputOffsets; $z++ ) {
# Add new letter to the end
push(@keyOffsets, $keyOffsets[$y]);
# Increment index
$y++;
# Reset index when it goes out of bounds
if($y > $#keyOffsets) {
$y = 0;
}
}
my $result; # Encoded/Decoded string.
print "\nFlags: ". join(' ', @flags);
print "\nEffective offsets: ";
# Output loop
my $i;
for( $i = 0; $i < length($inputString); $i++) {
## Found a space so skip the math.
if($flags[$i] == 2) {
$result .= ' ';
next;
}
my $newIdx; # Encoded/Decoded letter's offset.
if( $type eq 'e' ) {
## Add the two offsets to encode.
$newIdx = $inputOffsets[$i] + $keyOffsets[$i];
} else {
## Subtract the two offsets to decode.
$newIdx = $inputOffsets[$i] - $keyOffsets[$i];
}
## Loop around to 'a' if we went past 'z' (encoding)
if( $newIdx > 25 ) {
$newIdx -= 26;
## Loop around to 'z' if we went past 'a' (decoding)
} elsif( $newIdx < 0 ) {
$newIdx += 26;
}
print "$newIdx ";
# Print the new letter
if($flags[$i] == 1) {
## Preserve capitals.
$result .= uc($letters[$newIdx]);
} else {
$result .= $letters[$newIdx];
}
}
## Print the results
print "\n\"$inputString\" + \"$keyString\" = \"$result\"";