Added stream cipher
[computing-unplugged-book.git] / stream-cipher.ipynb
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 5,
6 "metadata": {
7 "collapsed": true
8 },
9 "outputs": [],
10 "source": [
11 "import string"
12 ]
13 },
14 {
15 "cell_type": "code",
16 "execution_count": 40,
17 "metadata": {
18 "collapsed": true
19 },
20 "outputs": [],
21 "source": [
22 "def sanitised(text):\n",
23 " return ''.join(letter.lower() for letter in text if letter in string.ascii_letters)"
24 ]
25 },
26 {
27 "cell_type": "code",
28 "execution_count": 41,
29 "metadata": {
30 "collapsed": false
31 },
32 "outputs": [
33 {
34 "data": {
35 "text/plain": [
36 "'thequickbrownfoxjumpedoverthelzydoga'"
37 ]
38 },
39 "execution_count": 41,
40 "metadata": {},
41 "output_type": "execute_result"
42 }
43 ],
44 "source": [
45 "sanitised('The quick brown fox! jumped OVER the l\\a!z%y* dog....a')"
46 ]
47 },
48 {
49 "cell_type": "code",
50 "execution_count": 2,
51 "metadata": {
52 "collapsed": false
53 },
54 "outputs": [],
55 "source": [
56 "def encipher_letter(previous, current):\n",
57 " new = (ord(previous) + ord(current) - 2 * ord('a')) % 26\n",
58 " return chr(new + ord('a'))"
59 ]
60 },
61 {
62 "cell_type": "code",
63 "execution_count": 15,
64 "metadata": {
65 "collapsed": true
66 },
67 "outputs": [],
68 "source": [
69 "def decipher_letter(previous, current):\n",
70 " new = (ord(current) - ord(previous) - 2 * ord('a')) % 26\n",
71 " return chr(new + ord('a'))"
72 ]
73 },
74 {
75 "cell_type": "code",
76 "execution_count": 4,
77 "metadata": {
78 "collapsed": false
79 },
80 "outputs": [
81 {
82 "data": {
83 "text/plain": [
84 "'a'"
85 ]
86 },
87 "execution_count": 4,
88 "metadata": {},
89 "output_type": "execute_result"
90 }
91 ],
92 "source": [
93 "encipher_letter('a', 'a')"
94 ]
95 },
96 {
97 "cell_type": "code",
98 "execution_count": 6,
99 "metadata": {
100 "collapsed": false
101 },
102 "outputs": [
103 {
104 "data": {
105 "text/plain": [
106 "'abcdefghijklmnopqrstuvwxyz'"
107 ]
108 },
109 "execution_count": 6,
110 "metadata": {},
111 "output_type": "execute_result"
112 }
113 ],
114 "source": [
115 "''.join(encipher_letter('a', l) for l in string.ascii_lowercase)"
116 ]
117 },
118 {
119 "cell_type": "code",
120 "execution_count": 7,
121 "metadata": {
122 "collapsed": false
123 },
124 "outputs": [
125 {
126 "data": {
127 "text/plain": [
128 "'bcdefghijklmnopqrstuvwxyza'"
129 ]
130 },
131 "execution_count": 7,
132 "metadata": {},
133 "output_type": "execute_result"
134 }
135 ],
136 "source": [
137 "''.join(encipher_letter('b', l) for l in string.ascii_lowercase)"
138 ]
139 },
140 {
141 "cell_type": "code",
142 "execution_count": 17,
143 "metadata": {
144 "collapsed": false
145 },
146 "outputs": [
147 {
148 "data": {
149 "text/plain": [
150 "'abcdefghijklmnopqrstuvwxyz'"
151 ]
152 },
153 "execution_count": 17,
154 "metadata": {},
155 "output_type": "execute_result"
156 }
157 ],
158 "source": [
159 "''.join(decipher_letter('a', l) for l in string.ascii_lowercase)"
160 ]
161 },
162 {
163 "cell_type": "code",
164 "execution_count": 18,
165 "metadata": {
166 "collapsed": false
167 },
168 "outputs": [
169 {
170 "data": {
171 "text/plain": [
172 "'b'"
173 ]
174 },
175 "execution_count": 18,
176 "metadata": {},
177 "output_type": "execute_result"
178 }
179 ],
180 "source": [
181 "decipher_letter('a', 'b')"
182 ]
183 },
184 {
185 "cell_type": "markdown",
186 "metadata": {},
187 "source": [
188 "e = (p + c) % 26\n",
189 "c = e - p"
190 ]
191 },
192 {
193 "cell_type": "code",
194 "execution_count": 20,
195 "metadata": {
196 "collapsed": false
197 },
198 "outputs": [
199 {
200 "data": {
201 "text/plain": [
202 "'abcdefghijklmnopqrstuvwxyzbcdefghijklmnopqrstuvwxyzacdefghijklmnopqrstuvwxyzabdefghijklmnopqrstuvwxyzabcefghijklmnopqrstuvwxyzabcdfghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdefhijklmnopqrstuvwxyzabcdefgijklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghiklmnopqrstuvwxyzabcdefghijlmnopqrstuvwxyzabcdefghijkmnopqrstuvwxyzabcdefghijklnopqrstuvwxyzabcdefghijklmopqrstuvwxyzabcdefghijklmnpqrstuvwxyzabcdefghijklmnoqrstuvwxyzabcdefghijklmnoprstuvwxyzabcdefghijklmnopqstuvwxyzabcdefghijklmnopqrtuvwxyzabcdefghijklmnopqrsuvwxyzabcdefghijklmnopqrstvwxyzabcdefghijklmnopqrstuwxyzabcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvwyzabcdefghijklmnopqrstuvwxzabcdefghijklmnopqrstuvwxy'"
203 ]
204 },
205 "execution_count": 20,
206 "metadata": {},
207 "output_type": "execute_result"
208 }
209 ],
210 "source": [
211 "''.join(encipher_letter(k, l) for l in string.ascii_lowercase for k in string.ascii_lowercase)"
212 ]
213 },
214 {
215 "cell_type": "code",
216 "execution_count": 21,
217 "metadata": {
218 "collapsed": false
219 },
220 "outputs": [
221 {
222 "data": {
223 "text/plain": [
224 "[('a', 'a', 'a'),\n",
225 " ('b', 'a', 'b'),\n",
226 " ('c', 'a', 'c'),\n",
227 " ('d', 'a', 'd'),\n",
228 " ('e', 'a', 'e'),\n",
229 " ('f', 'a', 'f'),\n",
230 " ('g', 'a', 'g'),\n",
231 " ('h', 'a', 'h'),\n",
232 " ('i', 'a', 'i'),\n",
233 " ('j', 'a', 'j')]"
234 ]
235 },
236 "execution_count": 21,
237 "metadata": {},
238 "output_type": "execute_result"
239 }
240 ],
241 "source": [
242 "encrypted = [(k, l, encipher_letter(k, l)) for l in string.ascii_lowercase for k in string.ascii_lowercase]\n",
243 "encrypted[:10]"
244 ]
245 },
246 {
247 "cell_type": "code",
248 "execution_count": 22,
249 "metadata": {
250 "collapsed": false
251 },
252 "outputs": [
253 {
254 "data": {
255 "text/plain": [
256 "True"
257 ]
258 },
259 "execution_count": 22,
260 "metadata": {},
261 "output_type": "execute_result"
262 }
263 ],
264 "source": [
265 "all(l == decipher_letter(k, e) for k, l, e in encrypted)"
266 ]
267 },
268 {
269 "cell_type": "code",
270 "execution_count": 55,
271 "metadata": {
272 "collapsed": true
273 },
274 "outputs": [],
275 "source": [
276 "def encipher_message(plaintext, key='a'):\n",
277 " ciphertext = ''\n",
278 " previous = key\n",
279 " for letter in plaintext:\n",
280 " cipherletter = encipher_letter(previous, letter)\n",
281 " ciphertext += cipherletter\n",
282 " previous = cipherletter\n",
283 " # previous = letter\n",
284 " return ciphertext"
285 ]
286 },
287 {
288 "cell_type": "code",
289 "execution_count": 56,
290 "metadata": {
291 "collapsed": false
292 },
293 "outputs": [
294 {
295 "data": {
296 "text/plain": [
297 "'hlwhv'"
298 ]
299 },
300 "execution_count": 56,
301 "metadata": {},
302 "output_type": "execute_result"
303 }
304 ],
305 "source": [
306 "encipher_message('hello')"
307 ]
308 },
309 {
310 "cell_type": "code",
311 "execution_count": 57,
312 "metadata": {
313 "collapsed": false
314 },
315 "outputs": [
316 {
317 "data": {
318 "text/plain": [
319 "'xbmxl'"
320 ]
321 },
322 "execution_count": 57,
323 "metadata": {},
324 "output_type": "execute_result"
325 }
326 ],
327 "source": [
328 "encipher_message('hello', 'q')"
329 ]
330 },
331 {
332 "cell_type": "code",
333 "execution_count": 54,
334 "metadata": {
335 "collapsed": true
336 },
337 "outputs": [],
338 "source": [
339 "def decipher_message(ciphertext, key='a'):\n",
340 " plaintext = ''\n",
341 " previous = key\n",
342 " for letter in ciphertext:\n",
343 " plainletter = decipher_letter(previous, letter)\n",
344 " plaintext += plainletter\n",
345 " previous = letter\n",
346 " # previous = plainletter\n",
347 " return plaintext"
348 ]
349 },
350 {
351 "cell_type": "code",
352 "execution_count": 58,
353 "metadata": {
354 "collapsed": false
355 },
356 "outputs": [
357 {
358 "data": {
359 "text/plain": [
360 "'hello'"
361 ]
362 },
363 "execution_count": 58,
364 "metadata": {},
365 "output_type": "execute_result"
366 }
367 ],
368 "source": [
369 "decipher_message('hlwhv')"
370 ]
371 },
372 {
373 "cell_type": "code",
374 "execution_count": 59,
375 "metadata": {
376 "collapsed": false
377 },
378 "outputs": [
379 {
380 "data": {
381 "text/plain": [
382 "'xello'"
383 ]
384 },
385 "execution_count": 59,
386 "metadata": {},
387 "output_type": "execute_result"
388 }
389 ],
390 "source": [
391 "decipher_message('xbmxl')"
392 ]
393 },
394 {
395 "cell_type": "code",
396 "execution_count": 60,
397 "metadata": {
398 "collapsed": false
399 },
400 "outputs": [
401 {
402 "data": {
403 "text/plain": [
404 "'hello'"
405 ]
406 },
407 "execution_count": 60,
408 "metadata": {},
409 "output_type": "execute_result"
410 }
411 ],
412 "source": [
413 "decipher_message('xbmxl', 'q')"
414 ]
415 },
416 {
417 "cell_type": "code",
418 "execution_count": 61,
419 "metadata": {
420 "collapsed": false
421 },
422 "outputs": [
423 {
424 "data": {
425 "text/plain": [
426 "'hlwhvjxlznbpdrfthvjxlznbpd'"
427 ]
428 },
429 "execution_count": 61,
430 "metadata": {},
431 "output_type": "execute_result"
432 }
433 ],
434 "source": [
435 "encipher_message('helloooooooooooooooooooooo')"
436 ]
437 },
438 {
439 "cell_type": "code",
440 "execution_count": 62,
441 "metadata": {
442 "collapsed": false
443 },
444 "outputs": [
445 {
446 "data": {
447 "text/plain": [
448 "'helloooooooooooooooooooooo'"
449 ]
450 },
451 "execution_count": 62,
452 "metadata": {},
453 "output_type": "execute_result"
454 }
455 ],
456 "source": [
457 "decipher_message('hlwhvjxlznbpdrfthvjxlznbpd')"
458 ]
459 },
460 {
461 "cell_type": "code",
462 "execution_count": null,
463 "metadata": {
464 "collapsed": true
465 },
466 "outputs": [],
467 "source": []
468 }
469 ],
470 "metadata": {
471 "kernelspec": {
472 "display_name": "Python 3",
473 "language": "python",
474 "name": "python3"
475 },
476 "language_info": {
477 "codemirror_mode": {
478 "name": "ipython",
479 "version": 3
480 },
481 "file_extension": ".py",
482 "mimetype": "text/x-python",
483 "name": "python",
484 "nbconvert_exporter": "python",
485 "pygments_lexer": "ipython3",
486 "version": "3.4.2"
487 }
488 },
489 "nbformat": 4,
490 "nbformat_minor": 0
491 }