5 <meta name=
"viewport" content=
"width=device-width, initial-scale=1, minimum-scale=1" />
6 <meta name=
"generator" content=
"pdoc 0.9.1" />
7 <title>szyfrow.hill API documentation
</title>
8 <meta name=
"description" content=
"" />
9 <link rel=
"preload stylesheet" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity=
"sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin
>
10 <link rel=
"preload stylesheet" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity=
"sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin
>
11 <link rel=
"stylesheet preload" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin
>
12 <style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:
1.5em}#content{padding:
20px}#sidebar{padding:
30px;overflow:hidden}#sidebar
> *:last-child{margin-bottom:
2cm}.http-server-breadcrumbs{font-size:
130%;margin:
0 0 15px
0}#footer{font-size:
.75em;padding:
5px
30px;border-top:
1px solid #ddd;text-align:right}#footer p{margin:
0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:
30px}h1,h2,h3,h4,h5{font-weight:
300}h1{font-size:
2.5em;line-height:
1.1em}h2{font-size:
1.75em;margin:
1em
0 .50em
0}h3{font-size:
1.4em;margin:
25px
0 10px
0}h4{margin:
0;font-size:
105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:
.2em
0}a{color:#
058;text-decoration:none;transition:color
.3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^=
"header-"]{margin-top:
2em}.ident{color:#
900}pre code{background:#f8f8f8;font-size:
.8em;line-height:
1.4em}code{background:#f2f2f1;padding:
1px
4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:
0;border-top:
1px solid #ccc;border-bottom:
1px solid #ccc;margin:
1em
0;padding:
1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:
10%}#http-server-module-list p{margin-top:
0}.toc ul,#index{list-style-type:none;margin:
0;padding:
0}#index code{background:transparent}#index h3{border-bottom:
1px solid #ddd}#index ul{padding:
0}#index h4{margin-top:
.6em;font-weight:bold}@media (min-width:
200ex){#index .two-column{column-count:
2}}@media (min-width:
300ex){#index .two-column{column-count:
3}}dl{margin-bottom:
2em}dl dl:last-child{margin-bottom:
4em}dd{margin:
0 0 1em
3em}#header-classes + dl
> dd{margin-bottom:
3em}dd dd{margin-left:
2em}dd p{margin:
10px
0}.name{background:#eee;font-weight:bold;font-size:
.85em;padding:
5px
10px;display:inline-block;min-width:
40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name
> span:first-child{white-space:nowrap}.name.class
> span:nth-child(
2){margin-left:
.4em}.inherited{color:#
999;border-left:
5px solid #eee;padding-left:
1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:
400;font-size:
1.25em}.desc h3{font-size:
1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#
666;text-align:right;font-weight:
400;font-size:
.8em;text-transform:uppercase}.source summary
> *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:
1em}.source pre{max-height:
500px;overflow:auto;margin:
0}.source pre code{font-size:
12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\
2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:
1em}img{max-width:
100%}td{padding:
0 .5em}.admonition{padding:
.1em
.5em;margin-bottom:
1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}
</style>
13 <style media=
"screen and (min-width: 700px)">@media screen and (min-width:
700px){#sidebar{width:
30%;height:
100vh;overflow:auto;position:sticky;top:
0}#content{width:
70%;max-width:
100ch;padding:
3em
4em;border-left:
1px solid #ddd}pre code{font-size:
1em}.item .name{font-size:
1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:
1.5em}.toc
> ul
> li{margin-top:
.5em}}
</style>
14 <style media=
"print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#
000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:
" (" attr(href)
")";font-size:
90%}a[href][title]:after{content:none}abbr[title]:after{content:
" (" attr(title)
")"}.ir a:after,a[href^=
"javascript:"]:after,a[href^=
"#"]:after{content:
""}pre,blockquote{border:
1px solid #
999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:
100% !important}@page{margin:
0.5cm}p,h2,h3{orphans:
3;widows:
3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}
</style>
15 <script defer
src=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity=
"sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin
></script>
16 <script>window.addEventListener('DOMContentLoaded', () =
> hljs.initHighlighting())
</script>
20 <article id=
"content">
22 <h1 class=
"title">Module
<code>szyfrow.hill
</code></h1>
24 <section id=
"section-intro">
25 <details class=
"source">
27 <span>Expand source code
</span>
29 <pre><code class=
"python">import multiprocessing
31 from numpy import matrix
32 from numpy import linalg
33 from szyfrow.support.utilities import *
34 from szyfrow.support.language_models import *
35 from szyfrow.affine import modular_division_table
38 def hill_encipher(matrix, message_letters, fillvalue=
'a
'):
39 """Hill cipher
41 >>> hill_encipher(np.matrix([[
7,
8], [
11,
11]]),
'hellothere
')
43 >>> hill_encipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), \
44 'hello there
')
45 'tfjflpznvyac
'
48 sanitised_message = sanitise(message_letters)
49 if len(sanitised_message) % n !=
0:
50 padding = fillvalue[
0] * (n - len(sanitised_message) % n)
53 message = [pos(c) for c in sanitised_message + padding]
54 message_chunks = [message[i:i+n] for i in range(
0, len(message), n)]
55 # message_chunks = chunks(message, len(matrix), fillvalue=None)
56 enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[
0]
57 for c in message_chunks]
58 return cat([unpos(round(l))
59 for l in sum(enciphered_chunks, [])])
61 def hill_decipher(matrix, message, fillvalue=
'a
'):
62 """Hill cipher
64 >>> hill_decipher(np.matrix([[
7,
8], [
11,
11]]),
'drjiqzdrvx
')
66 >>> hill_decipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), \
67 'tfjflpznvyac
')
68 'hellothereaa
'
70 adjoint = linalg.det(matrix)*linalg.inv(matrix)
71 inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) %
26,
1]
72 inverse_matrix = (inverse_determinant * adjoint) %
26
73 return hill_encipher(inverse_matrix, message, fillvalue)
75 def hill_break(message, matrix_size=
2, fitness=Pletters,
76 number_of_solutions=
1, chunksize=
500):
78 all_matrices = [np.matrix(list(m))
79 for m in itertools.product([list(r)
80 for r in itertools.product(range(
26), repeat=matrix_size)],
82 valid_matrices = [m for m, d in
83 zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
87 with multiprocessing.Pool() as pool:
88 helper_args = [(message, matrix, fitness)
89 for matrix in valid_matrices]
90 # Gotcha: the helper function here needs to be defined at the top level
91 # (limitation of Pool.starmap)
92 breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
93 if number_of_solutions ==
1:
94 return max(breaks, key=lambda k: k[
1])
96 return sorted(breaks, key=lambda k: k[
1], reverse=True)[:number_of_solutions]
98 def hill_break_worker(message, matrix, fitness):
99 plaintext = hill_decipher(matrix, message)
100 fit = fitness(plaintext)
103 if __name__ ==
"__main__
":
104 import doctest
</code></pre>
112 <h2 class=
"section-title" id=
"header-functions">Functions
</h2>
114 <dt id=
"szyfrow.hill.cat"><code class=
"name flex">
115 <span>def
<span class=
"ident">cat
</span></span>(
<span>iterable, /)
</span>
118 <div class=
"desc"><p>Concatenate any number of strings.
</p>
119 <p>The string whose method is called is inserted in between each given string.
120 The result is returned as a new string.
</p>
121 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
123 <dt id=
"szyfrow.hill.hill_break"><code class=
"name flex">
124 <span>def
<span class=
"ident">hill_break
</span></span>(
<span>message, matrix_size=
2, fitness=
<function Pletters
>, number_of_solutions=
1, chunksize=
500)
</span>
127 <div class=
"desc"></div>
128 <details class=
"source">
130 <span>Expand source code
</span>
132 <pre><code class=
"python">def hill_break(message, matrix_size=
2, fitness=Pletters,
133 number_of_solutions=
1, chunksize=
500):
135 all_matrices = [np.matrix(list(m))
136 for m in itertools.product([list(r)
137 for r in itertools.product(range(
26), repeat=matrix_size)],
139 valid_matrices = [m for m, d in
140 zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))
144 with multiprocessing.Pool() as pool:
145 helper_args = [(message, matrix, fitness)
146 for matrix in valid_matrices]
147 # Gotcha: the helper function here needs to be defined at the top level
148 # (limitation of Pool.starmap)
149 breaks = pool.starmap(hill_break_worker, helper_args, chunksize)
150 if number_of_solutions ==
1:
151 return max(breaks, key=lambda k: k[
1])
153 return sorted(breaks, key=lambda k: k[
1], reverse=True)[:number_of_solutions]
</code></pre>
156 <dt id=
"szyfrow.hill.hill_break_worker"><code class=
"name flex">
157 <span>def
<span class=
"ident">hill_break_worker
</span></span>(
<span>message, matrix, fitness)
</span>
160 <div class=
"desc"></div>
161 <details class=
"source">
163 <span>Expand source code
</span>
165 <pre><code class=
"python">def hill_break_worker(message, matrix, fitness):
166 plaintext = hill_decipher(matrix, message)
167 fit = fitness(plaintext)
168 return matrix, fit
</code></pre>
171 <dt id=
"szyfrow.hill.hill_decipher"><code class=
"name flex">
172 <span>def
<span class=
"ident">hill_decipher
</span></span>(
<span>matrix, message, fillvalue='a')
</span>
175 <div class=
"desc"><p>Hill cipher
</p>
176 <pre><code class=
"language-python-repl">>>> hill_decipher(np.matrix([[
7,
8], [
11,
11]]), 'drjiqzdrvx')
178 >>> hill_decipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), 'tfjflpznvyac')
181 <details class=
"source">
183 <span>Expand source code
</span>
185 <pre><code class=
"python">def hill_decipher(matrix, message, fillvalue=
'a
'):
186 """Hill cipher
188 >>> hill_decipher(np.matrix([[
7,
8], [
11,
11]]),
'drjiqzdrvx
')
190 >>> hill_decipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), \
191 'tfjflpznvyac
')
192 'hellothereaa
'
194 adjoint = linalg.det(matrix)*linalg.inv(matrix)
195 inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) %
26,
1]
196 inverse_matrix = (inverse_determinant * adjoint) %
26
197 return hill_encipher(inverse_matrix, message, fillvalue)
</code></pre>
200 <dt id=
"szyfrow.hill.hill_encipher"><code class=
"name flex">
201 <span>def
<span class=
"ident">hill_encipher
</span></span>(
<span>matrix, message_letters, fillvalue='a')
</span>
204 <div class=
"desc"><p>Hill cipher
</p>
205 <pre><code class=
"language-python-repl">>>> hill_encipher(np.matrix([[
7,
8], [
11,
11]]), 'hellothere')
207 >>> hill_encipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), 'hello there')
210 <details class=
"source">
212 <span>Expand source code
</span>
214 <pre><code class=
"python">def hill_encipher(matrix, message_letters, fillvalue=
'a
'):
215 """Hill cipher
217 >>> hill_encipher(np.matrix([[
7,
8], [
11,
11]]),
'hellothere
')
219 >>> hill_encipher(np.matrix([[
6,
24,
1], [
13,
16,
10], [
20,
17,
15]]), \
220 'hello there
')
221 'tfjflpznvyac
'
224 sanitised_message = sanitise(message_letters)
225 if len(sanitised_message) % n !=
0:
226 padding = fillvalue[
0] * (n - len(sanitised_message) % n)
229 message = [pos(c) for c in sanitised_message + padding]
230 message_chunks = [message[i:i+n] for i in range(
0, len(message), n)]
231 # message_chunks = chunks(message, len(matrix), fillvalue=None)
232 enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[
0]
233 for c in message_chunks]
234 return cat([unpos(round(l))
235 for l in sum(enciphered_chunks, [])])
</code></pre>
238 <dt id=
"szyfrow.hill.lcat"><code class=
"name flex">
239 <span>def
<span class=
"ident">lcat
</span></span>(
<span>iterable, /)
</span>
242 <div class=
"desc"><p>Concatenate any number of strings.
</p>
243 <p>The string whose method is called is inserted in between each given string.
244 The result is returned as a new string.
</p>
245 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
247 <dt id=
"szyfrow.hill.wcat"><code class=
"name flex">
248 <span>def
<span class=
"ident">wcat
</span></span>(
<span>iterable, /)
</span>
251 <div class=
"desc"><p>Concatenate any number of strings.
</p>
252 <p>The string whose method is called is inserted in between each given string.
253 The result is returned as a new string.
</p>
254 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
267 <li><h3>Super-module
</h3>
269 <li><code><a title=
"szyfrow" href=
"index.html">szyfrow
</a></code></li>
272 <li><h3><a href=
"#header-functions">Functions
</a></h3>
273 <ul class=
"two-column">
274 <li><code><a title=
"szyfrow.hill.cat" href=
"#szyfrow.hill.cat">cat
</a></code></li>
275 <li><code><a title=
"szyfrow.hill.hill_break" href=
"#szyfrow.hill.hill_break">hill_break
</a></code></li>
276 <li><code><a title=
"szyfrow.hill.hill_break_worker" href=
"#szyfrow.hill.hill_break_worker">hill_break_worker
</a></code></li>
277 <li><code><a title=
"szyfrow.hill.hill_decipher" href=
"#szyfrow.hill.hill_decipher">hill_decipher
</a></code></li>
278 <li><code><a title=
"szyfrow.hill.hill_encipher" href=
"#szyfrow.hill.hill_encipher">hill_encipher
</a></code></li>
279 <li><code><a title=
"szyfrow.hill.lcat" href=
"#szyfrow.hill.lcat">lcat
</a></code></li>
280 <li><code><a title=
"szyfrow.hill.wcat" href=
"#szyfrow.hill.wcat">wcat
</a></code></li>
287 <p>Generated by
<a href=
"https://pdoc3.github.io/pdoc"><cite>pdoc
</cite> 0.9.1</a>.
</p>