**Twin Bifid**

A couple weeks ago, I wrote about solving a 5×5 Bifid, and that I’d been unable to successfully use a bruteforce wordlist attack against the key alphabet, or a hillclimber, to crack that or a Twin Bifid. I ended the blog entry at that point. However, I’d gotten up to 88 solutions, with 22 of the 26 Cipher Exchange puzzles. That left me with 3 more crypts that I felt I had a chance to solve, and a shot at 91 out of 102 puzzles total. Percentage-wise, that would be another personal best, and I still had over 3 months before the October deadline for submitting the solutions for credit. Ok, yeah, let’s do Twin Bifid next.

See the write-up for details on solving the normal 5×5 and 6×6 Bifids. The main point is that with a manual solving approach, you’re given a crib that you have to place. After this, you build up the “equations” the crib gives you, and use that to fill in the Polybius square. Use the square to print out as much of the plaintext as you can, and alternate between solving the square and solving for the plaintext.

With Twin Bifid, you have two messages that use the same Polybius square, but have different periods. At least part of the two messages are identical. This way, although you don’t get a crib directly, the equations you build up through equivalence will contribute to filling in the square, and now you have two different messages that give you additional hints to plaintext words you can complete.

Say we have the following two messages, and we’re told that the first 25 letters are the same. Additionally, the letters are grouped to match the periods used (periods 5 and 7).

FSHPU PGTHT BBDEO RIEEY RORPL RRNPP XAMBE TQRBO QNTBO HQBTO QGPBD AIAMO CRRNB IBEMQ TNNBB ZQA

FSHOPUO GMMOTQP LRQELUL BLREOEP IXGHMBD QIIPFAF ODOOIYI OAGCPVM DQLVPMP MEDEUMF NFLNHYD TIOEFPH QFQVEDN SN

For illustration purposes, I’m going to use a new convention. Normally, we’d have the Polybius square, and we’d use the row and column numbers to identify both of the crypt pair values (i.e. – “A” = 11 becomes A0 = 1 and A1 = 1, or Ar (row) = 1 and Ac (column) = 1). That doubles the length of the example text, so I’m going to use Aa, where **A = A0 or Ar**, and **a = A1 or Ac**. With this convention, write out the intermediary step for decryption in two rows of period length, as row/column identifier pairs.

FfSsH PpGgT BbBbD RrIiE RrOoR - Msg 1 rows

hPpUu tHhTt dEeOo eEeYy rPpLl - Msg 1 columns

FfSsHhO GgMmMmO LlRrQqE BbLlRrE - Msg 2 rows

oPpUuOo oTtQqPp eLlUuLl eOoEePp - Msg 2 columns

Remove the spaces, trim the second message to be 25 letters long, and align the Msg 2 rows and columns under the Msg 1 rows and columns.

FfSsHPpGgTBbBbDRrIiERrOoR - Msg 1 rows

FfSsHhOGgMmMmOLlRrQqEBbLl - Msg 2 rows

hPpUutHhTtdEeOoeEeYyrPpLl - Msg 1 columns

oPpUuOooTtQqPpeLlUuLleOoE - Msg 2 columns

We know that the plaintext here is the same for both messages, so the letters that encipher the row values for both messages map to the same plaintext letter row. The same holds for the column letters. This lets us build up a set of equivalency equations. In places where the two letters are the same (i.e. F=F and s=s) ignore and skip.

P=h=e=L=o=H

p=O=b

etc.

Notice that on the first line, we have h=H. This means that “H” is on the diagonal in the Polybius square. Using my solver assist tool, the full set of equations is:

1: ['P0', 'H1', 'O1', 'H0', 'E1', 'L0', 'U0', 'Y1', 'D0']

2: ['P1', 'O0', 'B1', 'T1', 'T0', 'M0']

3: ['B0', 'M1', 'R1', 'L1', 'E0', 'R0', 'I0', 'Q1']

4: ['I1', 'Q0', 'D1']

5: ['Y0', 'U1']

I prepended the line numbers for two reasons. First, this lets me refer to the equations by line number more easily. Second, I can now build up the Polybius square with these purely arbitrary values, and immediately get some of the plaintext out of the cipher texts. I also switched back to “A0” and “A1” because I find this notation a little easier to read here.

. 12345

. -----

1|HPLDU

2|OTM..

3|EBRI.

4|..Q..

5|Y....

`FfSsHPpGgTBbBbDRrIiERrOoRRrRrNXxAaMTtQqRQqNnTHhQqBQqGgPAaIiACcRrRIiBbETtNnNZzQ`

hPpUutHhTtdEeOoeEeYyrPpLlnPpPpmBbEerBbOotBbOobTtOopBbDdaMmOorNnBbeMmQqnBbBbqAa

....UPO..TIMETHERE.ERETHR.EBE.....OMM.BE.R..OPP.BE.R..D..R.....RBE.R.R.M......

FFSSHHOGGMMMMOLLRRQQEBBLLRREIIXXGGHQQIIIIPOODDOOOOOAAGGCDDQQLLVMMEEDDENNFFLLNTTIIOOEQQFFQQVSS

OPPUUOOOTTQQPPELLUULLEOOEEPPHMMBBDDPFFAAFFOIIYYIICPPVVMMVPPMMPPEUUMMFFNHHYYDDEFFPPHHVEEDDNNNN

....UPO..TIMETHERE.ERETHREEBE.....D.......OLD.OL..H........BLE.OE.PL......HE.O...THE.R.......

I’m only going to use my uppercase/lowercase convention in the first message, because I’m hand-editing this specifically for the blog, and it’s getting to be too much work to do this for both messages. Just pretend that the second letter of each pair is lowercase, and therefore refers to the column number for that letter. That is, “O” = 21, so “O” row = O0 = **O = 2**; “O” column = **o = 1** (or, **Oo = 21**).

It should be obvious that both messages start with “once upon a time there were…”

FfSsHPpGgTBbBbDRrIiERr

hPpUutHhTtdEeOoeEeYyrP

ONCEUPONATIMETHEREWERE

This gives us:

O=Fh = F row + h col

N=fP = F col + P row

C=Sp = S row + p col

E=sU = s col + U row

. 12345

. -----

1|HPLDU

2|OTM..

3|EBRI.

4|..Q..

5|Y....

Looking at “O = Fh = F row + h col”, we have O and H already, but we’re missing F from the table. O row = 2, so F row has to be 2 as well, but we don’t know which column F is in, 4 or 5. In the next equation, “N = fP”, we only have “P”. We’re missing “S” and “C” from equation 3, but with equation 4, “E=sU”, we have “E” and “U”. “E” = 31, so “S” is in column 3. There’s only one opening there, giving S=53. Going back to equation 3, C=52.

. 12345

. -----

1|HPLDU

2|OTM.. + F

3|EBRI.

4|..Q..

5|YCS..

Attacking the square, if we look at column 3, we have “LMRQS”, which can be put into ascending order as “LMQRS”. Let’s change the current number assignments of 12345 to 12435. This doesn’t change the plaintext out for the crypts.

. 12345

. -----

1|HPDLU

2|OT.M. + F

3|...Q.

4|EBIR.

5|YC.S.

Looking in columns, we have “BC” at the bottom of column 2, and “D..I” in column 3. Assuming that the key is “HO.EYPT”, and that “A” is not in the key, then “ABCDFGIKLMQRSUVWXZ” comes out when we fill in the blanks with the obvious choices. Notice also that in column 4, there’s no gap between “M” and “Q”, meaning that “N” has to be in the key.

. 12345

. -----

1|HPDLU

2|OTFMV

3|NAGQW

4|EBIRX

5|YCKSZ

The keyword is “HONEYPOT”, the route is “on by columns”, and the messages are:

ONCEUPONATIMETHEREWERETHREEBEARSAMOMMABEARAPOPPABEARANDATRANSFERBEARFROMALASKA

ONCEUPONATIMETHEREWERETHREEBEARSANDABIGBADOLDWOLFTHATWASUNABLETOEXPLAINHOWHEGOTINTHEWRONGIOKE (IOKE = JOKE)

It took me several hours to figure out how to approach the solver in Python. What I finally settled on was a pair of lists, incorporating the message periods, alternating with letter+0, letter+1.

msg1 = [['F0', 'F1', 'S0', 'S1', 'H0', 'P0', 'P1', 'G0', 'G1', 'T0'],

['H1', 'P0', 'P1', 'U0', 'U1', 'T1', 'H0', 'H1', 'T0', 'T1']]

This represents the first 10 letters of message 1, with the row assignments in the first element, and the column assignments in the second element.

msg2 = [['F0', 'F1', 'S0', 'S1', 'H0', 'H1', 'O0', 'G0', 'G1', 'M0', 'M1', 'M0', 'M1', 'O0'],

['O1', 'P0', 'P1', 'U0', 'U1', 'O0', 'O1', 'O1', 'T0', 'T1', 'Q0', 'Q0', 'P0', 'P1']]

The row and column equations then come from equating msg1[0] with msg2[0], and msg1[1] with msg2[1].

['F0', 'F1', 'S0', 'S1', 'H0', 'P0', 'P1', 'G0', 'G1', 'T0']

['F0', 'F1', 'S0', 'S1', 'H0', 'H1', 'O0', 'G0', 'G1', 'M0']

['H1', 'P0', 'P1', 'U0', 'U1', 'T1', 'H0', 'H1', 'T0', 'T1']

['O1', 'P0', 'P1', 'U0', 'U1', 'O0', 'O1', 'O1', 'T0', 'T1']

The equations start out kind of disconnected, in that the program needs more than one pass through the assignments for each of the letter components.

P0, H1

P1, O0, T1

T0, M0

H1, O1, H0

To fix this, I run through the equations again, and if any two elements contain a shared letter component (i.e. – lines 1 and 4 both have “H1”), combine them.

P0, H1, O1, H0

P1, O0, T1

T0, M0

The reason for using the row = 0, column = 1 notation here, rather than the uppercase, lowercase convention described above, is that it’s easier to expand the tool to handle a 6×6 square (A1B2C3D4E5F6G7H8I9J0KLMNOPQRSTUVWXYZ) this way (because there’s no “lowercase” for a “1”).

I then number the equations 1 through n as described above, where “n” is the total number of lines I end up with. Depending on the crypt and the length of shared letters in the plaintext, “n” can be anywhere from 3 to 10. I use this numbering for 1-5 to create the tentative Polybius square, and go into a solving loop on the crypt text.

The tool command line commands are:

E/Q/X : Print out the solution in ACA format and quit.

H/? : Print the Help.

Key=text : Accept a keyword for printout in ACA format.

Table=nnnn : Assign new row and column numbering.

ch=nn : Assign a letter by row and column.

Examples:

Key = Honeypot

Table=12435

n=31

The solver assist tool took maybe 6-7 hours to type up, debug and test. (In comparison, this blog entry took 3 hours.) The crypt was comparatively easy, but when I first started working on it, the plaintexts out from the equations were so spotty that I’d thought my program was corrupting something somewhere. But, I was able to slowly work my way through it, and it fell within 20 minutes, and that included having to hand-solve the route the keyed alphabet was written into the square. In the end though, I had both messages, the keyword, and the Route Transposition route for the square.

This gives me solve #89, leaving what should be a simple NULL (I hate NULLs), and a modification on the Grille cipher. With 12 more weeks to the deadline. I’m not optimistic…