http://qs321.pair.com?node_id=554404

A slightly less simple obfuscation for a slightly less simple substitution cipher. My next stop in old forgotten encryption ciphers is the Playfair cipher. This is a slightly more obfuscated encryption cipher than my last one - In case you haven't noticed, I'm increasing the obfuscation level as the encryption algorithm increases. This either takes a file as a parameter to encrypt in playfair, or provided no input encrypts its __DATA__.

Description borrowed from Wikipedia:

The Playfair cipher uses a 5 by 5 table containing a key word or phrase. Memorization of the keyword and 4 simple rules was all that was required to create the 5 by 5 table and use the cipher.

To generate the key table, one would first fill in the spaces in the table with the letters of the keyword (dropping any duplicate letters), then fill the remaining spaces with the rest of the letters of the alphabet in order (usually omitting "Q" to reduce the alphabet to fit, other versions put both "I" and "J" in the same space). The key can be written in the top rows of the table, from left to right, or in some other pattern, such as a spiral beginning in the upper-left-hand corner and ending in the center. The keyword together with the conventions for filling in the 5 by 5 table constitute the cipher key. To encrypt a message, one would break the message into groups of 2 letters ("HelloWorld" becomes "HE LL OW OR LD"), and map them out on the key table. We imagine simple rectangles between sets of letters. Then apply the following 4 rules, in order, to each pair of letters in the plaintext:

  • If both letters are the same (or only one letter is left), add an "X" after the first letter. Encrypt the new pair and continue. Some variants of Playfair use "Q" instead of "X", but any uncommon monograph will do.
  • If the letters appear on the same row of your table, replace them with the letters to their immediate right respectively (wrapping around to the left side of the row if a letter in the original pair was on the right side of the row).
  • If the letters appear on the same column of your table, replace them with the letters immediately below respectively (wrapping around to the top side of the column if a letter in the original pair was on the bottom side of the column).
  • If the letters are not on the same row or column, replace them with the letters on the same row respectively but at the other pair of corners of the rectangle defined by the original pair. The order is important - the first encrypted letter of the pair is the one that lies on the same row as the first plaintext letter.

To decrypt, use the inverse of these 4 rules (dropping any extra "X"s (or "Q"s) that don't make sense in the final message when you finish).

$_=q|P"\e[2J\n";SQw{my$s;select$s,$s,$s,H}SQc{P"\e[12;1f\n"}($_=pop)?o +pen+DAT A,$_:$@;$k=N"",MQuc,grep/[a-z]/,M$.{$_}++or$_,$0=~/\w/g;@s=($k=~/./g,g +rep/[^J $k]/,(A..Z));@Z=@s;F$r(0..4){$t[$r][$_]=H@sQFQ0..4}$t.=N"",grep/[A-Z]/ +,MQuc,/ ./gQF <DATA >;$_= $t;s/ + (\w)\ 1/$1X $1/g;(y ///c% 2)& &($_. ="X ");@e =/. ./g + ;$E=N "Q",@ e;$ D=1 3;$C= 1;F $o(1. .11){ M{P$o %2? ($_ + -1)%4 ?"\e[ $o; ${_ }f.": "\e [$o;$ {_} f". ($o== 1?" .": + ":"): ($_-1 )%4 ?"" :"\e[ $o; ${_}f :"} 1.. 21}F$ z(2 ..1 + 0){ne xtQif $z% 2;M {(P(" \e[ $z;${ _}f ".( H@Z)) &&( &c& + &w.03 ))if( ($z -1) %2)&& !(( $_+1) %4);}3..1 9}SQb {($I, + $x,$y )=@_; $r= 0;M{$ c=0 ;M{/$ y/& &U@ $I,$c .$r + ;/$x/ &&unH @$I ,$c.$ r;$ c++}@ $_; $r+ +}@t} SQf + {P"\e [12;1 f\e [0J\n "}S Qa{my ($x ,$y ,$t,$ f,@ + r)=H= ~/./g ;s/ J/I/F $x,$y;$w= 0;b\@ r,$ x,$ y;M{( $h, + $i)=/ ./g;$ p=++$ h>4?0 :$h;$ + t.=$t [$i][$p];if($iQeq$w){$j++}else{$w=$i;$j=0}}@r;$j?$t:0}SQe{my($x,$y,$t, +@r)=H=~ /./g;s/J/I/F$x,$y;b\@r,$x,$y;$s=$o=$f=0;M{($c,$d)=/./g;if($o++){$f++if +$s==$c} else{$s=$c}$d+=$d>3?-4:1;$t.=$t[$d][$c]}@r;$f?$t:0}SQn{my($x,$y,$t,@r, +$Y)=H=~ /./g;s/J/I/F$x,$y;b\@r,$x,$y;$_=N":",@r;s/(\d)(\d):(\d)(\d)/$2$3:$4$1/ +;M{($e, $f)=/./ g;$t.=$t[$e] [$f]}L/:/;$t}SQ k{($l1,$lt,@ R) +=H=~/./ g;b\@R, $l1,$lt;N":",@R}S Qj{N"-",k($_[0 ]),k$_[1]}SQ h{ m +y($t,$b ,$l,$r, $c)=@_;F$o($t..$ b ){M{P"\e[$o;$ {_}f$c"if(($ o%2 +)or!(($ _-1)%4) )}$l..$r}c}SQi{ my( $t,$b,$l,$r) =@_;F$o($t.. $b) +{F($l.. $r){P"\ e[$o;${_}f."if$ o%2 ;P"\e[$o;${_ }f".($o==1?" ." : +":")unl ess($_- 1)%4}}c}SQd{ my($x,$y,$h, $C)=@_;$l=($ x+ +1)*2;$c =($y+1) *4-1;$h?h$l-1,$ l+1 ,$c-2,$c+2,$ C:i$l-1,$l+1 ,$ c +-2,$c+2 }SQp{my ($p,$h,$c)=@_;M {d/ ./g,$h,$c}L/ :/,$p}SQg{my ($p +,$e)=@_ ;$j=j$p ,$e;($A,$B)=(L/ -/, $j);p$A,1,"* ";c;w.02;p$B ,1, +"@";c;w .01;$D= =13&&$C==1&&&f; P"\ e[$D;${C}f$p Q->Q$e\n";$C +=$ +D>19?$C <60?12:1-$C:0;$D+=$D<20?1:-7;p$A,0;p$B,0;c;w.01;}F(@e){if($T=a$_){g$_, +$T;U@c, $T}elsif($T=e$_){g$_,$T;U@c,$T}else{$P=$_;$T=n$_;g$P,$T;U@c,$T}}|;s.\s +..g;s:P :print:gx;s:U:push:g;s+N+join+g;s,M,map,g;s:S:sub:g;s'H'shift'g;s-L-sp +lit-g;; s;F;for;g;s,Q, ,g;s/([^f])or/$1||/g;eval;&f;print"encrypted:\n@c\n";ch +argrill __DATA__ The Playfair cipher is a manual symmetric encryption technique and was + the first literal digraph substitution cipher. The scheme was invented in +1854 by Charles Wheatstone, but bears the name of Lord Playfair who promoted t +he use of the cipher. The technique encrypts pairs of letters (digraphs), in +stead of single letters as in the simple substitution cipher and rather more co +mplex Vigenere cipher systems then in use. The Playfair is thus significantl +y harder to break since the frequency analysis used for simple substitution cip +hers does not work with it.


--chargrill
$,=42;for(34,0,-3,9,-11,11,-17,7,-5){$*.=pack'c'=>$,+=$_}for(reverse s +plit//=>$* ){$%++?$ %%2?push@C,$_,$":push@c,$_,$":(push@C,$_,$")&&push@c,$"}$C[$# +C]=$/;($#C >$#c)?($ c=\@C)&&($ C=\@c):($ c=\@c)&&($C=\@C);$%=$|;for(@$c){print$_^ +$$C[$%++]}

Replies are listed 'Best First'.
Re: Playfair cipher
by liverpole (Monsignor) on Jun 09, 2006 at 12:19 UTC
    Very elegant!  ++chargrill.

    The presentation is superb, as always.  But you have outdone yourself on the visual effect during program execution!  I admit that I've run the program numerous times now just to watch the dazzling output during the cipher-generation.  It's really a lot of fun!

    One of the subtle beauties of this obfuscation is that perl -MO=deparse doesn't really help much.  (<shameless plug> In constrast with this obfuscation, where -MO=Deparse is actually necessary for revealing the hidden message </shameless plug>).  It's also neat the way the deparse retains the positive-image/negative-image effect; the top half looks very much like a lighter shading of the bottom half.

    You clearly spent a lot of work on this gem, and it's paid off!


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Playfair cipher
by wulvrine (Friar) on Jun 09, 2006 at 14:41 UTC
    Wow great job ++!
    Of course you are not 'playing fair' either because -MO=Deparse didn't help me a bit (nice!).
    I was suprised at the output. I guess I was expecting to seeing encrypted data being massaged into unencrypted data even though it was stated that the output was encrypted. I think that was because of looking at too many obfu's and seeing encrypted data printing something you didn't expect. Perhaps this could be a next step?
    The screen updates during the encryption were cool. Definitely a marvel.

    Hell of a job!

    s&&VALKYRIE &&& print $_^q|!4 =+;' *|

      Thanks :)

      Unfortunately, as stated in the first paragraph, or perhaps in the __DATA__ section, this will be a tougher nut to crack than something like the vigenere cipher. Also unlike my obfuscated vigenere, I didn't wait to post this one until I had a Playfair cracker mostly ready to go... but I'm definitely planning on writing a playfair cracker, unless someone beats me to it ;)



      --chargrill
      $,=42;for(34,0,-3,9,-11,11,-17,7,-5){$*.=pack'c'=>$,+=$_}for(reverse s +plit//=>$* ){$%++?$ %%2?push@C,$_,$":push@c,$_,$":(push@C,$_,$")&&push@c,$"}$C[$# +C]=$/;($#C >$#c)?($ c=\@C)&&($ C=\@c):($ c=\@c)&&($C=\@C);$%=$|;for(@$c){print$_^ +$$C[$%++]}
Re: Playfair cipher
by wazoox (Prior) on Jun 09, 2006 at 14:02 UTC
    Wow! ++chargrill... Now what about a Playfair encrypted perl program that decrypt itself ? ;)