+"""Enciphering and deciphering using the [Bifid cipher](https://en.wikipedia.org/wiki/Bifid_cipher).
+Also attempts to break messages that use a Bifid cipher.
+"""
import multiprocessing
from szyfrow.support.utilities import *
from szyfrow.support.language_models import *
>>> bifid_encipher("indiacurry", 'iguana', period=4, fillvalue='x')
'ibnhgaqltzml'
"""
+
+ if period:
+ if not fillvalue:
+ raise ValueError("fillvalue must be given if period is given")
+ else:
+ p_message = message + pad(len(message), period, fillvalue)
+ else:
+ p_message = message
+
translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
- t_message = message.translate(translation)
+ t_message = p_message.translate(translation)
pairs0 = [f_grid[l] for l in sanitise(t_message)]
if period:
- chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
- if len(chunked_pairs[-1]) < period and fillvalue:
- chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
+ # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
+ # if len(chunked_pairs[-1]) < period and fillvalue:
+ # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
+ chunked_pairs = chunks(pairs0, period, fillvalue=None)
else:
chunked_pairs = [pairs0]
>>> bifid_decipher("ibnhgaqltzml", 'iguana', period=4)
'indiacurryxx'
"""
+ if period:
+ if not fillvalue:
+ raise ValueError("fillvalue must be given if period is given")
+ else:
+ p_message = message + pad(len(message), period, fillvalue)
+ else:
+ p_message = message
+
translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)
t_message = message.translate(translation)
pairs0 = [f_grid[l] for l in sanitise(t_message)]
if period:
- chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
- if len(chunked_pairs[-1]) < period and fillvalue:
- chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
+ # chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]
+ # if len(chunked_pairs[-1]) < period and fillvalue:
+ # chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))
+ chunked_pairs = chunks(pairs0, period, fillvalue=None)
else:
chunked_pairs = [pairs0]
return cat(r_grid[p] for p in pairs1)
-def bifid_break_mp(message, wordlist=keywords, fitness=Pletters, max_period=10,
+def bifid_break(message, wordlist=None, fitness=Pletters, max_period=10,
number_of_solutions=1, chunksize=500):
"""Breaks a keyword substitution cipher using a dictionary and
frequency analysis
- >>> bifid_break_mp(bifid_encipher('this is a test message for the ' \
+ If `wordlist` is not specified, use
+ [`szyfrow.support.langauge_models.keywords`](support/language_models.html#szyfrow.support.language_models.keywords).
+
+ >>> bifid_break(bifid_encipher('this is a test message for the ' \
'keyword decipherment', 'elephant', wrap_alphabet=KeywordWrapAlphabet.from_last), \
wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
(('elephant', <KeywordWrapAlphabet.from_last: 2>, 0), -52.834575011...)
- >>> bifid_break_mp(bifid_encipher('this is a test message for the ' \
+ >>> bifid_break(bifid_encipher('this is a test message for the ' \
'keyword decipherment', 'elephant', wrap_alphabet=KeywordWrapAlphabet.from_last), \
wordlist=['cat', 'elephant', 'kangaroo'], \
number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
[(('elephant', <KeywordWrapAlphabet.from_last: 2>, 0), -52.834575011...),
(('elephant', <KeywordWrapAlphabet.from_largest: 3>, 0), -52.834575011...)]
"""
+ if wordlist is None:
+ wordlist = keywords
+
with multiprocessing.Pool() as pool:
helper_args = [(message, word, wrap, period, fitness)
for word in wordlist
return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]
def bifid_break_worker(message, keyword, wrap_alphabet, period, fitness):
- plaintext = bifid_decipher(message, keyword, wrap_alphabet, period=period)
+ plaintext = bifid_decipher(message, keyword, wrap_alphabet,
+ period=period, fillvalue='e')
fit = fitness(plaintext)
return (keyword, wrap_alphabet, period), fit