A basic perl script that encrypts a message with a given key using the playfair cipher. Instead of having a 2 dimensional array I use a hash and have a 2 way mapping of coordinate to character "0,0"->"a" and character to coordinate "a"->"0,0". This allowed me to easily use the same datastructure to lookup a character's position and find the character at a given coordinate.
#!path-to-perl use warnings; use strict; die "usage: playfair <'key'> <'message'>" unless(@ARGV == 2); my $key = lc($ARGV[0]); my $message = lc($ARGV[1]); my @alphabet = qw(a b c d e f g h i k l m n o p q r s t u v w x y z); my %square_hash = (); my $x; my $y; #replace all 'j's with 'i's $key =~ s/j/i/g; #build a key with unique letters (no repeats) while($key =~ s/(.)(.*)\1/$1$2/) {} print "Reduced key: $key\n"; #form the mapping my @keys = split(//,$key); $x = 0; $y = 0; for my $char (@keys) { $square_hash{$x . "," . $y} = $char; $square_hash{$char} = $x . "," . $y; $x++; if($x==5) { $x=0;$y++;} } #put in the rest of the letters for my $char (@alphabet) { next if exists($square_hash{$char}); $square_hash{$x . "," . $y} = $char; $square_hash{$char} = $x . "," . $y; $x++; if($x==5) { $x=0; $y++;} } print "5x5 playfair square:\n +-----------+\n"; for $y (0..4) { print " | "; for $x (0..4) { print $square_hash{$x . "," . $y} . " "; } print "|\n"; } print " +-----------+\n"; #change all j's to i's $message =~ s/j/i/gi; #remove spaces from the message $message =~ s/\s+//g; #insert an X in between identical letters $message =~ s/(.)(\1)/$1x$2/g; $message =~ s/(.)(\1)/$1x$2/g; #make it even length $message .= "x" if length($message)%2==1; print "Formatted message: $message\n"; #now encrypt everything my $encrypted = ""; while($message =~ s/^(.)(.)//) { my @xy1 = split(/,/,$square_hash{$1}); my @xy2 = split(/,/,$square_hash{$2}); #3 rules. 1: same row. if($xy1[0] == $xy2[0]) { #same col. move down 1 $xy1[1] = ($xy1[1]+1)%5; $xy2[1] = ($xy2[1]+1)%5; } elsif($xy1[1] == $xy2[1]) { #same row move right 1 $xy1[0] = ($xy1[0]+1)%5; $xy2[0] = ($xy2[0]+1)%5; } else { #same corners. chose element on other column same row. my $tempcol = $xy2[0]; $xy2[0] = $xy1[0]; $xy1[0] = $tempcol; } $encrypted .= $square_hash{join(",",@xy1)}; $encrypted .= $square_hash{join(",",@xy2)}; } $encrypted = uc($encrypted); print "Encrypted message E:\n$encrypted\n"; #OUTPUT # .\playfair "playfairexample" "hide the gold in the tree stump" # Reduced key: playfirexm # 5x5 playfair square: # +-----------+ # | p l a y f | # | i r e x m | # | b c d g h | # | k n o q s | # | t u v w z | # +-----------+ # Formatted message: hidethegoldinthetrexestump # Encrypted message E: # BMODZBXDNABEKUDMUIXMMOUVIF
The playfair cipher should not be used in a modern encryption scheme. It is solely a classic cipher. It is vulnerable to frequency analysis (digraph rather than monograph) yet is still quite secure if short messages are encrypted.
I hope to post a better-than-bruteforce decryption algorithm shortly.
I welcome any and all comments regarding ways I could improve my Perl scripting.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Playfair cipher
by ww (Archbishop) on Jun 22, 2011 at 21:30 UTC | |
by jwkrahn (Abbot) on Jun 23, 2011 at 00:06 UTC | |
by ww (Archbishop) on Jun 23, 2011 at 02:25 UTC | |
by zek152 (Pilgrim) on Jun 23, 2011 at 13:03 UTC |