X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=szyfrow%2Fcaesar.py;h=910ada2f456639160adad6ec4cbf3ad4e08ae567;hb=refs%2Fheads%2Fmain;hp=ec878fcf2fe941d029853d0bed103e9250925054;hpb=a870050db6bc974b1bb0d132001750b6624fb43f;p=szyfrow.git diff --git a/szyfrow/caesar.py b/szyfrow/caesar.py index ec878fc..910ada2 100644 --- a/szyfrow/caesar.py +++ b/szyfrow/caesar.py @@ -1,10 +1,20 @@ -from support.utilities import * -from support.language_models import * +"""Enciphering and deciphering using the [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher). +Also attempts to break messages that use a Caesar cipher. -from logger import logger +The Caesar cipher operates one letter at a time. It converts each letter to a +number, then enciphers that number by adding the key. The result is taken mod +26 and converted back into a letter. + +""" + +from szyfrow.support.utilities import * +from szyfrow.support.language_models import * def caesar_encipher_letter(accented_letter, shift): - """Encipher a letter, given a shift amount + """Encipher a letter, given a shift amount. + + Accented version of latin letters (such as é and ö) are converted to their + non-accented versions before encryption. >>> caesar_encipher_letter('a', 1) 'b' @@ -93,6 +103,9 @@ def caesar_decipher(message, shift): def caesar_break(message, fitness=Pletters): """Breaks a Caesar cipher using frequency analysis + It tries all possible keys, scores the fitness of the text decipherd with + each key, and returns the key that produces the most fit deciphered text. + >>> caesar_break('ibxcsyorsaqcheyklxivoexlevmrimwxsfiqevvmihrsasrxliwyrh' \ 'ecjsppsamrkwleppfmergefifvmhixscsymjcsyqeoixlm') # doctest: +ELLIPSIS (4, -130.849989015...) @@ -109,13 +122,9 @@ def caesar_break(message, fitness=Pletters): for shift in range(26): plaintext = caesar_decipher(sanitised_message, shift) fit = fitness(plaintext) - logger.debug('Caesar break attempt using key {0} gives fit of {1} ' - 'and decrypt starting: {2}'.format(shift, fit, - plaintext[:50])) + if fit > best_fit: best_fit = fit best_shift = shift - logger.info('Caesar break best fit: key {0} gives fit of {1} and ' - 'decrypt starting: {2}'.format(best_shift, best_fit, - caesar_decipher(sanitised_message, best_shift)[:50])) + return best_shift, best_fit