class Bifid(Cipher): """The Bifid Cipher is a fractionating cipher, and has a key consisting of a 25 letter keysquare (with a letter removed e.g. 'J'), along with a 'period', which is an integer. For more information, the algorithm can be seen e.g. http://www.practicalcryptography.com/ciphers/bifid-cipher/ :param key: The keysquare, as a 25 character string. :param period: an integer. """ def __init__(self,key='phqgmeaylnofdxkrcvszwbuti',period=5): self.key = [k.upper() for k in key] self.pb = PolybiusSquare(self.key,size=5) self.period = period assert len(key)==25, 'invalid key in init: must have length 25, has length '+str(len(key)) assert period>=1, 'invalid period in init: period should be >= 1' def encipher(self,string): """Encipher string using Bifid cipher according to initialised key. Punctuation and whitespace are removed from the input. Example:: ciphertext = Bifid('phqgmeaylnofdxkrcvszwbuti',5).encipher(plaintext) :param string: The string to encipher. :returns: The enciphered string. """ string = self.remove_punctuation(string) step1 = self.pb.encipher(string) evens = step1[::2] odds = step1[1::2] step2 = [] for i in range(0,len(string),self.period): step2 += evens[i:i+self.period] step2 += odds[i:i+self.period] return self.pb.decipher(''.join(step2)) def decipher(self,string): """Decipher string using Bifid cipher according to initialised key. Punctuation and whitespace are removed from the input. Example:: plaintext = Bifid('phqgmeaylnofdxkrcvszwbuti',5).decipher(ciphertext) :param string: The string to decipher. :returns: The deciphered string. """ ret = '' string = string.upper() rowseq,colseq = [],[] # take blocks of length period, reform rowseq,colseq from them for i in range(0,len(string),self.period): tempseq = [] for j in range(0,self.period): if i+j >= len(string): continue tempseq.append( self.key.index(string[i + j]) / 5 ) tempseq.append( self.key.index(string[i + j]) % 5 ) rowseq.extend(tempseq[0:len(tempseq)/2]) colseq.extend(tempseq[len(tempseq)/2:]) for i in range(len(rowseq)): ret += self.key[rowseq[i]*5 + colseq[i]] return ret
def crypto_polybius_decipher_api(key: 'The keysquare, each row one after the other. The key must by size^2 characters in length', size:type_key_square_size, chars:'the set of characters to use. By default ABCDE are used, this parameter should have the same length as size', msg: 'Message to be [de]ciphered'): """The Polybius square is a simple substitution cipher that outputs 2 characters of ciphertext for each character of plaintext. It has a key consisting which depends on 'size'. By default 'size' is 5, and the key is 25 letters (5^2). For a size of 6 a 36 letter key required etc. For a more detailed look at how it works see http://www.practicalcryptography.com/ciphers pycipher.polybius-square-cipher/""" if len(key) == size**2 and len(chars) == size: polybius = PolybiusSquare(key=key, size=size, chars=chars) return polybius.decipher(msg) else: return 'Invalid parameters'