bgneal@68: StdProcedure Class bgneal@68: ================== bgneal@68: bgneal@68: The ``StdProcedure`` class encapsulates the encrypting and decrypting bgneal@68: procedures outlined in :ref:`references-label`. In particular, see bgneal@68: references [5] and [7]. This class takes care of the high level details of bgneal@71: inserting various message indicators into an encrypted message, and stripping bgneal@68: them off during decrypt. These message indicators tell the recipient what key bgneal@68: list and initial key wheel settings to use when configuring their M-209 for bgneal@68: decrypt. bgneal@68: bgneal@68: .. class:: m209.procedure.StdProcedure([m_209=None[, key_list=None]]) bgneal@68: bgneal@68: :param m_209: an instance of a :class:`~m209.converter.M209` can optionally be bgneal@68: provided to the procedure object. If ``None`` the procedure object bgneal@68: will create one for internal use. bgneal@68: :param key_list: an instance of a :class:`~m209.keylist.KeyList` can be bgneal@68: provided if known ahead of time. Before an encrypt or decrypt operation bgneal@68: can be performed, a key list must be provided. This can be done after bgneal@68: object creation via :meth:`set_key_list`. Note that the ``letter_check`` bgneal@68: attribute of the :class:`~m209.keylist.KeyList` is not accessed by the bgneal@68: procedure object, and can be ``None`` if not known. bgneal@68: bgneal@68: Before an :meth:`encrypt` operation can be performed, a valid key list must be bgneal@68: installed, either during procedure object construction, or by the bgneal@68: :meth:`set_key_list` method. bgneal@68: bgneal@68: Decrypt operations are performed in a 3-step process. bgneal@68: bgneal@68: #. First, a call to the :meth:`set_decrypt_message` method passes the message bgneal@68: to be decrypted to the procedure and establishes the parameters to be used bgneal@68: for the actual :meth:`decrypt` operation. These decrypt parameters are bgneal@68: returned to the caller. bgneal@68: bgneal@68: #. The caller can examine the decrypt parameters to determine which key list bgneal@68: must be installed before a successful :meth:`decrypt` operation can be bgneal@68: carried out. The caller may call :meth:`get_key_list` to examine the bgneal@68: currently installed key list. It is up to the caller to obtain the required bgneal@68: key list and install it with :meth:`set_key_list`, if necessary. This is bgneal@68: done by ensuring the installed key list indicator matches the bgneal@68: ``key_list_ind`` field of the decrypt parameters. bgneal@68: bgneal@68: #. Finally :meth:`decrypt` can be called. If the procedure does not have the bgneal@68: key list necessary to decrypt the message, a ``ProcedureError`` is bgneal@68: raised. bgneal@68: bgneal@68: ``StdProcedure`` objects have the following methods: bgneal@68: bgneal@68: .. method:: get_key_list() bgneal@68: bgneal@68: :returns: the currently installed :class:`~m209.keylist.KeyList` object bgneal@68: or ``None`` if one has not been set bgneal@68: bgneal@68: .. method:: set_key_list(key_list) bgneal@68: bgneal@68: Establishes the :class:`~m209.keylist.KeyList` to be used for future bgneal@68: :meth:`encrypt` and :meth:`decrypt` operations bgneal@68: bgneal@68: :param key_list: the new :class:`~m209.keylist.KeyList` to use bgneal@68: bgneal@68: .. method:: encrypt(plaintext[, spaces=True[, ext_msg_ind=None[, sys_ind=None]]]) bgneal@68: :noindex: bgneal@68: bgneal@68: Encrypts a plaintext message using the installed bgneal@68: :class:`~m209.keylist.KeyList` and by following the standard procedure. bgneal@68: The encrypted text with the required message indicators are returned as bgneal@68: a string. bgneal@68: bgneal@68: :param plaintext: the input string to be encrypted bgneal@68: :param spaces: if ``True``, space characters in the input plaintext are bgneal@68: allowed and will be replaced with ``Z`` characters before encrypting bgneal@68: :param ext_msg_ind: this is the external message indicator, which, if bgneal@68: supplied, must be a valid 6-letter string of key wheel settings. If not bgneal@68: supplied, one will be generated randomly. bgneal@68: :param sys_ind: this is the system indicator, which must be a string of length bgneal@68: 1 in the range ``A`` - ``Z``, inclusive. If ``None``, one is chosen at random. bgneal@68: :returns: the encrypted text with the required message indicators bgneal@68: :raises ProcedureError: if the procedure does not have bgneal@68: a :class:`~m209.keylist.KeyList` or the input indicators are invalid bgneal@68: bgneal@68: .. method:: set_decrypt_message(msg) bgneal@68: bgneal@68: Prepare to decrypt the supplied message. bgneal@68: bgneal@68: :param msg: the messsage to decrypt. The message can be grouped into bgneal@68: 5-letter groups separated by spaces or accepted without spaces. bgneal@68: :returns: a ``DecryptParams`` named tuple to the caller (see below) bgneal@68: bgneal@68: The ``DecryptParams`` named tuple has the following attributes: bgneal@68: bgneal@68: * ``sys_ind`` - the system indicator bgneal@68: * ``ext_msg_ind`` - the external message indicator bgneal@68: * ``key_list_ind`` - the key list indicator bgneal@68: * ``ciphertext`` - the cipher text with all indicators removed bgneal@68: bgneal@68: The caller should ensure the procedure instance has the required bgneal@68: :class:`~m209.keylist.KeyList` before calling :meth:`decrypt`. The bgneal@68: ``key_list_ind`` attribute of the returned ``DecryptParams`` named tuple bgneal@68: identifies the key list that should be installed with bgneal@68: :meth:`set_key_list`. bgneal@68: bgneal@68: .. method:: decrypt() bgneal@68: :noindex: bgneal@68: bgneal@68: Decrypt the message set in a previous :meth:`set_decrypt_message` call. The bgneal@68: resulting plaintext is returned as a string. bgneal@68: bgneal@68: :returns: the decrypted plaintext as a string bgneal@68: :raises ProcedureError: if the procedure instance has not been bgneal@68: previously configured with the required :class:`~m209.keylist.KeyList` bgneal@68: via :meth:`set_key_list` bgneal@68: bgneal@68: Here is a simple interactive example of performing an encrypt operation. Here bgneal@68: we choose a random key list from our key list file, and use random indicators: bgneal@68: bgneal@68: >>> from m209.keylist.config import read_key_list bgneal@68: >>> from m209.procedure import StdProcedure bgneal@68: >>> bgneal@68: >>> key_list = read_key_list('m209keys.cfg') bgneal@68: >>> proc = StdProcedure(key_list=key_list) bgneal@68: >>> ct = proc.encrypt('ORDER THE PIZZA AT TWELVE HUNDRED HOURS') bgneal@68: >>> ct bgneal@68: 'YYGBM ENNHT VBMTJ PEEFV JWLUU PAFTS VOHEA QEPEQ OKVUA XDAUX YYGBM ENNHT' bgneal@68: >>> bgneal@68: bgneal@68: The first and last two groups of this message contain the indicators. Here we bgneal@68: can see the system indicator was ``Y``, the external message indicator is bgneal@68: ``GBMENN``, and the key list indicator is ``HT``. bgneal@68: bgneal@68: An example session for decrypting the above message might look like: bgneal@68: bgneal@68: >>> proc = StdProcedure() bgneal@68: >>> ct = 'YYGBM ENNHT VBMTJ PEEFV JWLUU PAFTS VOHEA QEPEQ OKVUA XDAUX YYGBM ENNHT' bgneal@68: >>> params = proc.set_decrypt_message(ct) bgneal@68: >>> params bgneal@68: DecryptParams(sys_ind='Y', ext_msg_ind='GBMENN', key_list_ind='HT', ciphertext='VBMTJ PEEFV JWLUU PAFTS VOHEA QEPEQ OKVUA XDAUX') bgneal@68: >>> key_list = read_key_list('m209keys.cfg', params.key_list_ind) bgneal@68: >>> proc.set_key_list(key_list) bgneal@68: >>> pt = proc.decrypt() bgneal@68: >>> pt bgneal@68: 'ORDER THE PI A AT TWELVE HUNDRED HOURS ' bgneal@68: >>> bgneal@68: