2

Disclaimer: this is actually a coding challenge therefore I am expressly not looking for complete solutions.

The way the cipher works is as follows:

Start with ABCDEFGHIJKLMNOPQRSTUVWXYZ and a keyword KEYWORD. We construct our first alphabet by shuffling the above around each letter of the keyword in turn. I.e.:

First letter K, alphabet becomes LMNOPQRSTUVWXYZKABCDEFGHIJ

Second letter E, alphabet becomes FGHIJELMNOPQRSTUVWXYZKABCD

etc. etc. until we get the initial cipher alphabet: YFGHIJELMNRPQDSTUVOXWZKABC

In order to encrypt we then use this alphabet and for each letter in the plain text perform the same shuffling operation as in the inception stage around the plaintext letter (so if the first letter of the plaintext is F you would get J as the first ciphertext letter and your new alphabet would be GHIJELMNRPQDSTUVOXWZKABCFY

How would I go about solving this? I'm thinking known plaintext attack since I most likely know the beginning of the plaintext and also know that there are only a finite amount of possible words in the solution.

Further research led me to an obscure cipher Chaoscipher which goes in that direction.

Edit: longer example (also uses keyword as keyword):

doyouthinkthereisanotherwaytosolvethiscipher

becomes

HFUTLNAQYWHBWBEBTIEXWSZFGZQPINTQGHKDSVVVPXNM

Second edit: python code to test it

class ScrabbleCipher:
    def __init__(self, keyword):
        self.alpha = string.ascii_uppercase
        self.keyword = keyword.upper()
        self.initialAlpha()

    def initialAlpha(self):
        for i in self.keyword:
            self.shuffle(i)
        self.initial = self.alpha


    def shuffle(self, letter):
        try:
            tg = self.alpha.index(letter)
        except Exception as e:
            print letter
        self.alpha = self.alpha[tg+1:] + letter + self.alpha[:tg]


    def encrypt(self, plaintext):
        self.alpha = self.initial
        plaintext = plaintext.upper()
        ciphertext = ''
        for i in plaintext:
            pos = string.ascii_uppercase.index(i)
            ciphertext += self.alpha[pos]
            self.shuffle(i)
        return ciphertext

    def decrypt(self, ciphertext):
        ciphertext = self.sani(ciphertext)
        self.alpha = self.initial
        plaintext = ''
        for i in ciphertext:
            pos = self.alpha.index(i)
            corLet = string.ascii_uppercase[pos]
            plaintext += corLet
            self.shuffle(corLet)
        return plaintext
S. L.
  • 431
  • 3
  • 15

1 Answers1

2

So, I found a way to do it but it's neither elegant nor a general solution. It relies on the (heavy) assumption that the initial chosen keyword is English and a second assumption that the resulting cipher text is also English. It then becomes a relatively crude bruteforcing exercise:

1) Choose an English word

2) Create a cipher instantiated by that word

3) Decrypt the ciphertext using that cipher

4) Check whether the decrypted plaintext contains English words

Using a relatively large wordlist (400k), it took around 30-40 seconds to break, the keyword itself was 9 chars long. As such, the solution would be completely unpractical if the keyword is random (which incidentally is the second part of this challenge and as such I will update this answer if I solve that one too).

S. L.
  • 431
  • 3
  • 15