Breaking hill ciphers done, challenge 6 done.
[cipher-tools.git] / hill-ciphers.ipynb
1 {
2 "metadata": {
3 "name": "",
4 "signature": "sha256:112d1c84c318592f927e18c5b0f15ed60ac8418ca15cb79596ba6212ff2d7e3f"
5 },
6 "nbformat": 3,
7 "nbformat_minor": 0,
8 "worksheets": [
9 {
10 "cells": [
11 {
12 "cell_type": "code",
13 "collapsed": false,
14 "input": [
15 "import matplotlib.pyplot as plt\n",
16 "import pandas as pd\n",
17 "import collections\n",
18 "import string\n",
19 "import numpy as np\n",
20 "from numpy import matrix\n",
21 "from numpy import linalg\n",
22 "%matplotlib inline\n",
23 "\n",
24 "from cipher import *\n",
25 "from cipherbreak import *\n",
26 "\n",
27 "c6a = open('2014/6a.ciphertext').read()\n",
28 "c6b = open('2014/6b.ciphertext').read()"
29 ],
30 "language": "python",
31 "metadata": {},
32 "outputs": [],
33 "prompt_number": 54
34 },
35 {
36 "cell_type": "code",
37 "collapsed": false,
38 "input": [
39 "key_a, score = railfence_break(sanitise(c6a))\n",
40 "key_a, score"
41 ],
42 "language": "python",
43 "metadata": {},
44 "outputs": [
45 {
46 "metadata": {},
47 "output_type": "pyout",
48 "prompt_number": 3,
49 "text": [
50 "(3, -2314.997881051078)"
51 ]
52 }
53 ],
54 "prompt_number": 3
55 },
56 {
57 "cell_type": "code",
58 "collapsed": false,
59 "input": [
60 "' '.join(segment(railfence_decipher(sanitise(c6a), key_a)))"
61 ],
62 "language": "python",
63 "metadata": {},
64 "outputs": [
65 {
66 "metadata": {},
67 "output_type": "pyout",
68 "prompt_number": 4,
69 "text": [
70 "'mark the last message told usa lot the scuttling equipment is designed to pump water in and out of the vessel like a submarine dive control but clearly they werent planning to turn a container ship into a sub this ship is a largescale version of something i have seen in the caribbean drug runners use a similar technique to get below radar coverage for inshore runs sinking the vessel so that the deck remains just below the wave tops the fda pirates seem more interested in staying away from shore but getting close enough to track and record electronic communications without detection i am guessing this scuttling system is what they call nautilus in their log but i am still baffled by the references to seahorse the next page of the log looks harder to crack but the cipher clerk tells me it is a hill cipher and that they must have been in a hurry or have been enciphering by hand since they just used a two by two matrix actually we have been pretty lax with our security and i think the next message is end will use avi genere cipher given that we are using secure cables i dont think we have too much to worry about so i will keep the keyword short say three characters more later harry'"
71 ]
72 }
73 ],
74 "prompt_number": 4
75 },
76 {
77 "cell_type": "code",
78 "collapsed": false,
79 "input": [
80 "c6bs = sanitise(c6b)\n",
81 "c6bs"
82 ],
83 "language": "python",
84 "metadata": {},
85 "outputs": [
86 {
87 "metadata": {},
88 "output_type": "pyout",
89 "prompt_number": 7,
90 "text": [
91 "'hwssswxfewhhrfewpdrvttdhxbccleayphalnadhiehaoudrotwnrrvysabjlttbaytmelrkaidopthatlelrtwaamaneksvvzrvllatkcrjquicizgtoqcpnrrkttowandqehtqrvtbaydqealannohulanuzlwextlvjrvivhnohdqmgykaclmswrupdetfioftfelhzpxhaswftwprrsweiseohefpdrvttnvagdvswgoerbetnharvaeevtlltbmgaiatgelinmdawevhatterdhrznbnvoutnefoteveaehlaymhacglzeptvvdimworfisgtuzlwibeqohubtghamqornjnnrumqvjtxeltfovgawdaeevllgrtxibgtibevmpsaateoasevaeyqohameonncfuidoefafattemuimnflznbekofobrliaehhauihnnnwzaeevtlltpaalnanvtzlzuucptaelinanpaahewfthaosetaribnbnvhaevdhyytlmuxb'"
92 ]
93 }
94 ],
95 "prompt_number": 7
96 },
97 {
98 "cell_type": "code",
99 "collapsed": false,
100 "input": [
101 "c6b_nums = [ord(c) - ord('a') for c in c6bs]\n",
102 "c6b_nums"
103 ],
104 "language": "python",
105 "metadata": {},
106 "outputs": [
107 {
108 "metadata": {},
109 "output_type": "pyout",
110 "prompt_number": 17,
111 "text": [
112 "[7,\n",
113 " 22,\n",
114 " 18,\n",
115 " 18,\n",
116 " 18,\n",
117 " 22,\n",
118 " 23,\n",
119 " 5,\n",
120 " 4,\n",
121 " 22,\n",
122 " 7,\n",
123 " 7,\n",
124 " 17,\n",
125 " 5,\n",
126 " 4,\n",
127 " 22,\n",
128 " 15,\n",
129 " 3,\n",
130 " 17,\n",
131 " 21,\n",
132 " 19,\n",
133 " 19,\n",
134 " 3,\n",
135 " 7,\n",
136 " 23,\n",
137 " 1,\n",
138 " 2,\n",
139 " 2,\n",
140 " 11,\n",
141 " 4,\n",
142 " 0,\n",
143 " 24,\n",
144 " 15,\n",
145 " 7,\n",
146 " 0,\n",
147 " 11,\n",
148 " 13,\n",
149 " 0,\n",
150 " 3,\n",
151 " 7,\n",
152 " 8,\n",
153 " 4,\n",
154 " 7,\n",
155 " 0,\n",
156 " 14,\n",
157 " 20,\n",
158 " 3,\n",
159 " 17,\n",
160 " 14,\n",
161 " 19,\n",
162 " 22,\n",
163 " 13,\n",
164 " 17,\n",
165 " 17,\n",
166 " 21,\n",
167 " 24,\n",
168 " 18,\n",
169 " 0,\n",
170 " 1,\n",
171 " 9,\n",
172 " 11,\n",
173 " 19,\n",
174 " 19,\n",
175 " 1,\n",
176 " 0,\n",
177 " 24,\n",
178 " 19,\n",
179 " 12,\n",
180 " 4,\n",
181 " 11,\n",
182 " 17,\n",
183 " 10,\n",
184 " 0,\n",
185 " 8,\n",
186 " 3,\n",
187 " 14,\n",
188 " 15,\n",
189 " 19,\n",
190 " 7,\n",
191 " 0,\n",
192 " 19,\n",
193 " 11,\n",
194 " 4,\n",
195 " 11,\n",
196 " 17,\n",
197 " 19,\n",
198 " 22,\n",
199 " 0,\n",
200 " 0,\n",
201 " 12,\n",
202 " 0,\n",
203 " 13,\n",
204 " 4,\n",
205 " 10,\n",
206 " 18,\n",
207 " 21,\n",
208 " 21,\n",
209 " 25,\n",
210 " 17,\n",
211 " 21,\n",
212 " 11,\n",
213 " 11,\n",
214 " 0,\n",
215 " 19,\n",
216 " 10,\n",
217 " 2,\n",
218 " 17,\n",
219 " 9,\n",
220 " 16,\n",
221 " 20,\n",
222 " 8,\n",
223 " 2,\n",
224 " 8,\n",
225 " 25,\n",
226 " 6,\n",
227 " 19,\n",
228 " 14,\n",
229 " 16,\n",
230 " 2,\n",
231 " 15,\n",
232 " 13,\n",
233 " 17,\n",
234 " 17,\n",
235 " 10,\n",
236 " 19,\n",
237 " 19,\n",
238 " 14,\n",
239 " 22,\n",
240 " 0,\n",
241 " 13,\n",
242 " 3,\n",
243 " 16,\n",
244 " 4,\n",
245 " 7,\n",
246 " 19,\n",
247 " 16,\n",
248 " 17,\n",
249 " 21,\n",
250 " 19,\n",
251 " 1,\n",
252 " 0,\n",
253 " 24,\n",
254 " 3,\n",
255 " 16,\n",
256 " 4,\n",
257 " 0,\n",
258 " 11,\n",
259 " 0,\n",
260 " 13,\n",
261 " 13,\n",
262 " 14,\n",
263 " 7,\n",
264 " 20,\n",
265 " 11,\n",
266 " 0,\n",
267 " 13,\n",
268 " 20,\n",
269 " 25,\n",
270 " 11,\n",
271 " 22,\n",
272 " 4,\n",
273 " 23,\n",
274 " 19,\n",
275 " 11,\n",
276 " 21,\n",
277 " 9,\n",
278 " 17,\n",
279 " 21,\n",
280 " 8,\n",
281 " 21,\n",
282 " 7,\n",
283 " 13,\n",
284 " 14,\n",
285 " 7,\n",
286 " 3,\n",
287 " 16,\n",
288 " 12,\n",
289 " 6,\n",
290 " 24,\n",
291 " 10,\n",
292 " 0,\n",
293 " 2,\n",
294 " 11,\n",
295 " 12,\n",
296 " 18,\n",
297 " 22,\n",
298 " 17,\n",
299 " 20,\n",
300 " 15,\n",
301 " 3,\n",
302 " 4,\n",
303 " 19,\n",
304 " 5,\n",
305 " 8,\n",
306 " 14,\n",
307 " 5,\n",
308 " 19,\n",
309 " 5,\n",
310 " 4,\n",
311 " 11,\n",
312 " 7,\n",
313 " 25,\n",
314 " 15,\n",
315 " 23,\n",
316 " 7,\n",
317 " 0,\n",
318 " 18,\n",
319 " 22,\n",
320 " 5,\n",
321 " 19,\n",
322 " 22,\n",
323 " 15,\n",
324 " 17,\n",
325 " 17,\n",
326 " 18,\n",
327 " 22,\n",
328 " 4,\n",
329 " 8,\n",
330 " 18,\n",
331 " 4,\n",
332 " 14,\n",
333 " 7,\n",
334 " 4,\n",
335 " 5,\n",
336 " 15,\n",
337 " 3,\n",
338 " 17,\n",
339 " 21,\n",
340 " 19,\n",
341 " 19,\n",
342 " 13,\n",
343 " 21,\n",
344 " 0,\n",
345 " 6,\n",
346 " 3,\n",
347 " 21,\n",
348 " 18,\n",
349 " 22,\n",
350 " 6,\n",
351 " 14,\n",
352 " 4,\n",
353 " 17,\n",
354 " 1,\n",
355 " 4,\n",
356 " 19,\n",
357 " 13,\n",
358 " 7,\n",
359 " 0,\n",
360 " 17,\n",
361 " 21,\n",
362 " 0,\n",
363 " 4,\n",
364 " 4,\n",
365 " 21,\n",
366 " 19,\n",
367 " 11,\n",
368 " 11,\n",
369 " 19,\n",
370 " 1,\n",
371 " 12,\n",
372 " 6,\n",
373 " 0,\n",
374 " 8,\n",
375 " 0,\n",
376 " 19,\n",
377 " 6,\n",
378 " 4,\n",
379 " 11,\n",
380 " 8,\n",
381 " 13,\n",
382 " 12,\n",
383 " 3,\n",
384 " 0,\n",
385 " 22,\n",
386 " 4,\n",
387 " 21,\n",
388 " 7,\n",
389 " 0,\n",
390 " 19,\n",
391 " 19,\n",
392 " 4,\n",
393 " 17,\n",
394 " 3,\n",
395 " 7,\n",
396 " 17,\n",
397 " 25,\n",
398 " 13,\n",
399 " 1,\n",
400 " 13,\n",
401 " 21,\n",
402 " 14,\n",
403 " 20,\n",
404 " 19,\n",
405 " 13,\n",
406 " 4,\n",
407 " 5,\n",
408 " 14,\n",
409 " 19,\n",
410 " 4,\n",
411 " 21,\n",
412 " 4,\n",
413 " 0,\n",
414 " 4,\n",
415 " 7,\n",
416 " 11,\n",
417 " 0,\n",
418 " 24,\n",
419 " 12,\n",
420 " 7,\n",
421 " 0,\n",
422 " 2,\n",
423 " 6,\n",
424 " 11,\n",
425 " 25,\n",
426 " 4,\n",
427 " 15,\n",
428 " 19,\n",
429 " 21,\n",
430 " 21,\n",
431 " 3,\n",
432 " 8,\n",
433 " 12,\n",
434 " 22,\n",
435 " 14,\n",
436 " 17,\n",
437 " 5,\n",
438 " 8,\n",
439 " 18,\n",
440 " 6,\n",
441 " 19,\n",
442 " 20,\n",
443 " 25,\n",
444 " 11,\n",
445 " 22,\n",
446 " 8,\n",
447 " 1,\n",
448 " 4,\n",
449 " 16,\n",
450 " 14,\n",
451 " 7,\n",
452 " 20,\n",
453 " 1,\n",
454 " 19,\n",
455 " 6,\n",
456 " 7,\n",
457 " 0,\n",
458 " 12,\n",
459 " 16,\n",
460 " 14,\n",
461 " 17,\n",
462 " 13,\n",
463 " 9,\n",
464 " 13,\n",
465 " 13,\n",
466 " 17,\n",
467 " 20,\n",
468 " 12,\n",
469 " 16,\n",
470 " 21,\n",
471 " 9,\n",
472 " 19,\n",
473 " 23,\n",
474 " 4,\n",
475 " 11,\n",
476 " 19,\n",
477 " 5,\n",
478 " 14,\n",
479 " 21,\n",
480 " 6,\n",
481 " 0,\n",
482 " 22,\n",
483 " 3,\n",
484 " 0,\n",
485 " 4,\n",
486 " 4,\n",
487 " 21,\n",
488 " 11,\n",
489 " 11,\n",
490 " 6,\n",
491 " 17,\n",
492 " 19,\n",
493 " 23,\n",
494 " 8,\n",
495 " 1,\n",
496 " 6,\n",
497 " 19,\n",
498 " 8,\n",
499 " 1,\n",
500 " 4,\n",
501 " 21,\n",
502 " 12,\n",
503 " 15,\n",
504 " 18,\n",
505 " 0,\n",
506 " 0,\n",
507 " 19,\n",
508 " 4,\n",
509 " 14,\n",
510 " 0,\n",
511 " 18,\n",
512 " 4,\n",
513 " 21,\n",
514 " 0,\n",
515 " 4,\n",
516 " 24,\n",
517 " 16,\n",
518 " 14,\n",
519 " 7,\n",
520 " 0,\n",
521 " 12,\n",
522 " 4,\n",
523 " 14,\n",
524 " 13,\n",
525 " 13,\n",
526 " 2,\n",
527 " 5,\n",
528 " 20,\n",
529 " 8,\n",
530 " 3,\n",
531 " 14,\n",
532 " 4,\n",
533 " 5,\n",
534 " 0,\n",
535 " 5,\n",
536 " 0,\n",
537 " 19,\n",
538 " 19,\n",
539 " 4,\n",
540 " 12,\n",
541 " 20,\n",
542 " 8,\n",
543 " 12,\n",
544 " 13,\n",
545 " 5,\n",
546 " 11,\n",
547 " 25,\n",
548 " 13,\n",
549 " 1,\n",
550 " 4,\n",
551 " 10,\n",
552 " 14,\n",
553 " 5,\n",
554 " 14,\n",
555 " 1,\n",
556 " 17,\n",
557 " 11,\n",
558 " 8,\n",
559 " 0,\n",
560 " 4,\n",
561 " 7,\n",
562 " 7,\n",
563 " 0,\n",
564 " 20,\n",
565 " 8,\n",
566 " 7,\n",
567 " 13,\n",
568 " 13,\n",
569 " 13,\n",
570 " 22,\n",
571 " 25,\n",
572 " 0,\n",
573 " 4,\n",
574 " 4,\n",
575 " 21,\n",
576 " 19,\n",
577 " 11,\n",
578 " 11,\n",
579 " 19,\n",
580 " 15,\n",
581 " 0,\n",
582 " 0,\n",
583 " 11,\n",
584 " 13,\n",
585 " 0,\n",
586 " 13,\n",
587 " 21,\n",
588 " 19,\n",
589 " 25,\n",
590 " 11,\n",
591 " 25,\n",
592 " 20,\n",
593 " 20,\n",
594 " 2,\n",
595 " 15,\n",
596 " 19,\n",
597 " 0,\n",
598 " 4,\n",
599 " 11,\n",
600 " 8,\n",
601 " 13,\n",
602 " 0,\n",
603 " 13,\n",
604 " 15,\n",
605 " 0,\n",
606 " 0,\n",
607 " 7,\n",
608 " 4,\n",
609 " 22,\n",
610 " 5,\n",
611 " 19,\n",
612 " 7,\n",
613 " 0,\n",
614 " 14,\n",
615 " 18,\n",
616 " 4,\n",
617 " 19,\n",
618 " 0,\n",
619 " 17,\n",
620 " 8,\n",
621 " 1,\n",
622 " 13,\n",
623 " 1,\n",
624 " 13,\n",
625 " 21,\n",
626 " 7,\n",
627 " 0,\n",
628 " 4,\n",
629 " 21,\n",
630 " 3,\n",
631 " 7,\n",
632 " 24,\n",
633 " 24,\n",
634 " 19,\n",
635 " 11,\n",
636 " 12,\n",
637 " 20,\n",
638 " 23,\n",
639 " 1]"
640 ]
641 }
642 ],
643 "prompt_number": 17
644 },
645 {
646 "cell_type": "code",
647 "collapsed": false,
648 "input": [
649 "m = np.matrix([[7,8], [11,11]])\n",
650 "m"
651 ],
652 "language": "python",
653 "metadata": {},
654 "outputs": [
655 {
656 "metadata": {},
657 "output_type": "pyout",
658 "prompt_number": 106,
659 "text": [
660 "matrix([[ 7, 8],\n",
661 " [11, 11]])"
662 ]
663 }
664 ],
665 "prompt_number": 106
666 },
667 {
668 "cell_type": "code",
669 "collapsed": false,
670 "input": [
671 "np.linalg.det(m)"
672 ],
673 "language": "python",
674 "metadata": {},
675 "outputs": [
676 {
677 "metadata": {},
678 "output_type": "pyout",
679 "prompt_number": 107,
680 "text": [
681 "-11.000000000000002"
682 ]
683 }
684 ],
685 "prompt_number": 107
686 },
687 {
688 "cell_type": "code",
689 "collapsed": false,
690 "input": [
691 "m.I"
692 ],
693 "language": "python",
694 "metadata": {},
695 "outputs": [
696 {
697 "metadata": {},
698 "output_type": "pyout",
699 "prompt_number": 108,
700 "text": [
701 "matrix([[-1. , 0.72727273],\n",
702 " [ 1. , -0.63636364]])"
703 ]
704 }
705 ],
706 "prompt_number": 108
707 },
708 {
709 "cell_type": "code",
710 "collapsed": false,
711 "input": [
712 "v = np.matrix([[7], [22]])\n",
713 "v"
714 ],
715 "language": "python",
716 "metadata": {},
717 "outputs": [
718 {
719 "metadata": {},
720 "output_type": "pyout",
721 "prompt_number": 37,
722 "text": [
723 "matrix([[ 7],\n",
724 " [22]])"
725 ]
726 }
727 ],
728 "prompt_number": 37
729 },
730 {
731 "cell_type": "code",
732 "collapsed": false,
733 "input": [
734 "c = (m*v) % 26\n",
735 "c"
736 ],
737 "language": "python",
738 "metadata": {},
739 "outputs": [
740 {
741 "metadata": {},
742 "output_type": "pyout",
743 "prompt_number": 46,
744 "text": [
745 "matrix([[9],\n",
746 " [5]])"
747 ]
748 }
749 ],
750 "prompt_number": 46
751 },
752 {
753 "cell_type": "code",
754 "collapsed": false,
755 "input": [
756 "np.linalg.solve(m, c) % 26"
757 ],
758 "language": "python",
759 "metadata": {},
760 "outputs": [
761 {
762 "metadata": {},
763 "output_type": "pyout",
764 "prompt_number": 48,
765 "text": [
766 "matrix([[ 7.],\n",
767 " [ 22.]])"
768 ]
769 }
770 ],
771 "prompt_number": 48
772 },
773 {
774 "cell_type": "code",
775 "collapsed": false,
776 "input": [
777 "m*v"
778 ],
779 "language": "python",
780 "metadata": {},
781 "outputs": [
782 {
783 "metadata": {},
784 "output_type": "pyout",
785 "prompt_number": 40,
786 "text": [
787 "matrix([[ 87],\n",
788 " [109]])"
789 ]
790 }
791 ],
792 "prompt_number": 40
793 },
794 {
795 "cell_type": "code",
796 "collapsed": false,
797 "input": [
798 "(m*v)%26"
799 ],
800 "language": "python",
801 "metadata": {},
802 "outputs": [
803 {
804 "metadata": {},
805 "output_type": "pyout",
806 "prompt_number": 41,
807 "text": [
808 "matrix([[9],\n",
809 " [5]])"
810 ]
811 }
812 ],
813 "prompt_number": 41
814 },
815 {
816 "cell_type": "code",
817 "collapsed": false,
818 "input": [
819 "np.linalg.solve(m, (m*v)%26)%26"
820 ],
821 "language": "python",
822 "metadata": {},
823 "outputs": [
824 {
825 "metadata": {},
826 "output_type": "pyout",
827 "prompt_number": 42,
828 "text": [
829 "matrix([[ 7.],\n",
830 " [ 22.]])"
831 ]
832 }
833 ],
834 "prompt_number": 42
835 },
836 {
837 "cell_type": "code",
838 "collapsed": false,
839 "input": [
840 "len(m)"
841 ],
842 "language": "python",
843 "metadata": {},
844 "outputs": [
845 {
846 "metadata": {},
847 "output_type": "pyout",
848 "prompt_number": 51,
849 "text": [
850 "2"
851 ]
852 }
853 ],
854 "prompt_number": 51
855 },
856 {
857 "cell_type": "code",
858 "collapsed": false,
859 "input": [
860 "def hill_encipher(matrix, message_letters, fillvalue='a'):\n",
861 " n = len(matrix)\n",
862 " sanitised_message = sanitise(message_letters)\n",
863 " if len(sanitised_message) % n != 0:\n",
864 " padding = fillvalue[0] * (n - len(sanitised_message) % n)\n",
865 " else:\n",
866 " padding = ''\n",
867 " message = [ord(c) - ord('a') for c in sanitised_message + padding]\n",
868 " message_chunks = [message[i:i+n] for i in range(0, len(message), n)]\n",
869 " # message_chunks = chunks(message, len(matrix), fillvalue=None)\n",
870 " enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0] for c in message_chunks]\n",
871 " return ''.join([chr(int(round(l)) % 26 + ord('a')) for l in sum(enciphered_chunks, [])])"
872 ],
873 "language": "python",
874 "metadata": {},
875 "outputs": [],
876 "prompt_number": 181
877 },
878 {
879 "cell_type": "code",
880 "collapsed": false,
881 "input": [
882 "hill_encipher(m, 'hellothere')"
883 ],
884 "language": "python",
885 "metadata": {},
886 "outputs": [
887 {
888 "metadata": {},
889 "output_type": "pyout",
890 "prompt_number": 156,
891 "text": [
892 "'drjiqzdrvx'"
893 ]
894 }
895 ],
896 "prompt_number": 156
897 },
898 {
899 "cell_type": "code",
900 "collapsed": false,
901 "input": [
902 "msg = [ord(c) - ord('a') for c in 'hellothere']\n",
903 "msg"
904 ],
905 "language": "python",
906 "metadata": {},
907 "outputs": [
908 {
909 "metadata": {},
910 "output_type": "pyout",
911 "prompt_number": 68,
912 "text": [
913 "[7, 4, 11, 11, 14, 19, 7, 4, 17, 4]"
914 ]
915 }
916 ],
917 "prompt_number": 68
918 },
919 {
920 "cell_type": "code",
921 "collapsed": false,
922 "input": [
923 "msgc = [msg[i:i+len(m)] for i in range(0, len(msg), len(m))]\n",
924 "msgc"
925 ],
926 "language": "python",
927 "metadata": {},
928 "outputs": [
929 {
930 "metadata": {},
931 "output_type": "pyout",
932 "prompt_number": 112,
933 "text": [
934 "[[7, 11], [14, 25], [21, 14], [7, 11], [11, 15], [0, 0]]"
935 ]
936 }
937 ],
938 "prompt_number": 112
939 },
940 {
941 "cell_type": "code",
942 "collapsed": false,
943 "input": [
944 "((m*np.matrix(msgc[0]).T).T % 26).tolist()[0]"
945 ],
946 "language": "python",
947 "metadata": {},
948 "outputs": [
949 {
950 "metadata": {},
951 "output_type": "pyout",
952 "prompt_number": 87,
953 "text": [
954 "[7, 11]"
955 ]
956 }
957 ],
958 "prompt_number": 87
959 },
960 {
961 "cell_type": "code",
962 "collapsed": false,
963 "input": [
964 "def hill_decipher(matrix, message, fillvalue='a'):\n",
965 " adjugate = linalg.det(matrix)*linalg.inv(matrix)\n",
966 " inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26][1]\n",
967 " inverse_matrix = (inverse_determinant * adjugate) % 26\n",
968 " return hill_encipher(inverse_matrix, message, fillvalue) "
969 ],
970 "language": "python",
971 "metadata": {},
972 "outputs": [],
973 "prompt_number": 195
974 },
975 {
976 "cell_type": "code",
977 "collapsed": false,
978 "input": [
979 "hill_decipher(m, 'drjiqzdrvx')"
980 ],
981 "language": "python",
982 "metadata": {},
983 "outputs": [
984 {
985 "metadata": {},
986 "output_type": "pyout",
987 "prompt_number": 161,
988 "text": [
989 "'hellothere'"
990 ]
991 }
992 ],
993 "prompt_number": 161
994 },
995 {
996 "cell_type": "code",
997 "collapsed": false,
998 "input": [
999 "msg = [ord(c) - ord('a') for c in 'drjiqzdrvxaa']\n",
1000 "msg"
1001 ],
1002 "language": "python",
1003 "metadata": {},
1004 "outputs": [
1005 {
1006 "metadata": {},
1007 "output_type": "pyout",
1008 "prompt_number": 114,
1009 "text": [
1010 "[3, 17, 9, 8, 16, 25, 3, 17, 21, 23, 0, 0]"
1011 ]
1012 }
1013 ],
1014 "prompt_number": 114
1015 },
1016 {
1017 "cell_type": "code",
1018 "collapsed": false,
1019 "input": [
1020 "msgc = [msg[i:i+len(m)] for i in range(0, len(msg), len(m))]\n",
1021 "msgc"
1022 ],
1023 "language": "python",
1024 "metadata": {},
1025 "outputs": [
1026 {
1027 "metadata": {},
1028 "output_type": "pyout",
1029 "prompt_number": 115,
1030 "text": [
1031 "[[3, 17], [9, 8], [16, 25], [3, 17], [21, 23], [0, 0]]"
1032 ]
1033 }
1034 ],
1035 "prompt_number": 115
1036 },
1037 {
1038 "cell_type": "code",
1039 "collapsed": false,
1040 "input": [
1041 "(np.linalg.solve(m, np.matrix(msgc[0]).T).T % 26)"
1042 ],
1043 "language": "python",
1044 "metadata": {},
1045 "outputs": [
1046 {
1047 "metadata": {},
1048 "output_type": "pyout",
1049 "prompt_number": 116,
1050 "text": [
1051 "matrix([[ 9.36363636, 18.18181818]])"
1052 ]
1053 }
1054 ],
1055 "prompt_number": 116
1056 },
1057 {
1058 "cell_type": "code",
1059 "collapsed": false,
1060 "input": [
1061 "m_adj = linalg.det(m)*linalg.inv(m)\n",
1062 "m_adj"
1063 ],
1064 "language": "python",
1065 "metadata": {},
1066 "outputs": [
1067 {
1068 "metadata": {},
1069 "output_type": "pyout",
1070 "prompt_number": 142,
1071 "text": [
1072 "matrix([[ 11., -8.],\n",
1073 " [-11., 7.]])"
1074 ]
1075 }
1076 ],
1077 "prompt_number": 142
1078 },
1079 {
1080 "cell_type": "code",
1081 "collapsed": false,
1082 "input": [
1083 "modular_division_table[int(round(linalg.det(m))) % 26][1]"
1084 ],
1085 "language": "python",
1086 "metadata": {},
1087 "outputs": [
1088 {
1089 "metadata": {},
1090 "output_type": "pyout",
1091 "prompt_number": 148,
1092 "text": [
1093 "7"
1094 ]
1095 }
1096 ],
1097 "prompt_number": 148
1098 },
1099 {
1100 "cell_type": "code",
1101 "collapsed": false,
1102 "input": [
1103 "m_inv = (modular_division_table[int(round(linalg.det(m))) % 26][1] * m_adj) % 26\n",
1104 "m_inv"
1105 ],
1106 "language": "python",
1107 "metadata": {},
1108 "outputs": [
1109 {
1110 "metadata": {},
1111 "output_type": "pyout",
1112 "prompt_number": 150,
1113 "text": [
1114 "matrix([[ 25., 22.],\n",
1115 " [ 1., 23.]])"
1116 ]
1117 }
1118 ],
1119 "prompt_number": 150
1120 },
1121 {
1122 "cell_type": "code",
1123 "collapsed": false,
1124 "input": [
1125 "hill_encipher(m_inv, 'drjiqzdrvx')"
1126 ],
1127 "language": "python",
1128 "metadata": {},
1129 "outputs": [
1130 {
1131 "metadata": {},
1132 "output_type": "pyout",
1133 "prompt_number": 157,
1134 "text": [
1135 "'hellothere'"
1136 ]
1137 }
1138 ],
1139 "prompt_number": 157
1140 },
1141 {
1142 "cell_type": "code",
1143 "collapsed": false,
1144 "input": [
1145 "np.dot(m , 1/linalg.det(m) * mc)"
1146 ],
1147 "language": "python",
1148 "metadata": {},
1149 "outputs": [
1150 {
1151 "metadata": {},
1152 "output_type": "pyout",
1153 "prompt_number": 120,
1154 "text": [
1155 "matrix([[ 1., 0.],\n",
1156 " [ 0., 1.]])"
1157 ]
1158 }
1159 ],
1160 "prompt_number": 120
1161 },
1162 {
1163 "cell_type": "code",
1164 "collapsed": false,
1165 "input": [
1166 "ml = np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]])\n",
1167 "ml"
1168 ],
1169 "language": "python",
1170 "metadata": {},
1171 "outputs": [
1172 {
1173 "metadata": {},
1174 "output_type": "pyout",
1175 "prompt_number": 122,
1176 "text": [
1177 "matrix([[ 6, 24, 1],\n",
1178 " [13, 16, 10],\n",
1179 " [20, 17, 15]])"
1180 ]
1181 }
1182 ],
1183 "prompt_number": 122
1184 },
1185 {
1186 "cell_type": "code",
1187 "collapsed": false,
1188 "input": [
1189 "ml_adj = linalg.det(ml)*linalg.inv(ml) % 26\n",
1190 "ml_adj"
1191 ],
1192 "language": "python",
1193 "metadata": {},
1194 "outputs": [
1195 {
1196 "metadata": {},
1197 "output_type": "pyout",
1198 "prompt_number": 137,
1199 "text": [
1200 "matrix([[ 18., 21., 16.],\n",
1201 " [ 5., 18., 5.],\n",
1202 " [ 5., 14., 18.]])"
1203 ]
1204 }
1205 ],
1206 "prompt_number": 137
1207 },
1208 {
1209 "cell_type": "code",
1210 "collapsed": false,
1211 "input": [
1212 "modular_division_table[int(linalg.det(ml) % 26)][1]"
1213 ],
1214 "language": "python",
1215 "metadata": {},
1216 "outputs": [
1217 {
1218 "metadata": {},
1219 "output_type": "pyout",
1220 "prompt_number": 138,
1221 "text": [
1222 "25"
1223 ]
1224 }
1225 ],
1226 "prompt_number": 138
1227 },
1228 {
1229 "cell_type": "code",
1230 "collapsed": false,
1231 "input": [
1232 "ml_inv = (modular_division_table[int(linalg.det(ml) % 26)][1] * ml_adj) % 26\n",
1233 "ml_inv"
1234 ],
1235 "language": "python",
1236 "metadata": {},
1237 "outputs": [
1238 {
1239 "metadata": {},
1240 "output_type": "pyout",
1241 "prompt_number": 139,
1242 "text": [
1243 "matrix([[ 8., 5., 10.],\n",
1244 " [ 21., 8., 21.],\n",
1245 " [ 21., 12., 8.]])"
1246 ]
1247 }
1248 ],
1249 "prompt_number": 139
1250 },
1251 {
1252 "cell_type": "code",
1253 "collapsed": false,
1254 "input": [
1255 "hill_encipher(ml, 'hello there')"
1256 ],
1257 "language": "python",
1258 "metadata": {},
1259 "outputs": [
1260 {
1261 "metadata": {},
1262 "output_type": "pyout",
1263 "prompt_number": 193,
1264 "text": [
1265 "'tfjflpznvyac'"
1266 ]
1267 }
1268 ],
1269 "prompt_number": 193
1270 },
1271 {
1272 "cell_type": "code",
1273 "collapsed": false,
1274 "input": [
1275 "hill_decipher(ml, 'tfjflpznvyac')"
1276 ],
1277 "language": "python",
1278 "metadata": {},
1279 "outputs": [
1280 {
1281 "metadata": {},
1282 "output_type": "pyout",
1283 "prompt_number": 196,
1284 "text": [
1285 "'hellothereaa'"
1286 ]
1287 }
1288 ],
1289 "prompt_number": 196
1290 },
1291 {
1292 "cell_type": "code",
1293 "collapsed": false,
1294 "input": [
1295 "hill_encipher(ml, 'act')"
1296 ],
1297 "language": "python",
1298 "metadata": {},
1299 "outputs": [
1300 {
1301 "metadata": {},
1302 "output_type": "pyout",
1303 "prompt_number": 182,
1304 "text": [
1305 "'poh'"
1306 ]
1307 }
1308 ],
1309 "prompt_number": 182
1310 },
1311 {
1312 "cell_type": "code",
1313 "collapsed": false,
1314 "input": [
1315 "hill_decipher(ml, 'poh')"
1316 ],
1317 "language": "python",
1318 "metadata": {},
1319 "outputs": [
1320 {
1321 "output_type": "stream",
1322 "stream": "stdout",
1323 "text": [
1324 "[[ 8. 5. 10.]\n",
1325 " [ 21. 8. 21.]\n",
1326 " [ 21. 12. 8.]]\n"
1327 ]
1328 },
1329 {
1330 "metadata": {},
1331 "output_type": "pyout",
1332 "prompt_number": 192,
1333 "text": [
1334 "'act'"
1335 ]
1336 }
1337 ],
1338 "prompt_number": 192
1339 },
1340 {
1341 "cell_type": "code",
1342 "collapsed": false,
1343 "input": [
1344 "[chr(int(round(i)) % 26 + ord('a')) for i in (ml_inv * np.matrix([ord(c) - ord('a') for c in 'poh']).T).T.tolist()[0]]"
1345 ],
1346 "language": "python",
1347 "metadata": {},
1348 "outputs": [
1349 {
1350 "metadata": {},
1351 "output_type": "pyout",
1352 "prompt_number": 180,
1353 "text": [
1354 "['a', 'c', 't']"
1355 ]
1356 }
1357 ],
1358 "prompt_number": 180
1359 },
1360 {
1361 "cell_type": "code",
1362 "collapsed": false,
1363 "input": [
1364 "hill_encipher(ml_inv, 'poh')"
1365 ],
1366 "language": "python",
1367 "metadata": {},
1368 "outputs": [
1369 {
1370 "metadata": {},
1371 "output_type": "pyout",
1372 "prompt_number": 184,
1373 "text": [
1374 "'act'"
1375 ]
1376 }
1377 ],
1378 "prompt_number": 184
1379 },
1380 {
1381 "cell_type": "code",
1382 "collapsed": false,
1383 "input": [
1384 "len([list(m) for m in itertools.product([list(r) for r in itertools.product(range(26), repeat=3)], repeat=3)])"
1385 ],
1386 "language": "python",
1387 "metadata": {},
1388 "outputs": [
1389 {
1390 "ename": "KeyboardInterrupt",
1391 "evalue": "",
1392 "output_type": "pyerr",
1393 "traceback": [
1394 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
1395 "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
1396 ]
1397 }
1398 ],
1399 "prompt_number": 203
1400 },
1401 {
1402 "cell_type": "code",
1403 "collapsed": false,
1404 "input": [
1405 "(3**3)**3"
1406 ],
1407 "language": "python",
1408 "metadata": {},
1409 "outputs": [
1410 {
1411 "metadata": {},
1412 "output_type": "pyout",
1413 "prompt_number": 202,
1414 "text": [
1415 "19683"
1416 ]
1417 }
1418 ],
1419 "prompt_number": 202
1420 },
1421 {
1422 "cell_type": "code",
1423 "collapsed": false,
1424 "input": [
1425 "[np.matrix(list(m)) for m in itertools.product([list(r) for r in itertools.product(range(3), repeat=2)], repeat=2)]"
1426 ],
1427 "language": "python",
1428 "metadata": {},
1429 "outputs": [
1430 {
1431 "metadata": {},
1432 "output_type": "pyout",
1433 "prompt_number": 206,
1434 "text": [
1435 "[matrix([[0, 0],\n",
1436 " [0, 0]]), matrix([[0, 0],\n",
1437 " [0, 1]]), matrix([[0, 0],\n",
1438 " [0, 2]]), matrix([[0, 0],\n",
1439 " [1, 0]]), matrix([[0, 0],\n",
1440 " [1, 1]]), matrix([[0, 0],\n",
1441 " [1, 2]]), matrix([[0, 0],\n",
1442 " [2, 0]]), matrix([[0, 0],\n",
1443 " [2, 1]]), matrix([[0, 0],\n",
1444 " [2, 2]]), matrix([[0, 1],\n",
1445 " [0, 0]]), matrix([[0, 1],\n",
1446 " [0, 1]]), matrix([[0, 1],\n",
1447 " [0, 2]]), matrix([[0, 1],\n",
1448 " [1, 0]]), matrix([[0, 1],\n",
1449 " [1, 1]]), matrix([[0, 1],\n",
1450 " [1, 2]]), matrix([[0, 1],\n",
1451 " [2, 0]]), matrix([[0, 1],\n",
1452 " [2, 1]]), matrix([[0, 1],\n",
1453 " [2, 2]]), matrix([[0, 2],\n",
1454 " [0, 0]]), matrix([[0, 2],\n",
1455 " [0, 1]]), matrix([[0, 2],\n",
1456 " [0, 2]]), matrix([[0, 2],\n",
1457 " [1, 0]]), matrix([[0, 2],\n",
1458 " [1, 1]]), matrix([[0, 2],\n",
1459 " [1, 2]]), matrix([[0, 2],\n",
1460 " [2, 0]]), matrix([[0, 2],\n",
1461 " [2, 1]]), matrix([[0, 2],\n",
1462 " [2, 2]]), matrix([[1, 0],\n",
1463 " [0, 0]]), matrix([[1, 0],\n",
1464 " [0, 1]]), matrix([[1, 0],\n",
1465 " [0, 2]]), matrix([[1, 0],\n",
1466 " [1, 0]]), matrix([[1, 0],\n",
1467 " [1, 1]]), matrix([[1, 0],\n",
1468 " [1, 2]]), matrix([[1, 0],\n",
1469 " [2, 0]]), matrix([[1, 0],\n",
1470 " [2, 1]]), matrix([[1, 0],\n",
1471 " [2, 2]]), matrix([[1, 1],\n",
1472 " [0, 0]]), matrix([[1, 1],\n",
1473 " [0, 1]]), matrix([[1, 1],\n",
1474 " [0, 2]]), matrix([[1, 1],\n",
1475 " [1, 0]]), matrix([[1, 1],\n",
1476 " [1, 1]]), matrix([[1, 1],\n",
1477 " [1, 2]]), matrix([[1, 1],\n",
1478 " [2, 0]]), matrix([[1, 1],\n",
1479 " [2, 1]]), matrix([[1, 1],\n",
1480 " [2, 2]]), matrix([[1, 2],\n",
1481 " [0, 0]]), matrix([[1, 2],\n",
1482 " [0, 1]]), matrix([[1, 2],\n",
1483 " [0, 2]]), matrix([[1, 2],\n",
1484 " [1, 0]]), matrix([[1, 2],\n",
1485 " [1, 1]]), matrix([[1, 2],\n",
1486 " [1, 2]]), matrix([[1, 2],\n",
1487 " [2, 0]]), matrix([[1, 2],\n",
1488 " [2, 1]]), matrix([[1, 2],\n",
1489 " [2, 2]]), matrix([[2, 0],\n",
1490 " [0, 0]]), matrix([[2, 0],\n",
1491 " [0, 1]]), matrix([[2, 0],\n",
1492 " [0, 2]]), matrix([[2, 0],\n",
1493 " [1, 0]]), matrix([[2, 0],\n",
1494 " [1, 1]]), matrix([[2, 0],\n",
1495 " [1, 2]]), matrix([[2, 0],\n",
1496 " [2, 0]]), matrix([[2, 0],\n",
1497 " [2, 1]]), matrix([[2, 0],\n",
1498 " [2, 2]]), matrix([[2, 1],\n",
1499 " [0, 0]]), matrix([[2, 1],\n",
1500 " [0, 1]]), matrix([[2, 1],\n",
1501 " [0, 2]]), matrix([[2, 1],\n",
1502 " [1, 0]]), matrix([[2, 1],\n",
1503 " [1, 1]]), matrix([[2, 1],\n",
1504 " [1, 2]]), matrix([[2, 1],\n",
1505 " [2, 0]]), matrix([[2, 1],\n",
1506 " [2, 1]]), matrix([[2, 1],\n",
1507 " [2, 2]]), matrix([[2, 2],\n",
1508 " [0, 0]]), matrix([[2, 2],\n",
1509 " [0, 1]]), matrix([[2, 2],\n",
1510 " [0, 2]]), matrix([[2, 2],\n",
1511 " [1, 0]]), matrix([[2, 2],\n",
1512 " [1, 1]]), matrix([[2, 2],\n",
1513 " [1, 2]]), matrix([[2, 2],\n",
1514 " [2, 0]]), matrix([[2, 2],\n",
1515 " [2, 1]]), matrix([[2, 2],\n",
1516 " [2, 2]])]"
1517 ]
1518 }
1519 ],
1520 "prompt_number": 206
1521 },
1522 {
1523 "cell_type": "code",
1524 "collapsed": false,
1525 "input": [
1526 "all_matrices = [np.matrix(list(m)) for m in itertools.product([list(r) for r in itertools.product(range(26), repeat=2)], repeat=2)]\n",
1527 "valid_matrices = [m for m, d in zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))\n",
1528 " if d != 0\n",
1529 " if d % 2 != 0\n",
1530 " if d % 13 != 0 ]\n",
1531 "len(valid_matrices)"
1532 ],
1533 "language": "python",
1534 "metadata": {},
1535 "outputs": [
1536 {
1537 "metadata": {},
1538 "output_type": "pyout",
1539 "prompt_number": 215,
1540 "text": [
1541 "157248"
1542 ]
1543 }
1544 ],
1545 "prompt_number": 215
1546 },
1547 {
1548 "cell_type": "code",
1549 "collapsed": false,
1550 "input": [
1551 "%%timeit\n",
1552 "[m for m, d in zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))\n",
1553 " if d != 0\n",
1554 " if d % 2 != 0\n",
1555 " if d % 13 != 0 ]\n",
1556 "print('done')"
1557 ],
1558 "language": "python",
1559 "metadata": {},
1560 "outputs": [
1561 {
1562 "output_type": "stream",
1563 "stream": "stdout",
1564 "text": [
1565 "done\n",
1566 "done"
1567 ]
1568 },
1569 {
1570 "output_type": "stream",
1571 "stream": "stdout",
1572 "text": [
1573 "\n",
1574 "done"
1575 ]
1576 },
1577 {
1578 "output_type": "stream",
1579 "stream": "stdout",
1580 "text": [
1581 "\n",
1582 "done"
1583 ]
1584 },
1585 {
1586 "output_type": "stream",
1587 "stream": "stdout",
1588 "text": [
1589 "\n",
1590 "1 loops, best of 3: 10 s per loop\n"
1591 ]
1592 }
1593 ],
1594 "prompt_number": 216
1595 },
1596 {
1597 "cell_type": "code",
1598 "collapsed": false,
1599 "input": [
1600 "%%timeit\n",
1601 "[m for m in all_matrices\n",
1602 " if int(round(linalg.det(m))) != 0\n",
1603 " if int(round(linalg.det(m))) % 2 != 0\n",
1604 " if int(round(linalg.det(m))) % 13 != 0 ]\n",
1605 "print('done')"
1606 ],
1607 "language": "python",
1608 "metadata": {},
1609 "outputs": [
1610 {
1611 "output_type": "stream",
1612 "stream": "stdout",
1613 "text": [
1614 "done\n",
1615 "done"
1616 ]
1617 },
1618 {
1619 "output_type": "stream",
1620 "stream": "stdout",
1621 "text": [
1622 "\n",
1623 "done"
1624 ]
1625 },
1626 {
1627 "output_type": "stream",
1628 "stream": "stdout",
1629 "text": [
1630 "\n",
1631 "done"
1632 ]
1633 },
1634 {
1635 "output_type": "stream",
1636 "stream": "stdout",
1637 "text": [
1638 "\n",
1639 "1 loops, best of 3: 20.4 s per loop\n"
1640 ]
1641 }
1642 ],
1643 "prompt_number": 217
1644 },
1645 {
1646 "cell_type": "code",
1647 "collapsed": false,
1648 "input": [],
1649 "language": "python",
1650 "metadata": {},
1651 "outputs": []
1652 }
1653 ],
1654 "metadata": {}
1655 }
1656 ]
1657 }