#!/usr/local/bin/perl5 # -*- perl -*- # # CMSC443 Project 2 # Michael A. Gurski # Simple rotor project # # make sure filename is supplied die "Usage: rotor \n" if ($#ARGV < 0); # set up the rotors & their wiring...make sure 2 wires don't end at same # spot @Rotor1 = ( Q, W, E, R, T, Y, U, I, O, P, A, S, D, F, G, H, J, K, L, Z, X, C, V, B, N, M); @Rotor1N = ( 3, 1, 9,24, 0,19, 2,24,18, 5,23,21, 8, 22,24, 2,25, 5,21,17,25,21,25, 2,20,24); @Rotor2 = ( Z, A, Q, X, S, W, C, D, E, V, F, R, B, G, T, N, H, Y, M, J, U, K, I, L, O, P); @Rotor2N = (21, 8,22,24, 2,25, 5,21,17,25,21,25, 2, 20,24, 3, 1, 9,24, 0,19, 2,24,18, 5,23); # optional plugboard... #@Plugboard = (18, 1,25,12, 3, 5, 9,11,24,17,22,20, 2, # 7,15, 6,16, 8,19,13,21, 4, 0,23,14,10); # reflector to make this self-inverting @Reflector = ( 3, 2, 1, 0, 7, 6, 5, 4,11,10, 9, 8,15, 14,13,12,19,18,17,16,23,22,21,20,25,24); # get the key from the user print STDERR "Enter key:\n"; $key = ; # eat EOL chomp $key; # convert to upper case $key =~ tr/a-z_/A-Z+/; # ensure key is 2 characters die "key must be of length 2!\n" if (length($key) != 2); # ensure key is alphabetic die "key must be alphabetic characters!\n" if (($key =~ /\W+/) || ($key =~ /\d+/)); # split key into 2 characters ($i1,$i2) = $key =~ /(\w)(\w)/; # set up initial offsets $off1 = 0; $off2 = 0; # "rotate" rotor 1 to initial position while($Rotor1[0] ne "$i1") { $tmp = shift(@Rotor1); push(@Rotor1,$tmp); $tmp = shift(@Rotor1N); push(@Rotor1N,$tmp); } # "rotate" rotor 2 to initial position while($Rotor2[0] ne "$i2") { $tmp = shift(@Rotor2); push(@Rotor2,$tmp); $tmp = shift(@Rotor2N); push(@Rotor2N,$tmp); } # open the input file open(FILE,"$ARGV[0]"); # read line by line while ($FILE = ) { # ignore end of line... chomp $FILE; # convert line to uppercase $FILE =~ tr/a-z/A-Z/; # split line into array of individual characters @FILE = split("",$FILE); # loop through array of plaintext characters while(@FILE) { # remove first character in array $Char = shift(@FILE); # encrypt it only if it's alphabetic if (($Char =~ /\w/) && ($Char =~ /\D/) && ("$Char" ne "_")) { # index into first rotor $R1ind = ord($Char) - ord("A"); # index into second rotor based on wiring of 1st $R2ind = ($R1ind + $Rotor1N[$R1ind]) % 26; # index into reflector based on wiring of 2nd rotor $RefInd = ($R2ind + $Rotor2N[$R2ind]) % 26; # the hard part...finding the reverse entries... # find the left side of rotor 2 that's connected to the # reflector's current index for($i=0;$i<26;$i++) { if(($i+$Rotor2N[$i])%26 == $Reflector[$RefInd]) { $R2ind = $i; last; } } # find the left side of rotor 1 that's connected to # rotor 2's current index for($i=0;$i<26;$i++) { if(($i+$Rotor1N[$i])%26 == $R2ind) { $R1ind = $i; last; } } # convert index to encrypted character $Char = pack("C",$R1ind+ord("A")); } # output ciphertext or non-alpha text print "$Char"; # rotate rotor 1 by 1 $off1 = ($off1 + 1) % 26; $tmp = shift(@Rotor1); push(@Rotor1,$tmp); $tmp = shift(@Rotor1N); push(@Rotor1N,$tmp); # rotate rotor 2 by 1 if rotor 1 has made a full rev if(($off1 + $origOff1) % 26 == 0) { $tmp = shift(@Rotor2); push(@Rotor2,$tmp); $tmp = shift(@Rotor2N); push(@Rotor2N,$tmp); } } # print end of line print "\n"; } # EOF