jameslyons / pycipher

python module containing many classical cipher algorithms: Caesar, Vigenere, ADFGVX, Enigma etc.
MIT License
213 stars 53 forks source link

Ciphers using a 5x5 keysquare can't encipher messages containing 'j' #8

Open jina312 opened 6 years ago

jina312 commented 6 years ago

If I use a cipher that requires a 5x5 keysquare with 'j' omitted, I can't encipher a message that includes the letter 'j'.

Test case:

>>> from pycipher import ADFGX
>>> ADFGX('phqgmeaylnofdxkrcvszwbuti','HELLO').decipher('bluejay')    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/.../lib/python3.6/site-packages/pycipher/adfgx.py", line 52, in decipher
    step1 = PolybiusSquare(self.key,size=5,chars='ADFGX').decipher(step2)
  File "/Users/.../lib/python3.6/site-packages/pycipher/polybius.py", line 65, in decipher
    ret += self.decipher_pair(string[i:i+2])
  File "/Users/.../lib/python3.6/site-packages/pycipher/polybius.py", line 32, in decipher_pair
    row = self.chars.index(pair[0])
ValueError: substring not found
jameslyons commented 6 years ago

This one is a bit tricky, It ignores the letter j because there is no j in the key provided. If you replace e.g. k with j in the key, then k won't be allowed. I could just filter out any letters not in the key, but usually a replacement is made e.g. j is replaced with i. But this would obviously be different depending on the letter that is left out of the key. So I guess one solution is to change j to i before calling the encipher function, but this is a bit clunky.

I'm thinking perhaps filter out any characters not in the key, but print a warning that characters were filtered out. What do you think?

jina312 commented 6 years ago

On the page you refer for the algorithm (http://www.practicalcryptography.com/ciphers/classical-era/adfgvx/), if you look at the javascript behind what they do there (I just did 'inspect element' on the 'Encrypt' button to see the Encrypt() function), it seems to enforce 'j' not to be in the key and remove any character that's not in the key. I don't know if that's how the algorithm is supposed to work, but it's similar to what you suggested. I do like the idea of printing a warning about any filtered character.