import norms
import logging
from itertools import zip_longest, cycle
-from segment import segment
+from segment import segment, Pwords
from multiprocessing import Pool
from cipher import *
>>> caesar_break('ibxcsyorsaqcheyklxivoexlevmrimwxsfiqevvmihrsasrxliwyrh' \
'ecjsppsamrkwleppfmergefifvmhixscsymjcsyqeoixlm') # doctest: +ELLIPSIS
- (4, 0.31863952890183...)
+ (4, 0.080345432737...)
>>> caesar_break('wxwmaxdgheetgwuxztgptedbgznitgwwhpguxyhkxbmhvvtlbhgtee' \
'raxlmhiixweblmxgxwmhmaxybkbgztgwztsxwbgmxgmert') # doctest: +ELLIPSIS
- (19, 0.42152901235832...)
+ (19, 0.11189290326...)
>>> caesar_break('yltbbqnqnzvguvaxurorgenafsbezqvagbnornfgsbevpnaabjurer' \
'svaquvzyvxrnznazlybequrvfohgriraabjtbaruraprur') # doctest: +ELLIPSIS
- (13, 0.316029208075451...)
+ (13, 0.08293968842...)
"""
sanitised_message = sanitise(message)
best_shift = 0
'ls umfjsd jlsi zg hfsqysxog. ls dmmdtsd mx jls bats mh bkbsf. ls ' \
'bfmctsd kfmyxd jls lyj, mztanamyu xmc jm clm cku tmmeaxw kj lai kxd ' \
'clm ckuxj.') # doctest: +ELLIPSIS
- ((15, 22, True), 0.23570361818655...)
+ ((15, 22, True), 0.0598745365924...)
"""
sanitised_message = sanitise(message)
best_multiplier = 0
>>> keyword_break(keyword_encipher('this is a test message for the ' \
'keyword decipherment', 'elephant', 1), \
wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
- (('elephant', 1), 0.41643991598441...)
+ (('elephant', 1), 0.1066453448861...)
"""
best_keyword = ''
best_wrap_alphabet = True
>>> keyword_break_mp(keyword_encipher('this is a test message for the ' \
'keyword decipherment', 'elephant', 1), \
wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
- (('elephant', 1), 0.41643991598441...)
+ (('elephant', 1), 0.106645344886...)
"""
with Pool() as pool:
helper_args = [(message, word, wrap, metric, target_counts,
>>> scytale_break('tfeulchtrtteehwahsdehneoifeayfsondmwpltmaoalhikotoere' \
'dcweatehiplwxsnhooacgorrcrcraotohsgullasenylrendaianeplscdriioto' \
'aek') # doctest: +ELLIPSIS
- (6, 0.83453041115025...)
+ (6, 0.092599933059...)
"""
best_key = 0
best_fit = float("inf")
n-gram frequency analysis
>>> column_transposition_break(column_transposition_encipher(sanitise( \
- "Turing's homosexuality resulted in a criminal prosecution in 1952, \
- when homosexual acts were still illegal in the United Kingdom. "), \
+ "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.898128626285...)
+ ((2, 0, 5, 3, 1, 4, 6), 0.0628106372...)
>>> column_transposition_break(column_transposition_encipher(sanitise( \
- "Turing's homosexuality resulted in a criminal prosecution in 1952, " \
- "when homosexual acts were still illegal in the United Kingdom."), \
+ "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), 1.1958792913127...)
+ ((2, 0, 5, 3, 1, 4, 6), 0.0592259560...)
"""
best_transposition = ''
best_fit = float("inf")
n-gram frequency analysis
>>> column_transposition_break_mp(column_transposition_encipher(sanitise( \
- "Turing's homosexuality resulted in a criminal prosecution in 1952, \
- when homosexual acts were still illegal in the United Kingdom. "), \
+ "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.898128626285...)
+ ((2, 0, 5, 3, 1, 4, 6), 0.0628106372...)
>>> column_transposition_break_mp(column_transposition_encipher(sanitise( \
- "Turing's homosexuality resulted in a criminal prosecution in 1952, " \
- "when homosexual acts were still illegal in the United Kingdom."), \
+ "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), 1.1958792913127...)
+ ((2, 0, 5, 3, 1, 4, 6), 0.0592259560...)
"""
ngram_length = len(next(iter(target_counts.keys())))
with Pool() as pool:
"""Breaks a vigenere cipher using a dictionary and
frequency analysis
- >>> vigenere_keyword_break(keyword_encipher('this is a test message for the ' \
- 'keyword decipherment', 'elephant', 1), \
+ >>> vigenere_keyword_break(vigenere_encipher(sanitise('this is a test ' \
+ 'message for the vigenere decipherment'), 'cat'), \
wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
- ('elephant', 0.7166585201707...)
+ ('cat', 0.15965224935...)
"""
best_keyword = ''
best_fit = float("inf")
"""Breaks a vigenere cipher using a dictionary and
frequency analysis
- >>> vigenere_keyword_break_mp(keyword_encipher('this is a test message for the ' \
- 'keyword decipherment', 'elephant', 1), \
+ >>> vigenere_keyword_break_mp(vigenere_encipher(sanitise('this is a test ' \
+ 'message for the vigenere decipherment'), 'cat'), \
wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS
- ('elephant', 0.7166585201707...)
+ ('cat', 0.159652249358...)
"""
with Pool() as pool:
helper_args = [(message, word, metric, target_counts,
return keyword, fit
+
+def vigenere_frequency_break(message,
+ metric=norms.euclidean_distance,
+ target_counts=normalised_english_counts,
+ message_frequency_scaling=norms.normalise):
+ """Breaks a Vigenere cipher with frequency analysis
+
+ >>> vigenere_frequency_break(vigenere_encipher(sanitise("It is time to " \
+ "run. She is ready and so am I. I stole Daniel's pocketbook this " \
+ "afternoon when he left his jacket hanging on the easel in the " \
+ "attic."), 'florence')) # doctest: +ELLIPSIS
+ ('florence', 0.077657073...)
+ """
+ best_fit = float("inf")
+ best_key = ''
+ sanitised_message = sanitise(message)
+ for trial_length in range(1, 20):
+ splits = every_nth(sanitised_message, trial_length)
+ key = ''.join([chr(caesar_break(s, target_counts=target_counts)[0] + ord('a')) for s in splits])
+ plaintext = vigenere_decipher(sanitised_message, key)
+ counts = message_frequency_scaling(frequencies(plaintext))
+ fit = metric(target_counts, counts)
+ logger.debug('Vigenere key length of {0} ({1}) gives fit of {2}'.
+ format(trial_length, key, fit))
+ if fit < best_fit:
+ best_fit = fit
+ best_key = key
+ logger.info('Vigenere break best fit with key {0} gives fit '
+ 'of {1} and decrypt starting: {2}'.format(best_key,
+ best_fit, sanitise(
+ vigenere_decipher(message, best_key))[:50]))
+ return best_key, best_fit
+
+
+
if __name__ == "__main__":
import doctest
doctest.testmod()