bgneal@65
|
1 M209 Class
|
bgneal@65
|
2 ==========
|
bgneal@65
|
3
|
bgneal@65
|
4 Naturally, the ``m209`` library includes a class that simulates a M-209
|
bgneal@65
|
5 converter. The :class:`~m209.converter.M209` class allows you to experiment
|
bgneal@65
|
6 with all moving parts of an M-209, including encrypting and decrypting
|
bgneal@69
|
7 messages. Keep in mind there is a higher level class,
|
bgneal@69
|
8 :class:`~m209.procedure.StdProcedure`, that encapsulates all the steps of the
|
bgneal@69
|
9 standard encrypting and decrypting operations, including generating indicators
|
bgneal@69
|
10 and placing or removing them from messages. However if you need lower-level
|
bgneal@69
|
11 access or you are inventing your own procedures, you would use the M209 class
|
bgneal@69
|
12 directly.
|
bgneal@65
|
13
|
bgneal@65
|
14 .. class:: m209.converter.M209([lugs=None[, pin_list=None]])
|
bgneal@65
|
15
|
bgneal@65
|
16 The ``M209`` class takes the following optional arguments.
|
bgneal@65
|
17
|
bgneal@65
|
18 :param lugs: either a lug settings list or string as per :meth:`set_drum_lugs`
|
bgneal@65
|
19 :param pin_list: a list of six strings each formatted as per :ref:`pin-settings`
|
bgneal@65
|
20
|
bgneal@67
|
21 ``M209`` objects have the following attributes.
|
bgneal@67
|
22
|
bgneal@67
|
23 .. attribute:: letter_count
|
bgneal@67
|
24
|
bgneal@67
|
25 This attribute represents the *letter counter* functionality. It is an
|
bgneal@67
|
26 integer that is incremented after every letter is encrypted or decrypted.
|
bgneal@67
|
27 It may be set to any integer value or examined at any time.
|
bgneal@67
|
28
|
bgneal@65
|
29 ``M209`` objects support the following methods.
|
bgneal@65
|
30
|
bgneal@65
|
31 .. method:: set_pins(n, effective_pins)
|
bgneal@65
|
32
|
bgneal@65
|
33 Sets the pin settings on the specified key wheel ``n``.
|
bgneal@65
|
34
|
bgneal@65
|
35 :param n: an integer between 0-5, inclusive. Key wheel 0 is the
|
bgneal@65
|
36 left-most wheel and wheel 5 is the right-most.
|
bgneal@65
|
37
|
bgneal@65
|
38 :param effective_pins: an iterable of letters whose pins are slid to
|
bgneal@65
|
39 the "effective" position (to the right). See :ref:`pin-settings`.
|
bgneal@65
|
40
|
bgneal@65
|
41 .. method:: set_all_pins(pin_list)
|
bgneal@65
|
42
|
bgneal@65
|
43 Sets all key wheel pins according to the supplied pin list.
|
bgneal@65
|
44
|
bgneal@65
|
45 :param pin_list: must either be ``None`` or a 6-element list of strings
|
bgneal@65
|
46 where each string element is as described in :ref:`pin-settings`.
|
bgneal@65
|
47 If ``None``, all pins in all key wheels are moved to the ineffective position.
|
bgneal@65
|
48
|
bgneal@65
|
49 .. method:: set_drum_lugs(lug_list)
|
bgneal@65
|
50
|
bgneal@65
|
51 Sets the drum lugs according to the given ``lug_list`` parameter.
|
bgneal@65
|
52
|
bgneal@65
|
53 If ``lug_list`` is ``None`` or empty, all lugs will be placed in neutral
|
bgneal@65
|
54 positions.
|
bgneal@65
|
55
|
bgneal@65
|
56 Otherwise, the ``lug_list`` can either be a list or a string.
|
bgneal@65
|
57
|
bgneal@65
|
58 If ``lug_list`` is passed a list, it must be a list of 1 or 2-tuple integers,
|
bgneal@65
|
59 where each integer is between 0-5, inclusive, and represents a 0-based
|
bgneal@65
|
60 key wheel position. The list can not be longer than 27 items. Only lug
|
bgneal@65
|
61 bars with lugs in non-neutral positions need be listed. Lug bars with one
|
bgneal@65
|
62 lug in a non-neutral position are represented by a 1-tuple. Bars with
|
bgneal@65
|
63 2 non-netural lugs are represented as a 2-tuple.
|
bgneal@65
|
64
|
bgneal@65
|
65 If ``lug_list`` is passed as a string, it is assumed to be in key list
|
bgneal@65
|
66 format as described in :ref:`lug-settings`.
|
bgneal@65
|
67
|
bgneal@65
|
68 Example::
|
bgneal@65
|
69
|
bgneal@65
|
70 m = M209()
|
bgneal@65
|
71 m.set_drum_lugs('1-0 2-0*2 0-3 0-5*3 0-6 2-4 3-6')
|
bgneal@65
|
72
|
bgneal@65
|
73 # or equivalently
|
bgneal@65
|
74 m.set_drum_lugs([(0, ), (1, ), (1, ), (2, ), (4, ), (4, ), (4, ), (5, ), (1, 3), (2, 5)])
|
bgneal@65
|
75
|
bgneal@65
|
76
|
bgneal@65
|
77 .. method:: set_key_wheel(n, c)
|
bgneal@65
|
78
|
bgneal@65
|
79 Set key wheel ``n`` to the letter ``c``.
|
bgneal@65
|
80
|
bgneal@65
|
81 :param n: an integer between 0-5 where key wheel 0 is the leftmost key wheel,
|
bgneal@65
|
82 and 5 is the rightmost
|
bgneal@65
|
83 :param c: a 1-letter string valid for key wheel ``n``
|
bgneal@65
|
84 :raises KeyWheelError: if ``c`` is not valid for wheel ``n``
|
bgneal@65
|
85
|
bgneal@65
|
86 .. method:: set_key_wheels(s)
|
bgneal@65
|
87
|
bgneal@65
|
88 Set the key wheels from left to right to the six letter string ``s``.
|
bgneal@65
|
89
|
bgneal@65
|
90 :raises KeyWheelError: if any letter in ``s`` is not valid for the corresponding key wheel
|
bgneal@65
|
91
|
bgneal@65
|
92 .. method:: set_random_key_wheels()
|
bgneal@65
|
93
|
bgneal@65
|
94 Sets the six key wheels to random letters.
|
bgneal@65
|
95
|
bgneal@65
|
96 :returns: a string of length six representing the new key wheel settings
|
bgneal@65
|
97
|
bgneal@65
|
98 .. method:: get_settings()
|
bgneal@65
|
99
|
bgneal@65
|
100 Returns the current key settings.
|
bgneal@65
|
101
|
bgneal@65
|
102 :returns: a named tuple of ``(lugs, pin_list)`` representing the current
|
bgneal@65
|
103 key settings. ``lugs`` will be in string format.
|
bgneal@65
|
104
|
bgneal@65
|
105 .. method:: encrypt(plaintext[, group=True[, spaces=True]])
|
bgneal@65
|
106
|
bgneal@65
|
107 Performs an encrypt operation on the given plaintext and returns the
|
bgneal@65
|
108 encrypted ciphertext as a string.
|
bgneal@65
|
109
|
bgneal@65
|
110 :param plaintext: the text string to encrypt
|
bgneal@65
|
111 :param group: if ``True``, the ciphertext string will be grouped into 5-letter
|
bgneal@65
|
112 groups, separated by spaces
|
bgneal@65
|
113 :param spaces: if ``True``, space characters in the input plaintext will
|
bgneal@65
|
114 automatically be treated as ``Z`` characters. Otherwise spaces in the
|
bgneal@65
|
115 plaintext will raise an ``M209Error``.
|
bgneal@65
|
116 :returns: the ciphertext as a string
|
bgneal@65
|
117
|
bgneal@65
|
118 .. method:: decrypt(ciphertext[, spaces=True[, z_sub=True]])
|
bgneal@65
|
119
|
bgneal@65
|
120 Performs a decrypt operation on the given ciphertext and returns the
|
bgneal@65
|
121 decrypted plaintext as a string.
|
bgneal@65
|
122
|
bgneal@65
|
123 :param ciphertext: the text string to decyrpt
|
bgneal@65
|
124 :param spaces: if ``True``, spaces will be allowed in the input ciphertext and
|
bgneal@65
|
125 ignored. Otherwise space characters will raise an ``M209Error``.
|
bgneal@65
|
126 This is useful if the input ciphertext is in 5-letter groups, separated
|
bgneal@65
|
127 by spaces.
|
bgneal@65
|
128 :param z_sub: if ``True``, ``Z`` characters in the output plaintext will be
|
bgneal@65
|
129 replaced by space characters, just like an actual M-209.
|
bgneal@65
|
130 :returns: the plaintext as a string
|
bgneal@65
|
131
|
bgneal@65
|
132 Example:
|
bgneal@65
|
133
|
bgneal@65
|
134 >>> from m209.converter import M209
|
bgneal@65
|
135 >>> m = M209()
|
bgneal@65
|
136 >>> m.set_drum_lugs('1-0 2-0*2 0-3 0-5*3 0-6 2-4 3-6')
|
bgneal@65
|
137 >>> pin_list = [
|
bgneal@65
|
138 ... 'FGIKOPRSUVWYZ',
|
bgneal@65
|
139 ... 'DFGKLMOTUY',
|
bgneal@65
|
140 ... 'ADEFGIORTUVX',
|
bgneal@65
|
141 ... 'ACFGHILMRSU',
|
bgneal@65
|
142 ... 'BCDEFJKLPS',
|
bgneal@65
|
143 ... 'EFGHIJLMNP'
|
bgneal@65
|
144 ... ]
|
bgneal@65
|
145 >>> m.set_all_pins(pin_list)
|
bgneal@65
|
146 >>> m.set_key_wheels('FFEGJP')
|
bgneal@65
|
147 >>> ct = m.encrypt('THE PIZZA HAS ARRIVED')
|
bgneal@65
|
148 >>> ct
|
bgneal@65
|
149 'QBCHU WCCDI YFNCH LOZJY G'
|
bgneal@65
|
150 >>> m.set_key_wheels('FFEGJP')
|
bgneal@65
|
151 >>> pt = m.decrypt(ct)
|
bgneal@65
|
152 >>> pt
|
bgneal@65
|
153 'THE PI A HAS ARRIVED'
|