changeset 15:672ba8b2269f

Added encrypt() and test.
author Brian Neal <bgneal@gmail.com>
date Mon, 02 Dec 2013 20:58:36 -0600
parents eea5734a1655
children adaca0a6b2b4
files purple/machine.py purple/tests/test_machine.py
diffstat 2 files changed, 78 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/purple/machine.py	Mon Dec 02 20:44:26 2013 -0600
+++ b/purple/machine.py	Mon Dec 02 20:58:36 2013 -0600
@@ -206,6 +206,38 @@
 
         return ''.join(plaintext)
 
+    def encrypt(self, plaintext):
+        """Encrypts the given plaintext message and returns the ciphertext
+        output.
+
+        plaintext must contain only the letters A-Z or else a Purple97Error
+        exception is raised.
+
+        """
+        ciphertext = []
+        for c in plaintext:
+            if c not in self.VALID_KEYS:
+                raise Purple97Error("invalid input '{}' to encrypt".format(c))
+
+            n = self.plugboard[c]
+            if n < 6:
+                # This input goes to the sixes switch
+                x = self.sixes.encrypt(n)
+            else:
+                # This input goes to the chain of twenties switches in reverse
+                # order compared to decrypt.
+                n -= 6
+                x = self.twenties[2].encrypt(self.twenties[1].encrypt(
+                        self.twenties[0].encrypt(n)))
+                x += 6
+
+            ciphertext.append(self.alphabet[x])
+
+            # Now step the switches.
+            self.step()
+
+        return ''.join(ciphertext)
+
     def step(self):
         """Step the stepping switches."""
         # First read the sixes and middle switch
--- a/purple/tests/test_machine.py	Mon Dec 02 20:44:26 2013 -0600
+++ b/purple/tests/test_machine.py	Mon Dec 02 20:58:36 2013 -0600
@@ -9,6 +9,25 @@
 from purple.switch import SteppingSwitchError
 
 
+# The ciphertext contains garbles, indicated by '-' chars.
+ciphertext = (
+    "ZTXODNWKCCMAVNZXYWEETUQTCIMN"
+    "VEUVIWBLUAXRRTLVARGNTPCNOIUP"
+    "JLCIVRTPJKAUHVMUDTHKTXYZELQTVWGBUHFAWSHU"
+    "LBFBHEXMYHFLOWD-KWHKKNXEBVPYHHGHEKXIOHQ"
+    "HUHWIKYJYHPPFEALNNAKIBOOZNFRLQCFLJTTSSDDOIOCVT-"
+    "ZCKQTSHXTIJCNWXOKUFNQR-TAOIHWTATWV"
+)
+
+plaintext = (
+    "FOVTATAKIDASINIMUIMINOMOXIWO"
+    "IRUBESIFYXXFCKZZRDXOOVBTNFYX"
+    "FAEMEMORANDUMFIOFOVOOMOJIBAKARIFYXRAICCY"
+    "LFCBBCFCTHEGOVE-NMENTOFJAPANLFLPROMPTED"
+    "BYAGENUINEDESIRETOCOMETOANAMICABLEUNDERSTANDIN-"
+    "WITHTHEGOVERNMENTOFTHE-NITEDSTATES"
+)
+
 class Purple97TestCase(unittest.TestCase):
 
     def test_construction(self):
@@ -92,31 +111,11 @@
         self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-1a')
         self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-123')
 
-    def test_first_part_of_14_part_message(self):
-
-        # The ciphertext contains garbles, indicated by '-' chars.
-        ciphertext = (
-            "ZTXODNWKCCMAVNZXYWEETUQTCIMN"
-            "VEUVIWBLUAXRRTLVARGNTPCNOIUP"
-            "JLCIVRTPJKAUHVMUDTHKTXYZELQTVWGBUHFAWSHU"
-            "LBFBHEXMYHFLOWD-KWHKKNXEBVPYHHGHEKXIOHQ"
-            "HUHWIKYJYHPPFEALNNAKIBOOZNFRLQCFLJTTSSDDOIOCVT-"
-            "ZCKQTSHXTIJCNWXOKUFNQR-TAOIHWTATWV"
-        )
-
-        self.assertEqual(216, len(ciphertext))
+    def test_decrypt_first_part_of_14_part_message(self):
 
         # Use 'X' in place of the garbles
         input_text = ciphertext.replace('-', 'X')
 
-        plaintext = (
-            "FOVTATAKIDASINIMUIMINOMOXIWO"
-            "IRUBESIFYXXFCKZZRDXOOVBTNFYX"
-            "FAEMEMORANDUMFIOFOVOOMOJIBAKARIFYXRAICCY"
-            "LFCBBCFCTHEGOVE-NMENTOFJAPANLFLPROMPTED"
-            "BYAGENUINEDESIRETOCOMETOANAMICABLEUNDERSTANDIN-"
-            "WITHTHEGOVERNMENTOFTHE-NITEDSTATES"
-        )
         self.assertEqual(len(ciphertext), len(plaintext))
 
         # Decrypt
@@ -137,3 +136,29 @@
                     mismatches)
 
         self.assertTrue(len(mismatches) == 0, msg)
+
+    def test_encrypt_first_part_of_14_part_message(self):
+
+        # Use 'X' in place of the garbles
+        input_text = plaintext.replace('-', 'X')
+
+        self.assertEqual(len(ciphertext), len(plaintext))
+
+        # Encrypt
+        purple = Purple97.from_key_sheet(
+                switches='9-1,24,6-23',
+                alphabet='NOKTYUXEQLHBRMPDICJASVWGZF')
+
+        actual = purple.encrypt(input_text)
+
+        mismatches = []
+        for n, (a, b) in enumerate(zip(ciphertext, actual)):
+            if a != b and a != '-':
+                mismatches.append(n)
+
+        msg = None
+        if mismatches:
+            msg = "There are {} mismatches: {}".format(len(mismatches),
+                    mismatches)
+
+        self.assertTrue(len(mismatches) == 0, msg)