Copied updated slides across
[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 .indexlink {
41 position: absolute;
42 bottom: 1em;
43 left: 1em;
44 }
45 .float-right {
46 float: right;
47 }
48 </style>
49 </head>
50 <body>
51 <textarea id="source">
52
53 # Keyword ciphers
54
55 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
56 --|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--
57 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
58
59 * Taking a more Pythonic approach
60
61 ---
62
63 layout: true
64
65 .indexlink[[Index](index.html)]
66
67 ---
68
69 # The cipher
70
71 * Still character-by-character substitution, still monosubstitution.
72
73 Ciphertext alphabet: start with a keyword, write out the rest of the alphabet, removing duplicates.
74
75 ## Three variants
76
77 Write out the rest of the alphabet...
78
79 1. ...starting from 'a' (keywordabcf...)
80 2. ...starting from the last letter of the keyword (keywordfgh...)
81 3. ...starting from the largest letter of the keyword (keywordzabc...)
82
83 ---
84
85 # A more Pythonic way
86
87 _string_`.translate()` and _string_`.maketrans()`
88
89 * Make the 'ciphertext' alphabet, relate to the 'plaintext' alphabet (`string.ascii_lowercase`)
90 * Use those to make the translation table
91 * Enciphering is simply applying `plaintext.translate(enciphering_table)`
92 * Deciphering just uses a different table
93
94 ---
95
96 # Making the cipher alphabet from a keyword
97
98 Three challenges:
99
100 1. How to say which type of cipher alphabet to use
101 2. Where to start the rest of the alphabet
102 3. Removing duplicate letters
103
104 Solutions:
105
106 1. Keyword arguments for procedures
107 2. sort and slices
108 3. Use something like an ordered set
109
110 Both enciphering and deciphering need the same keyword-based alphabet, so pull this out into another procedure.
111
112 ---
113
114 # Keyword arguments
115
116 Used to:
117
118 1. give a default value for a parameter
119 2. allow parameters to be named (not just positional)
120
121 Give our `keyword_encipher` and `keyword_decipher` procedures a keyword parameter of `wrap_alphabet`.
122
123 Pass this parameter to the `keyword_alphabet` procedure.
124
125 ## wrap_alphabet has no inherent meaning
126 Use Python 3.4's `Enum`
127 ```python
128 from enum import Enum
129
130 class KeywordWrapAlphabet(Enum):
131 from_a = 1
132 from_last = 2
133 from_largest = 3
134 ```
135
136 (Use integers in earlier Pythons)
137 ---
138
139 # Deduplicating a sequence
140
141 We need
142
143 * Something set-like
144 * Something ordered
145
146 No ordered set in Python, but do have an ordered dict.
147
148 * Keys of a dict are a set.
149 * Keys in an ordered dict retain their order (subsequent instances are ignored)
150
151 `deduplicated_list = list(collections.OrderedDict.fromkeys(list))`
152
153 ---
154
155 # Sorts and slices
156
157 ## Recap
158 Write out the rest of the alphabet...
159
160 1. ...starting from 'a' (keywordabcf...)
161 2. ...starting from the last letter of the keyword (keywordfgh...)
162 3. ...starting from the largest letter of the keyword (keywordzabc...)
163
164 * Santitise the keyword before we use it
165
166 ---
167 # Making the keyword alphabet
168
169 ## Cases
170 1. As we're deduplicating anyway, just add the entire alphabet to the end of the keyword, then deduplicate.
171 `deduplicate(keyword + string.ascii_lowercase)`
172
173 2. and 3. How to find the appropriate letter of the keyword.
174
175 `deduplicate(keyword + string_ascii_lowercase[from:] + string.ascii_lowercase)`
176
177 Question: why not take a slice of the second alphabet copy?
178
179 Question: what do we use as the last letter of 'character'? 'r' or 'e'?
180
181 `sorted()` will put a string in lexicographical order.
182 `.find()` will find an item in a sequence
183
184 ---
185
186 # Keyword enciphering
187
188 Now we've got the keyword-based cipher alphabet, simply use `.translate()` to do the enciphering/deciphering.
189
190 Use `''.maketrans()` to make the translation table.
191
192 Sorted!
193
194 Does it pass the tests?
195
196 </textarea>
197 <script src="http://gnab.github.io/remark/downloads/remark-0.6.0.min.js" type="text/javascript">
198 </script>
199
200 <script type="text/javascript"
201 src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&delayStartupUntil=configured"></script>
202
203 <script type="text/javascript">
204 var slideshow = remark.create({ ratio: "16:9" });
205
206 // Setup MathJax
207 MathJax.Hub.Config({
208 tex2jax: {
209 skipTags: ['script', 'noscript', 'style', 'textarea', 'pre']
210 }
211 });
212 MathJax.Hub.Queue(function() {
213 $(MathJax.Hub.getAllJax()).map(function(index, elem) {
214 return(elem.SourceElement());
215 }).parent().addClass('has-jax');
216 });
217 MathJax.Hub.Configured();
218 </script>
219 </body>
220 </html>