-def column_transposition_break(message,
- translist=transpositions,
- metric=norms.euclidean_distance,
- target_counts=normalised_english_bigram_counts,
- message_frequency_scaling=norms.normalise):
- """Breaks a column transposition cipher using a dictionary and
- n-gram frequency analysis
-
- >>> column_transposition_break(column_transposition_encipher(sanitise( \
- "It is a truth universally acknowledged, that a single man in \
- possession of a good fortune, must be in want of a wife. However \
- little known the feelings or views of such a man may be on his \
- first entering a neighbourhood, this truth is so well fixed in the \
- minds of the surrounding families, that he is considered the \
- rightful property of some one or other of their daughters."), \
- 'encipher'), \
- translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
- (5, 0, 6, 1, 3, 4, 2): ['fourteen'], \
- (6, 1, 0, 4, 5, 3, 2): ['keyword']}) # doctest: +ELLIPSIS
- ((2, 0, 5, 3, 1, 4, 6), 0.0628106372...)
- >>> column_transposition_break(column_transposition_encipher(sanitise( \
- "It is a truth universally acknowledged, that a single man in \
- possession of a good fortune, must be in want of a wife. However \
- little known the feelings or views of such a man may be on his \
- first entering a neighbourhood, this truth is so well fixed in the \
- minds of the surrounding families, that he is considered the \
- rightful property of some one or other of their daughters."), \
- 'encipher'), \
- translist={(2, 0, 5, 3, 1, 4, 6): ['encipher'], \
- (5, 0, 6, 1, 3, 4, 2): ['fourteen'], \
- (6, 1, 0, 4, 5, 3, 2): ['keyword']}, \
- target_counts=normalised_english_trigram_counts) # doctest: +ELLIPSIS
- ((2, 0, 5, 3, 1, 4, 6), 0.0592259560...)
- """
- best_transposition = ''
- best_fit = float("inf")
- ngram_length = len(next(iter(target_counts.keys())))
- for transposition in translist.keys():
- if len(message) % len(transposition) == 0:
- plaintext = column_transposition_decipher(message, transposition)
- counts = message_frequency_scaling(frequencies(
- ngrams(sanitise(plaintext), ngram_length)))
- fit = metric(target_counts, counts)
- logger.debug('Column transposition break attempt using key {0} '
- 'gives fit of {1} and decrypt starting: {2}'.format(
- translist[transposition][0], fit,
- sanitise(plaintext)[:50]))
- if fit < best_fit:
- best_fit = fit
- best_transposition = transposition
- logger.info('Column transposition break best fit with key {0} gives fit '
- 'of {1} and decrypt starting: {2}'.format(
- translist[best_transposition][0],
- best_fit, sanitise(
- column_transposition_decipher(message,
- best_transposition))[:50]))
- return best_transposition, best_fit
-