Modules

Note

fitness_functions in every module must return a value such that a lower score means the text is closer to the target.

Shift

Automated breaking of the Shift Cipher.

lantern.modules.shift.crack(ciphertext, *fitness_functions, min_key=0, max_key=26, shift_function=<function make_shift_function.<locals>.shift_case_sensitive>)

Break ciphertext by enumerating keys between min_key and max_key.

Example

>>> decryptions = crack("KHOOR", fitness.english.quadgrams)
>>> print(''.join(decryptions[0].plaintext))
HELLO
Parameters:
  • ciphertext (iterable) – The symbols to decrypt
  • *fitness_functions (variable length argument list) – Functions to score decryption with
Keyword Arguments:
 
  • min_key (int) – Key to start with
  • max_key (int) – Key to stop at (exclusive)
  • shift_function (function(shift, symbol)) – Shift function to use
Returns:

Sorted list of decryptions

Raises:
  • ValueError – If min_key exceeds max_key
  • ValueError – If no fitness_functions are given
lantern.modules.shift.decrypt(key: int, ciphertext: Iterable[T_co], shift_function: Callable[[int, object], object] = <function make_shift_function.<locals>.shift_case_sensitive>) → Iterable[T_co]

Decrypt Shift enciphered ciphertext using key.

Examples

>>> ''.join(decrypt(3, "KHOOR"))
HELLO
>>> decrypt(15, [0xed, 0xbc, 0xcd, 0xfe], shift_bytes)
[0xde, 0xad, 0xbe, 0xef]
Parameters:
  • key (int) – The shift to use
  • ciphertext (iterable) – The symbols to decrypt
  • shift_function (function (shift, symbol)) – Shift function to apply to symbols in the ciphertext
Returns:

Decrypted text

lantern.modules.shift.encrypt(key: int, plaintext: Iterable[T_co], shift_function: Callable[[int, object], object] = <function make_shift_function.<locals>.shift_case_sensitive>) → Iterable[T_co]

Encrypt plaintext with key using the Shift cipher.

Examples

>>> ''.join(encrypt(3, "HELLO"))
KHOOR
>>> encrypt(15, [0xde, 0xad, 0xbe, 0xef], shift_bytes)
[0xed, 0xbc, 0xcd, 0xfe]
Parameters:
  • key (int) – The shift to use
  • plaintext (iterable) – The symbols to encrypt
  • shift_function (function (shift, symbol)) – Shift function to apply to symbols in the plaintext
Returns:

Encrypted text

lantern.modules.shift.make_shift_function(alphabet: Iterable[T_co], operator: Callable[[int, int], int] = <function <lambda>>) → Callable[[int, object], object]

Construct a shift function from an alphabet.

Examples

Shift cases independently

>>> make_shift_function([string.ascii_uppercase, string.ascii_lowercase])

Additionally shift punctuation characters

>>> make_shift_function([string.ascii_uppercase, string.ascii_lowercase, string.punctuation])

Shift entire ASCII range, overflowing cases

>>> make_shift_function([''.join(chr(x) for x in range(32, 127))])
Parameters:alphabet (iterable) – Ordered iterable of strings representing separate cases of an alphabet
Returns:int, symbol: object)
Return type:Function (shift

Simple Substitution

Automated breaking of the Simple Substitution Cipher.

lantern.modules.simplesubstitution.crack(ciphertext, *fitness_functions, ntrials=30, nswaps=3000)

Break ciphertext using hill climbing.

Note

Currently ntrails and nswaps default to magic numbers. Generally the trend is, the longer the text, the lower the number of trials you need to run, because the hill climbing will lead to the best answer faster. Because randomness is involved, there is the possibility of the correct decryption not being found. In this circumstance you just need to run the code again.

Example

>>> decryptions = crack("XUOOB", fitness.english.quadgrams)
>>> print(decryptions[0])
HELLO
Parameters:
  • ciphertext (str) – The text to decrypt
  • *fitness_functions (variable length argument list) – Functions to score decryption with
Keyword Arguments:
 
  • ntrials (int) – The number of times to run the hill climbing algorithm
  • nswaps (int) – The number of rounds to find a local maximum
Returns:

Sorted list of decryptions

Raises:
  • ValueError – If nswaps or ntrails are not positive integers
  • ValueError – If no fitness_functions are given
lantern.modules.simplesubstitution.decrypt(key, ciphertext)

Decrypt Simple Substitution enciphered ciphertext using key.

Example

>>> decrypt("PQSTUVWXYZCODEBRAKINGFHJLM", "XUOOB")
HELLO
Parameters:
  • key (iterable) – The key to use
  • ciphertext (str) – The text to decrypt
Returns:

Decrypted ciphertext

Vigenere

Automated breaking of the Vigenere Cipher.

lantern.modules.vigenere.crack(ciphertext, *fitness_functions, key_period=None, max_key_period=30)

Break ciphertext by finding (or using the given) key_period then breaking key_period many Caesar ciphers.

Example

>>> decryptions = crack("OMSTV", fitness.ChiSquared(analysis.frequency.english.unigrams))
>>> print(decryptions[0])
HELLO
Parameters:
  • ciphertext (str) – The text to decrypt
  • *fitness_functions (variable length argument list) – Functions to score decryption with
Keyword Arguments:
 
  • key_period (int) – The period of the key
  • max_key_period (int) – The maximum period the key could be
Returns:

Sorted list of decryptions

Raises:
  • ValueError – If key_period or max_key_period are less than or equal to 0
  • ValueError – If no fitness_functions are given
lantern.modules.vigenere.decrypt(key, ciphertext)

Decrypt Vigenere encrypted ciphertext using key.

Example

>>> decrypt("KEY", "RIJVS")
HELLO
Parameters:
  • key (iterable) – The key to use
  • ciphertext (str) – The text to decrypt
Returns:

Decrypted ciphertext

lantern.modules.vigenere.key_periods(ciphertext, max_key_period)

Rank all key periods for ciphertext up to and including max_key_period

Example

>>> key_periods(ciphertext, 30)
[2, 4, 8, 3, ...]
Parameters:
  • ciphertext (str) – The text to analyze
  • max_key_period (int) – The maximum period the key could be
Returns:

Sorted list of keys

Raises:

ValueError – If max_key_period is less than or equal to 0