5 <meta name=
"viewport" content=
"width=device-width, initial-scale=1, minimum-scale=1" />
6 <meta name=
"generator" content=
"pdoc 0.9.2" />
7 <title>szyfrow.autokey API documentation
</title>
8 <meta name=
"description" content=
"Enciphering and deciphering using the [Autokey cipher](https://en.wikipedia.org/wiki/Autokey_cipher).
9 Also attempts to break messages that use a …" />
10 <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
>
11 <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
>
12 <link rel=
"stylesheet preload" as=
"style" href=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin
>
13 <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>
14 <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>
15 <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>
16 <script defer
src=
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity=
"sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin
></script>
17 <script>window.addEventListener('DOMContentLoaded', () =
> hljs.initHighlighting())
</script>
21 <article id=
"content">
23 <h1 class=
"title">Module
<code>szyfrow.autokey
</code></h1>
25 <section id=
"section-intro">
26 <p>Enciphering and deciphering using the
<a href=
"https://en.wikipedia.org/wiki/Autokey_cipher">Autokey cipher
</a>.
27 Also attempts to break messages that use a Autokey cipher.
</p>
28 <details class=
"source">
30 <span>Expand source code
</span>
32 <pre><code class=
"python">"""Enciphering and deciphering using the [Autokey cipher](https://en.wikipedia.org/wiki/Autokey_cipher).
33 Also attempts to break messages that use a Autokey cipher.
36 import multiprocessing
37 from szyfrow.support.utilities import *
38 from szyfrow.support.language_models import *
39 from szyfrow.caesar import caesar_encipher_letter, caesar_decipher_letter
42 def autokey_encipher(message, keyword):
43 """Encipher with the autokey cipher
45 >>> autokey_encipher(
'meetatthefountain
',
'kilt
')
46 'wmpmmxxaeyhbryoca
'
48 shifts = [pos(l) for l in keyword + message]
49 pairs = zip(message, shifts)
50 return cat([caesar_encipher_letter(l, k) for l, k in pairs])
52 def autokey_decipher(ciphertext, keyword):
53 """Decipher with the autokey cipher
55 >>> autokey_decipher(
'wmpmmxxaeyhbryoca
',
'kilt
')
56 'meetatthefountain
'
61 plaintext_letter = caesar_decipher_letter(c, pos(keys[
0]))
62 plaintext += [plaintext_letter]
63 keys = keys[
1:] + [plaintext_letter]
67 def autokey_sa_break( message
71 , initial_temperature=
200
72 , max_iterations=
20000
77 """Break an autokey cipher by simulated annealing
80 ciphertext = sanitise(message)
81 for keylength in range(min_keylength, max_keylength+
1):
82 for i in range(workers):
83 key = cat(random.choice(string.ascii_lowercase) for _ in range(keylength))
84 worker_args.append((ciphertext, key,
85 initial_temperature, max_iterations, fitness))
87 with multiprocessing.Pool() as pool:
88 breaks = pool.starmap(autokey_sa_break_worker,
89 worker_args, chunksize)
90 if result_count
<=
1:
91 return max(breaks, key=lambda k: k[
1])
93 return sorted(set(breaks), key=lambda k: k[
1], reverse=True)[:result_count]
96 def autokey_sa_break_worker(message, key,
97 t0, max_iterations, fitness):
99 dt = t0 / (
0.9 * max_iterations)
101 plaintext = autokey_decipher(message, key)
102 current_fitness = fitness(plaintext)
105 best_key = current_key
106 best_fitness = current_fitness
107 best_plaintext = plaintext
109 # print(
'starting for
', max_iterations)
110 for i in range(max_iterations):
111 swap_pos = random.randrange(len(current_key))
112 swap_char = random.choice(string.ascii_lowercase)
114 new_key = current_key[:swap_pos] + swap_char + current_key[swap_pos+
1:]
116 plaintext = autokey_decipher(message, new_key)
117 new_fitness = fitness(plaintext)
119 sa_chance = math.exp((new_fitness - current_fitness) / temperature)
120 except (OverflowError, ZeroDivisionError):
121 # print(
'exception triggered: new_fit {}, current_fit {}, temp {}
'.format(new_fitness, current_fitness, temperature))
123 if (new_fitness
> current_fitness or random.random()
< sa_chance):
124 current_fitness = new_fitness
125 current_key = new_key
127 if current_fitness
> best_fitness:
128 best_key = current_key
129 best_fitness = current_fitness
130 best_plaintext = plaintext
132 temperature = max(temperature - dt,
0.001)
134 # print(best_key, best_fitness, best_plaintext[:
70])
135 return best_key, best_fitness # current_alphabet, current_fitness
137 if __name__ ==
"__main__
":
138 import doctest
</code></pre>
146 <h2 class=
"section-title" id=
"header-functions">Functions
</h2>
148 <dt id=
"szyfrow.autokey.autokey_decipher"><code class=
"name flex">
149 <span>def
<span class=
"ident">autokey_decipher
</span></span>(
<span>ciphertext, keyword)
</span>
152 <div class=
"desc"><p>Decipher with the autokey cipher
</p>
153 <pre><code class=
"language-python-repl">>>> autokey_decipher('wmpmmxxaeyhbryoca', 'kilt')
156 <details class=
"source">
158 <span>Expand source code
</span>
160 <pre><code class=
"python">def autokey_decipher(ciphertext, keyword):
161 """Decipher with the autokey cipher
163 >>> autokey_decipher(
'wmpmmxxaeyhbryoca
',
'kilt
')
164 'meetatthefountain
'
169 plaintext_letter = caesar_decipher_letter(c, pos(keys[
0]))
170 plaintext += [plaintext_letter]
171 keys = keys[
1:] + [plaintext_letter]
172 return cat(plaintext)
</code></pre>
175 <dt id=
"szyfrow.autokey.autokey_encipher"><code class=
"name flex">
176 <span>def
<span class=
"ident">autokey_encipher
</span></span>(
<span>message, keyword)
</span>
179 <div class=
"desc"><p>Encipher with the autokey cipher
</p>
180 <pre><code class=
"language-python-repl">>>> autokey_encipher('meetatthefountain', 'kilt')
183 <details class=
"source">
185 <span>Expand source code
</span>
187 <pre><code class=
"python">def autokey_encipher(message, keyword):
188 """Encipher with the autokey cipher
190 >>> autokey_encipher(
'meetatthefountain
',
'kilt
')
191 'wmpmmxxaeyhbryoca
'
193 shifts = [pos(l) for l in keyword + message]
194 pairs = zip(message, shifts)
195 return cat([caesar_encipher_letter(l, k) for l, k in pairs])
</code></pre>
198 <dt id=
"szyfrow.autokey.autokey_sa_break"><code class=
"name flex">
199 <span>def
<span class=
"ident">autokey_sa_break
</span></span>(
<span>message, min_keylength=
2, max_keylength=
20, workers=
10, initial_temperature=
200, max_iterations=
20000, fitness=
<function Pletters
>, chunksize=
1, result_count=
1)
</span>
202 <div class=
"desc"><p>Break an autokey cipher by simulated annealing
</p></div>
203 <details class=
"source">
205 <span>Expand source code
</span>
207 <pre><code class=
"python">def autokey_sa_break( message
211 , initial_temperature=
200
212 , max_iterations=
20000
217 """Break an autokey cipher by simulated annealing
220 ciphertext = sanitise(message)
221 for keylength in range(min_keylength, max_keylength+
1):
222 for i in range(workers):
223 key = cat(random.choice(string.ascii_lowercase) for _ in range(keylength))
224 worker_args.append((ciphertext, key,
225 initial_temperature, max_iterations, fitness))
227 with multiprocessing.Pool() as pool:
228 breaks = pool.starmap(autokey_sa_break_worker,
229 worker_args, chunksize)
230 if result_count
<=
1:
231 return max(breaks, key=lambda k: k[
1])
233 return sorted(set(breaks), key=lambda k: k[
1], reverse=True)[:result_count]
</code></pre>
236 <dt id=
"szyfrow.autokey.autokey_sa_break_worker"><code class=
"name flex">
237 <span>def
<span class=
"ident">autokey_sa_break_worker
</span></span>(
<span>message, key, t0, max_iterations, fitness)
</span>
240 <div class=
"desc"></div>
241 <details class=
"source">
243 <span>Expand source code
</span>
245 <pre><code class=
"python">def autokey_sa_break_worker(message, key,
246 t0, max_iterations, fitness):
248 dt = t0 / (
0.9 * max_iterations)
250 plaintext = autokey_decipher(message, key)
251 current_fitness = fitness(plaintext)
254 best_key = current_key
255 best_fitness = current_fitness
256 best_plaintext = plaintext
258 # print(
'starting for
', max_iterations)
259 for i in range(max_iterations):
260 swap_pos = random.randrange(len(current_key))
261 swap_char = random.choice(string.ascii_lowercase)
263 new_key = current_key[:swap_pos] + swap_char + current_key[swap_pos+
1:]
265 plaintext = autokey_decipher(message, new_key)
266 new_fitness = fitness(plaintext)
268 sa_chance = math.exp((new_fitness - current_fitness) / temperature)
269 except (OverflowError, ZeroDivisionError):
270 # print(
'exception triggered: new_fit {}, current_fit {}, temp {}
'.format(new_fitness, current_fitness, temperature))
272 if (new_fitness
> current_fitness or random.random()
< sa_chance):
273 current_fitness = new_fitness
274 current_key = new_key
276 if current_fitness
> best_fitness:
277 best_key = current_key
278 best_fitness = current_fitness
279 best_plaintext = plaintext
281 temperature = max(temperature - dt,
0.001)
283 # print(best_key, best_fitness, best_plaintext[:
70])
284 return best_key, best_fitness # current_alphabet, current_fitness
</code></pre>
287 <dt id=
"szyfrow.autokey.cat"><code class=
"name flex">
288 <span>def
<span class=
"ident">cat
</span></span>(
<span>iterable, /)
</span>
291 <div class=
"desc"><p>Concatenate any number of strings.
</p>
292 <p>The string whose method is called is inserted in between each given string.
293 The result is returned as a new string.
</p>
294 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
296 <dt id=
"szyfrow.autokey.lcat"><code class=
"name flex">
297 <span>def
<span class=
"ident">lcat
</span></span>(
<span>iterable, /)
</span>
300 <div class=
"desc"><p>Concatenate any number of strings.
</p>
301 <p>The string whose method is called is inserted in between each given string.
302 The result is returned as a new string.
</p>
303 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
305 <dt id=
"szyfrow.autokey.wcat"><code class=
"name flex">
306 <span>def
<span class=
"ident">wcat
</span></span>(
<span>iterable, /)
</span>
309 <div class=
"desc"><p>Concatenate any number of strings.
</p>
310 <p>The string whose method is called is inserted in between each given string.
311 The result is returned as a new string.
</p>
312 <p>Example: '.'.join(['ab', 'pq', 'rs']) -
> 'ab.pq.rs'
</p></div>
325 <li><h3>Super-module
</h3>
327 <li><code><a title=
"szyfrow" href=
"index.html">szyfrow
</a></code></li>
330 <li><h3><a href=
"#header-functions">Functions
</a></h3>
332 <li><code><a title=
"szyfrow.autokey.autokey_decipher" href=
"#szyfrow.autokey.autokey_decipher">autokey_decipher
</a></code></li>
333 <li><code><a title=
"szyfrow.autokey.autokey_encipher" href=
"#szyfrow.autokey.autokey_encipher">autokey_encipher
</a></code></li>
334 <li><code><a title=
"szyfrow.autokey.autokey_sa_break" href=
"#szyfrow.autokey.autokey_sa_break">autokey_sa_break
</a></code></li>
335 <li><code><a title=
"szyfrow.autokey.autokey_sa_break_worker" href=
"#szyfrow.autokey.autokey_sa_break_worker">autokey_sa_break_worker
</a></code></li>
336 <li><code><a title=
"szyfrow.autokey.cat" href=
"#szyfrow.autokey.cat">cat
</a></code></li>
337 <li><code><a title=
"szyfrow.autokey.lcat" href=
"#szyfrow.autokey.lcat">lcat
</a></code></li>
338 <li><code><a title=
"szyfrow.autokey.wcat" href=
"#szyfrow.autokey.wcat">wcat
</a></code></li>
345 <p>Generated by
<a href=
"https://pdoc3.github.io/pdoc"><cite>pdoc
</cite> 0.9.2</a>.
</p>