Skip to content

Commit c6f4b44

Browse files
Copilotdhondta
andcommitted
Add autoclave (autokey) cipher codec
Co-authored-by: dhondta <9108102+dhondta@users.noreply.github.com> Agent-Logs-Url: https://github.com/dhondta/python-codext/sessions/4af53d1f-ef97-4bc3-9dd3-c6b23cdd761d
1 parent 2fc9666 commit c6f4b44

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/codext/crypto/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: UTF-8 -*-
22
from .affine import *
33
from .atbash import *
4+
from .autoclave import *
45
from .bacon import *
56
from .barbie import *
67
from .citrix import *

src/codext/crypto/autoclave.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# -*- coding: UTF-8 -*-
2+
"""Autoclave Cipher Codec - autoclave content encoding.
3+
4+
The Autoclave (Autokey) cipher is a variant of the Vigenere cipher where the key
5+
is extended by appending the plaintext to the initial key (key+plaintext), making
6+
the key stream as long as the message itself.
7+
8+
This codec:
9+
- en/decodes strings from str to str
10+
- en/decodes strings from bytes to bytes
11+
- decodes file content to str (read)
12+
- encodes file content from str to bytes (write)
13+
14+
Reference: https://www.dcode.fr/autoclave-cipher
15+
"""
16+
from string import ascii_lowercase as LC, ascii_uppercase as UC
17+
18+
from ..__common__ import *
19+
20+
21+
__examples__ = {
22+
'enc(autoclave)': None,
23+
'enc(autoclave-queenly)': {'ATTACKATDAWN': 'QNXEPVYTWTWP'},
24+
'enc-dec(autoclave-key)': ['hello world', 'ATTACK AT DAWN', 'Test 1234!', 'Mixed Case 123'],
25+
}
26+
__guess__ = ["autoclave-key", "autoclave-secret", "autoclave-password"]
27+
28+
29+
def __check(key):
30+
key = key.lower()
31+
if not key or not key.isalpha():
32+
raise LookupError("Bad parameter for encoding 'autoclave': key must be a non-empty alphabetic string")
33+
return key
34+
35+
36+
def autoclave_encode(key):
37+
def encode(text, errors="strict"):
38+
k = __check(key)
39+
text_str = ensure_str(text)
40+
alpha_chars = [c.lower() for c in text_str if c in LC or c in UC]
41+
key_stream = k + "".join(alpha_chars)
42+
result = []
43+
ki = 0
44+
for c in text_str:
45+
if c in LC:
46+
result.append(LC[(ord(c) - ord('a') + ord(key_stream[ki]) - ord('a')) % 26])
47+
ki += 1
48+
elif c in UC:
49+
result.append(UC[(ord(c) - ord('A') + ord(key_stream[ki]) - ord('a')) % 26])
50+
ki += 1
51+
else:
52+
result.append(c)
53+
r = "".join(result)
54+
return r, len(r)
55+
return encode
56+
57+
58+
def autoclave_decode(key):
59+
def decode(text, errors="strict"):
60+
k = __check(key)
61+
text_str = ensure_str(text)
62+
result = []
63+
key_stream = list(k)
64+
ki = 0
65+
for c in text_str:
66+
if c in LC:
67+
dec_c = LC[(ord(c) - ord('a') - (ord(key_stream[ki]) - ord('a'))) % 26]
68+
result.append(dec_c)
69+
key_stream.append(dec_c)
70+
ki += 1
71+
elif c in UC:
72+
dec_c = UC[(ord(c) - ord('A') - (ord(key_stream[ki]) - ord('a'))) % 26]
73+
result.append(dec_c)
74+
key_stream.append(dec_c.lower())
75+
ki += 1
76+
else:
77+
result.append(c)
78+
r = "".join(result)
79+
return r, len(r)
80+
return decode
81+
82+
83+
add("autoclave", autoclave_encode, autoclave_decode,
84+
r"auto(?:clave|key)(?:[-_]cipher)?(?:[-_]([a-zA-Z]+))?$", penalty=.1)

0 commit comments

Comments
 (0)