7
$\begingroup$
  • TJPGRROLZZNFSXMGLGDVMR
  • MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
  • UAPRZGSIJGAZALKZX
  • HRLPVDUQ
  • FAYHTFSIALGEDGCLWV
  • WLCCIWJ
  • AAGOTSHGDPCPNHKZJMJZMAMBPPMRWNDKO

There's a space between each segment.

$\endgroup$
6
  • $\begingroup$ Does each bullet point contain one "segment"? Which would mean that there is a space between each bullet point? $\endgroup$
    – JLee
    Commented Aug 6, 2022 at 19:27
  • $\begingroup$ @JLee " ".join(string.split("\n* ")) $\endgroup$
    – Someone
    Commented Aug 7, 2022 at 3:24
  • $\begingroup$ I see isomorphism in .......WLCCIWJ, OAKGNLVNGKKRND, and LXQNIWYINQQFIV, plus LWVWL and ZJMJZ, and the resulting chains suggest OGZNFFL and TJPGRRO are also the same letters, but those aren't enough to chain out a complete equivalent alphabet. $\endgroup$ Commented Mar 14, 2023 at 1:51
  • $\begingroup$ @codewarrior0 sorry, I have absolutely no idea how I came up with this. You could be right, but I don't remember. $\endgroup$
    – Someone
    Commented Mar 14, 2023 at 1:53
  • 1
    $\begingroup$ Finding isomorphism at all tells me that the cipher here is in one of three broad categories. Alphabet progressions (like increasing the Caesar shift by 1 after each letter); ciphertext-autokey (using the previous letter of the ciphertext as the key for the next one); or monoalphabetic groups (each word is enciphered separately with a simple substitution). $\endgroup$ Commented Mar 14, 2023 at 1:55

2 Answers 2

12
$\begingroup$

Plaintext:

WHAT_DOES_THIS_MEAN_QUESTION_MARK THIS_MESSAGE_IS_ENCRYPTED_FULL_STOP_CAN_YOU_CRACK_THE_ALGORITHM_QUESTION_MARK_WOW_YOU_GOT_IT_INTERROBANG_HOW_DOES_IT_WORK_QUESTION_MARK_POST_YOUR_ANSWER_IN_THE_SAME_CODE

SO_NUTGJIVLG_CLGTMZLQMCNYWJSQPEOXFTMOKAFXYUH__RNXEQBYB_YKYR_NPLD

I'm not going to spoiler the solve path. It makes use of some old codebreaking techniques, and knowing what they are and how to apply them doesn't really spoil the puzzle. Just, uh, don't scroll down if it starts to sound like a spoiler.

Early on I noticed the isomorphs .......WLCCIWJ, OAKGNLVNGKKRND, and LXQNIWYINQQFIV due to a prior fascination with the phenomenon. This is a kind of pattern seen in very few classical ciphers. If I write the texts one above the other...

.......WLCCIWJ
OAKGNLVNGKKRND
LXQNIWYINQQFIV

We can see that every W in the first text corresponds to an N in the second text; and every N in the second text corresponds to an I in the third text. A similar pattern is seen with G->N and K->Q in the second and third texts. Another way of seeing this is to suppose there is a simple substitution which can be applied to the second text to transform it into the third text. What makes it significant is the number of repeated letters in each text, the repeated Ws and Ns and Ks and Gs and Qs. If it were two spans of 14 unique letters in a row, it wouldn't be as interesting.

Finding this pattern is useful for several reasons. First, it identifies the method used as one of just a few types of cipher. Second, it indicates that the texts encipher repetitions in the plaintext. Third, it suggests that a solution method called alphabet chaining can be applied. In fact, this method can be applied even without knowing anything more about the cipher method...

.......WLCCIWJ     WN LG CK IR JD
OAKGNLVNGKKRND

.......WLCCIWJ     WIF LN CQ JV
LXQNIWYINQQFIV

OAKGNLVNGKKRND     OLW AX KQ GNI DVY RF 
LXQNIWYINQQFIV


 OLW
 GNI
  RF

...but it doesn't get very far at the moment, so I have to play with the cipher some more. The ciphertext is enigmatically given as a bullet-pointed list, and a comment suggests to replace the bullet points with spaces. This raises a question: Are the spaces significant to the cipher, or not? A standard diagnostic for classical ciphers is to compute the Periodic Index of Coincidence (or Kappa IC). This test aims to find evidence of a periodic cipher by comparing the ciphertext to itself over a range of intervals, and counting the number of times any letter repeats at that interval. For example:

                             !                     
MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
  MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
Interval: 2   Repeats: 1

                      !                       
MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
   MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
Interval: 3   Repeats: 1

                         !               !
MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
    MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLVNGKKRNDVMUQ
Interval: 4   Repeats: 2

Using a short python program together with Matplotlib, I can repeat this test for every interval up to 80 and plot the results. The number of repeats found is divided by the number of repeats expected for random text, which gives a result (the "index") close to 1.0 if the result is "like random" and a result above 1.6 if it resembles language. Similar functions are available in the deciphering programs CryptoCrack and CrypTool.

If spaces are significant, the plot looks like this: enter image description here

Without spaces: enter image description here

The text is short enough that most of these peaks are probably spurious. The "with spaces" plot is still more compelling. It has periodic spikes at 8 and 16, suggesting a factor of 8; it also has a big spike at 27, a slightly interesting number, being one more than the number of letters in the alphabet.

Treating spaces as significant, I went back and did a more thorough search for isomorphs using Callimahos' method. For each letter in the ciphertext, I looked back ten places and found whether that letter had already appeared, and wrote the distance to that letter above it.

                          !!!!!! 
000000000040400100030490003571050
WJDIRKGPZOG_ZNFFLQHLXQNIWYINQQFIV

0000010001000000920060030080000080000800000053004400200009086000400008
TJPGRROLZZNFSXMGLGDVMR_MPNDUZXEHPGJIRXOSLVCHSCEGSCQDQMAZJSIDAVUOAKGNLV
!!!!!!!!                                                  !!!!!!!!
3571050800003000000004972004000070000090000050070000306000357105080100
NGKKRNDVMUQ_UAPRZGSIJGAZALKZX_HRLPVDUQ_FAYHTFSIALGEDGCLWV_WLCCIWJ_AAGO

00050002070000243020014000000
TSHGDPCPNHKZJMJZMAMBPPMRWNDKO

Jackpot. With significant spaces, the isomorphs I found earlier can be extended in both directions. I'll try alphabet chaining again:

CLWV_WLCCIWJ_
KGNLVNGKKRNDV
QNIWYINQQFIV

CLWV_WLCCIWJ_   CQ LN JVWIF _Y
QNIWYINQQFIV

CLWV_WLCCIWJ_   CK _VLG WN IR JD
KGNLVNGKKRNDV

KGNLVNGKKRNDV   KQ GNI LW VY RF DV
QNIWYINQQFIV

    _Y
   JVWIF     CQ
   DLNR      K
    G

Better, but not a complete alphabet yet. Since I'm putting a space into the alphabet, that spike at 27 on the periodic IC chart becomes very interesting. The general method of alphabet chaining does not assume anything about the exact intervals along the alphabet, and only works with proportions.

One of the types of cipher indicated by isomorphs is an alphabet progression - a cipher based on the Caesar cipher where the shift amount increases by one after each letter enciphered. This kind of cipher can be done with a non-standard alphabet. A progression along a 27-letter alphabet would predict that spike at 27. If I assume this kind of cipher is used, then I can use an exact interval in alphabet chaining: the interval along a set of chains will be equal to the distance between the two isomorphs that produced those chains. So, I find the positions of the isomorphs in the text and compute the intervals.

While computing the intervals, I had a hunch that the title of the puzzle and the text in the body were each enciphered separately using the same cipher, so I confirmed that using the Kappa IC test:

 !  !   !       !         
WJDIRKGPZOG_ZNFFLQHLXQNIWYINQQFIV
TJPGRROLZZNFSXMGLGDVMR_MPNDUZXEHP
Hits: 4   Expected:  ~1.2

Confident that they were two separate texts enciphered identically, I counted the position of the isomorph in the title from the beginning of the title, and the positions of the two other isomorphs from the beginning of the text in the body. (Modulo 27, of course.)

With the intervals known, I can space out the resulting chains and try to fit them together into a complete 27-letter alphabet.

(15) CLWV_WLCCIWJ_
(11) KGNLVNGKKRNDV
(21) QNIWYINQQFIV

(15) CLWV_WLCCIWJ_   CQ LN JVWIF _Y    (+6)
(21) QNIWYINQQFIV

(11) KGNLVNGKKRNDV   KC GLV_ NW RI DJ    (+4)
(15) CLWV_WLCCIWJ_

(11) KGNLVNGKKRNDV   KQ GNI LW VY RF DV  (+10)
(21) QNIWYINQQFIV


    G       K
   DLNR     CQ
   JVWIF    
    _Y

J->V = 6
L->V = 4

012345678901234567890123456
  J.....V.....W.....I.....F
....L.....N.....R........D.

..J.L...V.N...W.R...I....DF
G...L...V 
          N...W...Y

G.J.L...V.N...W.R.Y.I....DF

At this point I recognized the .W.R.Y.I as alternating letters from QWERTYUI, assumed an alphabet progression along the keyboard alphabet (+ space) QWERTYUIOPASDFGHJKLZXCVBNM_, deciphered the text, and experienced deja vu.

...

My best guess about the intended solve path (if it had one!) is this:

  1. Assume the title begins with WHAT:
WHAT
WJDI
  1. Recognize the sequences HJ, AD, and TI as being increasing intervals along a keyboard alphabet.

  2. Assume an alphabet progression along a keyboard alphabet.

  3. When that fails, assume an alphabet progression along a keyboard alphabet plus a space.

$\endgroup$
1
  • $\begingroup$ Yes, this is correct! $\endgroup$
    – Someone
    Commented Apr 30, 2023 at 15:27
3
$\begingroup$

Based on codewarrior0's answer, I wrote a decoder program in Python. It looks like I used 0 as the key, but this tries all 27 possible keys.

def decode(string):
    alphabet = "QWERTYUIOPASDFGHJKLZXCVBNM_"

    string = string.upper().replace(" ", "_")
    for char in string:
        if not char in alphabet:
            raise ValueError("invalid character: " + char)

    decodes = [""] * len(alphabet)

    for char_index, char in enumerate(string):
        for key in range(len(alphabet)):
            decodes[key] += alphabet[
                (alphabet.index(char) - (key + char_index)) % len(alphabet)
            ]

    return decodes


if __name__ == "__main__":
    import sys

    decodes = decode("_".join(sys.argv[1:]))

    for key, decoded in enumerate(decodes):
        print((" " if key < 10 else "") + str(key), decoded)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.