cipher.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import random
from itertools import cycle
from string import ascii_lowercase as alphabet


def random_string(length):
    """
    Return random lowercase string of given length
    """
    return ''.join(random.choice(alphabet) for i in range(0, length + 1))


def wrap_lowercase(code):
    """
    Wrap char code back around to range of lower case letters

    :return: lower case character
    """
    return chr(((code - ord('a')) % 26) + ord('a'))


def lowercase_chars(text):
    """Extract lower case characters from text

    :return: iterator of chars
    """
    return filter(lambda c: c in alphabet, text.lower())


class Caesar:
    shifted_alphabet = alphabet[3:] + alphabet[:3]

    def encode(self, text):
        return ''.join(
            self.shifted_alphabet[ord(c) - ord('a')]
            for c in lowercase_chars(text)
        )

    def decode(self, text):
        return ''.join(
            chr(ord('a') + self.shifted_alphabet.index(c))
            for c in text
        )


class Cipher:
    def __init__(self, key=''):
        if key == '':
            self.key = random_string(length=100)
        elif key.islower() and key.isalpha():
            self.key = key
        else:
            raise ValueError('Invalid cipher key')

    @property
    def key_offsets(self):
        """
        Stream offset values from the cipher key
        Each value is the offset of the relevant key character from 'a'

        :return: iterator of offset values
        """
        return cycle(ord(c) - ord('a') for c in self.key)

    def encode(self, text):
        """Encode text"""
        return ''.join(
            wrap_lowercase(ord(c) + k)
            for c, k in zip(lowercase_chars(text), self.key_offsets)
        )

    def decode(self, text):
        """Decode text"""
        return ''.join(
            wrap_lowercase(ord(c) - k)
            for c, k in zip(lowercase_chars(text), self.key_offsets)
        )

Comments


You're not logged in right now. Please login via GitHub to comment