A fiercer four-square cipher

Background

One-hundred and thirteen years ago, amateur cryptographer Félix Delastelle published his work on the four-square cipher, a digraphic substitution cipher that accepts two permutations of a 25-letter alphabet as keys and encodes messages consisting of those letters.

Like most pen-and-paper ciphers, the four-square cipher does not have any cryptographic value today, but at the time of its invention, it had a significant advantage over its monographic counterparts.

One-hundred and thirteen years later, Alice Delastelle decides to improve the four-square cipher by increasing the alphabet's size and the number of keys.[citation needed]

Key setup

The alphabet contains the following characters (starting with space):

 !"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ  Given a pass phrase, we construct a permutation of this alphabet as follows: 1. Keep only the first occurrence of each character. 2. Append the unused characters from the alphabet, in their natural order. After turning four pass phrases into four keys, we split each key into a square of side length 7 and arrange the four resulting squares so that they form one big square. For example, if the pass phrases were PROGRAMMING PUZZLES & CODE GOLF POPULARITY CONTESTS & CODE BOWLING CORRECT HORSE BATTERY STAPLE DON'T TELL EVE!!!  the keys would be constructed and arranged like this: PROGAMI POULARI N UZLES TY CNES &CDF!"# &DBWG!"$%'()*+  #$%'()* ,-./:;< +,-./:; =>?@BHJ <=>?@FH KQTVWXY JKMQVXZ CORET H DON'T E SBAYPL! LV!"#$%
"#$%&'( &()*+,- )*+,-./ ./:;<=> :;<=>?@ ?@ABCFG DFGIJKM HIJKMPQ NQUVWXZ RSUWXYZ  Encryption Given a plaintext message such as ALICE LOVES BOB.  we append 0 or 1 spaces to make its length even and split it into character pairs: ["AL" "IC" "E " "LO" "VE" "S " "BO" "B."]  For each character pair, we locate the the first character in the first square (reading order) and the second in the fourth. Then, we choose the characters in the remaining squares such that the four selected characters form a rectangle whose sides are parallel to the sides of the squares. Finally, we replace the character pair by the selected characters of the second and third square. For our example string, this yields ["PP" "A@" "E " "YT" "ZE" "EH" "=T" "<-"]  resulting in the following ciphertext: PPA@E YTZEEH=T<-  Task Write a program or function that accepts four pass phrases and a plaintext, uses the above variant of the four-square cipher to encrypt it and returns the resulting ciphertext. Details: • The five input strings will consist solely of characters of the mentioned alphabet. • The five input strings can be read in any order, as such, a single string delimited by newlines or as an array of five strings. • You may assume that none of the strings is empty. • The output must be a single string. If you choose to print the output to STDOUT, you may print only the characters of the ciphertext and (optionally) a trailing newline. • Standard rules apply. Test cases In all test cases, the first four strings correspond to the key squares in reading order and the last input string to the plaintext. Input PROGRAMMING PUZZLES & CODE GOLF POPULARITY CONTESTS & CODE BOWLING CORRECT HORSE BATTERY STAPLE DON'T TELL EVE!!! ALICE LOVES BOB.  Output PPA@E YTZEEH=T<-  Input  !"#$%&'()*+,-./:;<=>
!"#$%&'()*+,-./:;<=>?@ABCDE !"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKL
!"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRS HELLO, WORLD!  Output LALLR)#TROKE !  Input ,'K AB-Q=?@("W$>XM).C#<I:G!OLP*+;SZJTU%NED/&VFHRY
:,-D$C<SU=IYHFVA;! JG/M&L+WT%#.Q@(N*R")EZOBKX?'>P L()JX,BND?Z<>P*FU%=O@&KIC+A!Y:;$SWHR.EMG'/T"QV #-
<->CI")AP Q:+U;O/F(KH&ER!MW?X'VJLZ#.$,BSGN@TD%*Y= SPIN THE PPCG WHEEL OF BLAME!  Output #>TE,VK+,ZQ(&<[email protected]@DM%NAC&>  Input & %(,-#)$@?/=>'*"<:;!.+
=/$- ?;',@#!(&<")%.:>+* &%-/<?.;$'#:=!( ,>"+*)@
=,<-*?#.'@/;>%!+:(& ")$HNRA#JX$H %JAV+"GTS,


Output

GOOD LUCK, HAVE FUN.


Pyth, 74 71 bytes

L+%eb7*7/hb7Jcms+oxdN{d--CMr33 91MTd.z2ssm@VeJ,ydy_dCmxLhdedC,hJ.tcz2d


Could probably be optimized a lot. I use a lot of zipping.

Takes input in the following order:

ALICE LOVES BOB.
PROGRAMMING PUZZLES & CODE GOLF
DON'T TELL EVE!!!
POPULARITY CONTESTS & CODE BOWLING
CORRECT HORSE BATTERY STAPLE

• Can I steal your input order idea? Commented Aug 1, 2015 at 4:15
• @Maltysen Sure.
– orlp
Commented Aug 1, 2015 at 4:19

CJam, 5250494746 44 bytes

l2/qN/'[,32>A,s-f|2/f{~@S+2<.#_7f%_W%.m.m.=}


The input order is lines 5, 2, 3, 1, 4. Try it online.

(-1 byte thanks to @MartinBüttner, -2 bytes thanks to @Dennis)

Explanation

l2/           Read the message and split into chunks of 2
qN/           Read rest of input and split by newlines (pass phrases)
'[,32>        Generate " !"#\$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
A,s-          Remove digits 0123456789
f|            Setwise OR with each pass phrase to remove duplicates, giving keys
2/            Split keys into two pairs
f{ ... }      For each message chunk...
~             Unwrap key pairs
@S+2<         Add a space to the message chunk then cap to length 2
.#            Find the two chars in keys 1, 4
_7f%          Copy indices and perform modulo 7 on both
_W%           Copy and reverse
.m.m          Vectorised subtraction twice
.=            Apply both indices to keys 2, 3


For the indices, we want to swap the least significant digits, base 7. For instance, for the first example AL are indices 4 and 7 in keys 1 and 4 respectively. In base 7, this is [0 4] and [1 0]. Swapping the least significant digits gives [0 0] and [1 4], i.e. 0 and 11, and this corresponds to P and P in keys 2 and 3 respectively.

However, instead of base converting, the code does the following:

[4 7]     A: Initial indices
[4 0]     B: Indices mod 7
[0 4]     C: Reverse of B

[4 -4]    B-C
[0 11]    A-(B-C)


Pyth - 888683787675 72 bytes

8 bytes saved thanks to @orlp.

Waaay too long, I'm pretty unhappy with this, but just posting it while I look for a better way to handle the squares.

Jm+oxdN{d-+d-CMr33 91MTd.zsms@VtPJ,+*7hKs.DR7xV,hJeJdeK+*7@[email protected]

• You can replace c+e.z*%le.z2d2 with C.tce.z2d. Don't ask :)
– orlp
Commented Aug 1, 2015 at 0:00