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