Note

This documentation is in draft form. Reports of any errors or suggestions for improvement are welcomed and should be submitted as new issues.

Cypher - crypto_enigma.cypher

This is a supporting module that implements the simple substitution cypher employed by the Enigma machine to encode messages. It will not generally be used directly.

Overview

Mapping A substitution cypher mapping.
encode_string Encode a string using the mapping.
encode_char Encode a single character using the mapping.

Substitution cypher mappings

All encoding functionality is built upon a single class:

class crypto_enigma.cypher.Mapping[source]

Bases: unicode

A substitution cypher mapping.

The Enigma machine, and the components from which it is constructed, use mappings to perform a simple substitution encoding. Mappings describe

  • the cryptographic effects of each component’s fixed wiring;
  • the encoding they perform individually in a machine based on their rotational positions and the direction in which a signal passes through them (see mapping); and,
  • the progressive (stage_mapping_list) and overall (enigma_mapping_list and enigma_mapping) encoding performed by the machine as a whole.

Mapping encoding

Mappings are expressed as a string of letters indicating the mapped-to letter for the letter at that position in the alphabet — i.e., as a permutation of the alphabet. For example, the mapping EKMFLGDQVZNTOWYHXUSPAIBRCJ encodes A to E, B to K, C to M, …, Y to C, and Z to J:

>>> mpg = Mapping(u'EKMFLGDQVZNTOWYHXUSPAIBRCJ')
>>> mpg.encode_string(u'ABCYZJ')
u'EKMCJZ'
>>> mpg.encode_string(u'ABCDEFGHIJKLMNOPQRSTUVWXYZ') == mpg
True

Note that there is no way to directly create Mapping for use by an EnigmaMachine or Component. The closest one can get is to configure a plugboard with component:

>>> component(u'AE.BK.CM.FD').wiring 
u'EKMF...'

For reference, two functions are provided to perform a mappings substitution cypher, though these will rarely be used directly:

Mapping.encode_string(string)[source]

Encode a string using the mapping.

Parameters:string (str) – A string to encode using the Mapping.
Returns:
A string consisting of each of the characters replaced with the corresponding
character in the Mapping.
Return type:str

Examples

This just the collected results of applying encode_char to each letter of the string:

>>> component(u'AE.BK.CM.FD').wiring.encode_string(u'ABKCFEKMD')
u'EKBMDABCF'
>>> ''.join(component(u'AE.BK.CM.FD').wiring.encode_char(c) for c in u'ABKCFEKMD')
u'EKBMDABCF'

Note that, critically, the mapping used by an Enigma machine changes before each character is encoded so that:

>>> cfg.enigma_mapping().encode_string(str) != cfg.enigma_encoding(str)
True
Mapping.encode_char(ch)[source]

Encode a single character using the mapping.

Parameters:ch (char) – A character to encode using the Mapping.
Returns:The character, replaced with the corresponding characters in the Mapping.
Return type:chr

Example

In the context of this package, this is most useful in low level analysis of the encoding process:

>>> wng = component(u'AE.BK.CM.FD').wiring
>>> wng.encode_char(u'A')
u'E'
>>> wng.encode_char(u'K')
u'B'
>>> wng.encode_char(u'Q')
u'Q'

For example, it can be used to confirm that only letters connected in a plugboard are unaltered by the encoding it performs:

>>> pbd = component(u'AE.BK.CM.FD')
>>> all(pbd.wiring.encode_char(c) == c for c in filter(lambda c: c not in pbd.name,  u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
True
>>> all(pbd.wiring.encode_char(c) != c for c in filter(lambda c: c in pbd.name,  u'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
True