|
| 1 | +# -*- coding: UTF-8 -*- |
| 2 | +"""Vigenere Cipher Codec - vigenere content encoding. |
| 3 | +
|
| 4 | +This codec: |
| 5 | +- en/decodes strings from str to str |
| 6 | +- en/decodes strings from bytes to bytes |
| 7 | +- decodes file content to str (read) |
| 8 | +- encodes file content from str to bytes (write) |
| 9 | +""" |
| 10 | +from string import ascii_lowercase as LC, ascii_uppercase as UC |
| 11 | + |
| 12 | +from ..__common__ import * |
| 13 | + |
| 14 | + |
| 15 | +__examples__ = { |
| 16 | + 'enc(vigenere)': None, |
| 17 | + 'enc(vigenere-lemon)': {'ATTACKATDAWN': 'LXFOPVEFRNHR'}, |
| 18 | + 'enc(vigenere-key)': {'hello': 'rijvs'}, |
| 19 | + 'enc(vigenère_key)': {'Hello World': 'Rijvs Uyvjn'}, |
| 20 | + 'enc-dec(vigenere-secret)': ['hello world', 'ATTACK AT DAWN', 'Test 1234!'], |
| 21 | +} |
| 22 | +__guess__ = ["vigenere-key", "vigenere-secret", "vigenere-password"] |
| 23 | + |
| 24 | + |
| 25 | +__char = lambda c, k, i, d=False: (LC if (b := c in LC) else UC)[(ord(c) - ord("Aa"[b]) + \ |
| 26 | + [1, -1][d] * (ord(k[i % len(k)]) - ord('a'))) % 26] |
| 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 'vigenere': key must be a non-empty alphabetic string") |
| 33 | + return key |
| 34 | + |
| 35 | + |
| 36 | +def vigenere_encode(key): |
| 37 | + def encode(text, errors="strict"): |
| 38 | + result, i, k = [], 0, __check(key) |
| 39 | + for c in ensure_str(text): |
| 40 | + if c in LC or c in UC: |
| 41 | + result.append(__char(c, k, i)) |
| 42 | + i += 1 |
| 43 | + else: |
| 44 | + result.append(c) |
| 45 | + r = "".join(result) |
| 46 | + return r, len(r) |
| 47 | + return encode |
| 48 | + |
| 49 | + |
| 50 | +def vigenere_decode(key): |
| 51 | + def decode(text, errors="strict"): |
| 52 | + result, i, k = [], 0, __check(key) |
| 53 | + for c in ensure_str(text): |
| 54 | + if c in LC or c in UC: |
| 55 | + result.append(__char(c, k, i, True)) |
| 56 | + i += 1 |
| 57 | + else: |
| 58 | + result.append(c) |
| 59 | + r = "".join(result) |
| 60 | + return r, len(r) |
| 61 | + return decode |
| 62 | + |
| 63 | + |
| 64 | +add("vigenere", vigenere_encode, vigenere_decode, r"vigen[eè]re(?:[-_]cipher)?(?:[-_]([a-zA-Z]+))?$", penalty=.1) |
| 65 | + |
0 commit comments