bb9e679775b9163bd9b19f9e636d3ee6fc1d3262
[cipher-training.git] / slides / keyword-encipher.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Keyword ciphers</title>
5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
6 <style type="text/css">
7 /* Slideshow styles */
8 body {
9 font-size: 20px;
10 }
11 h1, h2, h3 {
12 font-weight: 400;
13 margin-bottom: 0;
14 }
15 h1 { font-size: 3em; }
16 h2 { font-size: 2em; }
17 h3 { font-size: 1.6em; }
18 a, a > code {
19 text-decoration: none;
20 }
21 code {
22 -moz-border-radius: 5px;
23 -web-border-radius: 5px;
24 background: #e7e8e2;
25 border-radius: 5px;
26 font-size: 16px;
27 }
28 .plaintext {
29 background: #272822;
30 color: #80ff80;
31 text-shadow: 0 0 20px #333;
32 padding: 2px 5px;
33 }
34 .ciphertext {
35 background: #272822;
36 color: #ff6666;
37 text-shadow: 0 0 20px #333;
38 padding: 2px 5px;
39 }
40 .float-right {
41 float: right;
42 }
43 </style>
44 </head>
45 <body>
46 <textarea id="source">
47
48 # Keyword ciphers
49
50 a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z
51 --|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--
52 k | e | y | w | o | r | d | a | b | c | f | g | h | i | j | l | m | n | p | q | s | t | u | v | x | z
53
54 * Taking a more Pythonic approach
55
56 ---
57
58 # The cipher
59
60 * Still character-by-character substitution, still monosubstitution.
61
62 Ciphertext alphabet: start with a keyword, write out the rest of the alphabet, removing duplicates.
63
64 ## Three variants
65
66 Write out the rest of the alphabet...
67
68 1. ...starting from 'a' (keywordabcf...)
69 2. ...starting from the last letter of the keyword (keywordfgh...)
70 3. ...starting from the largest letter of the keyword (keywordzabc...)
71
72 ---
73
74 # A more Pythonic way
75
76 _string_`.translate()` and _string_`.maketrans()`
77
78 * Make the 'ciphertext' alphabet, relate to the 'plaintext' alphabet (`string.ascii_lowercase`)
79 * Use those to make the translation table
80 * Enciphering is simply applying `plaintext.translate(enciphering_table)`
81 * Deciphering just uses a different table
82
83 ---
84
85 # Making the cipher alphabet from a keyword
86
87 Three challenges:
88
89 1. How to say which type of cipher alphabet to use
90 2. Where to start the rest of the alphabet
91 3. Removing duplicate letters
92
93 Solutions:
94
95 1. Keyword arguments for procedures
96 2. sort and slices
97 3. Use something like an ordered set
98
99 Both enciphering and deciphering need the same keyword-based alphabet, so pull this out into another procedure.
100
101 ---
102
103 # Keyword arguments
104
105 Used to:
106
107 1. give a default value for a parameter
108 2. allow parameters to be named (not just positional)
109
110 Give our `keyword_encipher` and `keyword_decipher` procedures a keyword parameter of `wrap_alphabet`.
111
112 Pass this parameter to the `keyword_alphabet` procedure.
113
114 ## wrap_alphabet has no inherent meaning
115 Use Python 3.4's `Enum`
116 ```python
117 from enum import Enum
118
119 class Keyword_wrap_alphabet(Enum):
120 from_a = 1
121 from_last = 2
122 from_largest = 3
123 ```
124
125 (Use integers in earlier Pythons)
126 ---
127
128 # Deduplicating a sequence
129
130 We need
131
132 * Something set-like
133 * Something ordered
134
135 No ordered set in Python, but do have an ordered dict.
136
137 * Keys of a dict are a set.
138 * Keys in an ordered dict retain their order (subsequent instances are ignored)
139
140 `deduplicated_list = list(collections.OrderedDict.fromkeys(list))`
141
142 ---
143
144 # Sorts and slices
145
146 ## Recap
147 Write out the rest of the alphabet...
148
149 1. ...starting from 'a' (keywordabcf...)
150 2. ...starting from the last letter of the keyword (keywordfgh...)
151 3. ...starting from the largest letter of the keyword (keywordzabc...)
152
153 * Santitise the keyword before we use it
154
155 ---
156 # Making the keyword alphabet
157
158 ## Cases
159 1. As we're deduplicating anyway, just add the entire alphabet to the end of the keyword, then deduplicate.
160 `deduplicate(keyword + string.ascii_lowercase)`
161
162 2. and 3. How to find the appropriate letter of the keyword.
163
164 Indexing pulls out letters. `'keyword'[0]` = 'k' ; `'keyword'[3]` = 'w' ; `'keyword'[-1]` = 'd'
165
166 Slices pulls out substrings. `'keyword'[1:4]` = 'eyw' ; `'keyword'[:3]` = 'key' ; `'keyword'[5:]` = 'rd'
167
168 `deduplicate(keyword + string_ascii_lowercase[from:] + string.ascii_lowercase)`
169
170 Question: why not take a slice of the second alphabet copy?
171
172 Question: what do we use as the last letter of 'character'? 'r' or 'e'?
173
174 `sorted()` will put a string in lexicographical order.
175 `.find()` will find an item in a sequence
176
177 ---
178
179 # Keyword enciphering
180
181 Now we've got the keyword-based cipher alphabet, simply use `.translate()` to do the enciphering/deciphering.
182
183 Use `''.maketrans()` to make the translation table.
184
185 Sorted!
186
187 Does it pass the tests?
188
189 </textarea>
190 <script src="http://gnab.github.io/remark/downloads/remark-0.6.0.min.js" type="text/javascript">
191 </script>
192
193 <script type="text/javascript"
194 src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&delayStartupUntil=configured"></script>
195
196 <script type="text/javascript">
197 var slideshow = remark.create({ ratio: "16:9" });
198
199 // Setup MathJax
200 MathJax.Hub.Config({
201 tex2jax: {
202 skipTags: ['script', 'noscript', 'style', 'textarea', 'pre']
203 }
204 });
205 MathJax.Hub.Queue(function() {
206 $(MathJax.Hub.getAllJax()).map(function(index, elem) {
207 return(elem.SourceElement());
208 }).parent().addClass('has-jax');
209 });
210 MathJax.Hub.Configured();
211 </script>
212 </body>
213 </html>