Skip to content

Commit 9b8d574

Browse files
committed
Refined codec: vigenere
1 parent 1629399 commit 9b8d574

File tree

3 files changed

+53
-10
lines changed

3 files changed

+53
-10
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ This category also contains `ascii85`, `adobe`, `[x]btoa`, `zeromq` with the `ba
291291
- [X] `rotN`: aka Caesar cipher (*N* belongs to [1,25])
292292
- [X] `scytaleN`: encrypts using the number of letters on the rod (*N* belongs to [1,[)
293293
- [X] `shiftN`: shift ordinals (*N* belongs to [1,255])
294+
- [X] `trithemius`: aka Trithemius Cipher (variant of Vigenere Cipher)
294295
- [X] `vigenere`: aka Vigenere Cipher
295296
- [X] `xorN`: XOR with a single byte (*N* belongs to [1,255])
296297

docs/pages/enc/crypto.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ It implements the cipher for its 4 different keys.
109109

110110
-----
111111

112+
### Beaufort Cipher
113+
114+
This is a variant of the [Vigenere Cipher](#vigenere-cipher). There is no default key, meaning that `beaufort` as the encoding scheme throws a `LookupError` indicating that the _key must be a non-empty alphabetic string_.
115+
116+
**Codec** | **Conversions** | **Aliases** | **Comment**
117+
:---: | :---: | --- | ---
118+
`beaufort` | text <-> Beaufort ciphertext | `beaufort-abcdef`, `beaufort_MySuperSecret` | key only consists of characters, not digits
119+
120+
```python
121+
>>> codext.encode("This is a test !", "beaufort-abababa")
122+
'Husj sj a hxii !'
123+
>>> codext.encode("This is a test !", "beaufort_MySuperSecret")
124+
'Trkc hm r zaky !'
125+
>>> codext.decode("Husj sj a hxii !", "vigenere-abababa")
126+
'This is a test !'
127+
```
128+
129+
-----
130+
112131
### Citrix CTX1
113132

114133
This implements the Citrix CTX1 password encoding algorithm.
@@ -202,6 +221,23 @@ This is a dynamic encoding, that is, it can be called with an integer to define
202221

203222
-----
204223

224+
### Trithemius Cipher
225+
226+
This is a variant of the [Vigenere Cipher](#vigenere-cipher) with key `"ABCDEFGHIJKLMNOPQRSTUVWXYZ"`.
227+
228+
**Codec** | **Conversions** | **Aliases** | **Comment**
229+
:---: | :---: | --- | ---
230+
`trithemius` | text <-> Trithemius ciphertext | `trithemius`, `trithemius_cipher` |
231+
232+
```python
233+
>>> codext.encode("This is a test !", "trithemius")
234+
'Tikv mx g ambd !'
235+
>>> codext.decode("Tikv mx g ambd !", "trithemius")
236+
'This is a test !'
237+
```
238+
239+
-----
240+
205241
### Vigenere Cipher
206242

207243
This is a dynamic encoding, that is, it holds the key. There is no default key, meaning that `vigenere` as the encoding scheme throws a `LookupError` indicating that the _key must be a non-empty alphabetic string_.
@@ -216,6 +252,7 @@ This is a dynamic encoding, that is, it holds the key. There is no default key,
216252
>>> codext.encode("This is a test !", "vigenere_MySuperSecret")
217253
'Ffam xw r liuk !'
218254
>>> codext.decode("Tiit it a tfsu !", "vigenere-abababa")
255+
'This is a test !'
219256
```
220257

221258
-----

src/codext/crypto/vigenere.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,43 @@
1111

1212
from ..__common__ import *
1313

14-
1514
__examples__ = {
1615
'enc(beaufort)': None,
1716
'enc(beaufort-lemon)': {'ATTACKATDAWN': 'LLTOLBETLNPR'},
1817
'enc(beaufort-key)': {'hello': 'danzq'},
1918
'enc(beaufort_key)': {'Hello World': 'Danzq Cwnnh'},
20-
'enc-dec(beaufort-secret)': ['hello world', 'ATTACK AT DAWN', 'Test 1234!'],
19+
'enc(trithemius-cipher)': {'this is a test': "tikv mx g ambd"},
20+
'enc(trithemius)': {'HELLO': "HFNOS", '12345!@#$': "12345!@#$"},
2121
'enc(vigenere)': None,
2222
'enc(vigenere-lemon)': {'ATTACKATDAWN': 'LXFOPVEFRNHR'},
2323
'enc(vigenere-key)': {'hello': 'rijvs'},
2424
'enc(vigenère_key)': {'Hello World': 'Rijvs Uyvjn'},
25+
'enc-dec(beaufort-secret)': ['hello world', 'ATTACK AT DAWN', 'Test 1234!'],
26+
'enc-dec(trithemius)': ["Hello, World!", "@random"],
2527
'enc-dec(vigenere-secret)': ['hello world', 'ATTACK AT DAWN', 'Test 1234!'],
2628
}
27-
__guess__ = ["beaufort-key", "beaufort-secret", "beaufort-password",
29+
__guess__ = ["beaufort-key", "beaufort-secret", "beaufort-password", "trithemius",
2830
"vigenere-key", "vigenere-secret", "vigenere-password"]
2931

3032

31-
def __make(encoding, char_func):
33+
def __make(enc, cfunc):
3234
def code(decode=False):
33-
def _code(key):
34-
def _wrapper(text, errors="strict"):
35+
def _wrapper(key):
36+
def _subwrapper(text, errors="strict"):
3537
k = key.lower()
3638
if not k or not k.isalpha():
37-
raise LookupError(f"Bad parameter for encoding '{encoding}': key must be a non-empty alphabetic string")
39+
raise LookupError(f"Bad parameter for encoding '{enc}': key must be a non-empty alphabetic string")
3840
result, i = [], 0
3941
for c in ensure_str(text):
4042
if c in LC or c in UC:
41-
result.append(char_func(c, k, i, decode))
43+
result.append(cfunc(c, k, i, decode))
4244
i += 1
4345
else:
4446
result.append(c)
4547
r = "".join(result)
4648
return r, len(r)
47-
return _wrapper
48-
return _code
49+
return _subwrapper
50+
return _wrapper
4951
return code(), code(True)
5052

5153

@@ -55,5 +57,8 @@ def _wrapper(text, errors="strict"):
5557

5658
vchar = lambda c, k, i, d=False: (LC if (b := c in LC) else UC)[(ord(c) - ord("Aa"[b]) + \
5759
[1, -1][d] * (ord(k[i % len(k)]) - ord('a'))) % 26]
60+
enc, dec = __make("trithemius", vchar)
61+
add("trithemius", enc(k := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), dec(k), r"trithemius(?:[-_]cipher)?$", penalty=.1)
62+
5863
add("vigenere", *__make("vigenere", vchar), r"vigen[eè]re(?:[-_]cipher)?(?:[-_]([a-zA-Z]+))?$", penalty=.1)
5964

0 commit comments

Comments
 (0)