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