Skip to content

Commit 74af18c

Browse files
committed
Fixed codec: atbash
1 parent 4890884 commit 74af18c

3 files changed

Lines changed: 30 additions & 22 deletions

File tree

codext/crypto/atbash.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,23 @@
1212
from ..__common__ import *
1313

1414

15-
__guess__ = []
15+
__guess__ = ["atbash"]
1616

1717

1818
def encmap_factory(mask=None):
19-
alphabet = get_alphabet_from_mask(mask or "?l?u?s")
20-
return {k: v for k, v in zip(alphabet, alphabet[::-1])}
21-
22-
23-
add_map("atbash", encmap_factory, pattern=r"atbash(?:[-_]cipher)?(?:[-_](.+))?$")
19+
mask = mask or "?u?l"
20+
# [...] enclosure causes the mask to be handled as a whole
21+
if mask[0] == "[" and mask[-1] == "]":
22+
alphabet = get_alphabet_from_mask(mask[1:-1])
23+
return {k: v for k, v in zip(alphabet, alphabet[::-1])}
24+
# not enclosing the whole mask means that each group is to be considered separately
25+
else:
26+
m = {}
27+
for group in re.findall(r"(\?.|[^?]+)", mask):
28+
alphabet = get_alphabet_from_mask(group)
29+
m.update({k: v for k, v in zip(alphabet, alphabet[::-1])})
30+
return m
31+
32+
33+
add_map("atbash", encmap_factory, no_error=True, pattern=r"atbash(?:[-_]cipher)?(?:[-_](.+))?$")
2434

docs/enc/crypto.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ This codec implements the Affine monoalphabetic substitution cipher. It is param
5454

5555
### Atbash Cipher
5656

57-
It implements the monoalphabetic substitution cipher used for the Hebrew alphabet. By default, it considers the lowercase and uppercase letters and the whitespace for the alphabet. It can also use a mask to extend it.
57+
It implements the monoalphabetic substitution cipher used for the Hebrew alphabet. By default, it considers the lowercase and uppercase letters, inverted per group, as the alphabet. It can also use a mask to extend it. Note that it does not generate any error for characters that are not part of the alphabet.
5858

5959
**Codec** | **Conversions** | **Aliases** | **Comment**
6060
:---: | :---: | --- | ---
61-
`atbash` | text <-> Atbash ciphertext | `atbash`, `atbash_cipher-?l?d?s`, ... | Mask-generated alphabet ; uses default mask "`?l?u?s`"
61+
`atbash` | text <-> Atbash ciphertext | `atbash`, `atbash_cipher-?l?d?s`, ... | Mask-generated alphabet ; uses default mask "`?u?l`"
6262

6363
```python
6464
>>> codext.encode("this is a test", "atbash")
65-
'HTSIaSIa aHWIH'
66-
>>> codext.encode("this is a test", "atbash-?l?u?p?s")
65+
'gsrh rh z gvhg'
66+
>>> codext.encode("this is a test", "atbash-[?l?u?p?s]")
6767
'.^]/a]/a a.{/.'
68-
>>> codext.decode(".^]/a]/a a.{/.", "atbash_cipher_?l?u?p?s")
68+
>>> codext.decode(".^]/a]/a a.{/.", "atbash_cipher_[?l?u?p?s]")
6969
'this is a test'
7070
```
7171

tests/test_manual.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,21 @@ def test_codec_affine(self):
5555
self.assertRaises(LookupError, codecs.encode, STR, "affine-?l?u?d?s-6,8")
5656

5757
def test_codec_atbash(self):
58-
STR = "this is a test"
59-
ATB1 = "HTSIaSIa aHWIH"
60-
self.assertRaises(ValueError, codecs.encode, "test", "atbash-whatever")
58+
STR = "This is a test"
59+
ATB1 = "Gsrh rh z gvhg"
6160
self.assertIsNotNone(codecs.encode("test", "atbash-whatevers"))
6261
# uses by default an alphabet with lowercase and uppercase
63-
self.assertEqual(codecs.encode(STR, "atbash"), codecs.encode(STR, "atbash-?l?u?s"))
62+
self.assertEqual(codecs.encode(STR, "atbash"), codecs.encode(STR, "atbash-?l?u"))
63+
self.assertNotEqual(codecs.encode(STR, "atbash"), codecs.encode(STR, "atbash-[?l?u]"))
6464
self.assertEqual(codecs.encode(STR, "atbash_cipher"), ATB1)
6565
self.assertEqual(codecs.encode(b(STR), "atbash-cipher"), b(ATB1))
6666
self.assertEqual(codecs.decode(ATB1, "atbash"), STR)
6767
self.assertEqual(codecs.decode(b(ATB1), "atbash"), b(STR))
68-
ATB2 = ".^]/a]/a a.{/."
69-
self.assertEqual(codecs.encode(STR, "atbash-?l?u?p?s"), ATB2)
70-
self.assertEqual(codecs.encode(b(STR), "atbash_cipher-?l?u?p?s"), b(ATB2))
71-
self.assertEqual(codecs.decode(ATB2, "atbash-?l?u?p?s"), STR)
72-
self.assertEqual(codecs.decode(b(ATB2), "atbash_cipher-?l?u?p?s"), b(STR))
73-
# trying to decode with a non-matching alphabet
74-
self.assertRaises(ValueError, codecs.decode, ATB2, "atbash")
68+
ATB2 = "N^]/a]/a a.{/."
69+
self.assertEqual(codecs.encode(STR, "atbash-[?l?u?p?s]"), ATB2)
70+
self.assertEqual(codecs.encode(b(STR), "atbash_cipher-[?l?u?p?s]"), b(ATB2))
71+
self.assertEqual(codecs.decode(ATB2, "atbash-[?l?u?p?s]"), STR)
72+
self.assertEqual(codecs.decode(b(ATB2), "atbash_cipher-[?l?u?p?s]"), b(STR))
7573

7674
def test_codec_dummy_str_manips(self):
7775
STR = "this is a test"

0 commit comments

Comments
 (0)