-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxor_and_one_time_pad.py
117 lines (99 loc) · 3.47 KB
/
xor_and_one_time_pad.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
This is an implementation of One Time Pad Implemented here(./one_time_pad) using the XOR bitwise operation
rather than using addition and subtraction of shift number.
Why XOR?
https://www.khanacademy.org/computing/computer-science/cryptography/ciphers/a/xor-and-the-one-time-pad
"""
from random import randint
import ciphers.one_time_pad as one_time_pad
class XOR_One_Time_Pad(one_time_pad.One_Time_Pad):
"""
STEPS:
1. Generate a list of random numbers the length of the word to be encrypted.
2. Convert every letter of the word to be encrypted to number according the their place in the letters of the alphabet.
E.g a -> 1, z -> 26
3. Perform XOR on the number from the list of random numbers and the numbers gotten from the Step 2.
E.g random numbers = [23, 14, 11, 16], letter_conversions = [22, 12, 9, 1], xors = [(23 XOR 22), (14 XOR 12), (11 XOR 9), (16 XOR 1)]
4. Shift each letter by the result of the XOR operation
5. Perform xor on the random numbers and original xor values to decrypt
"""
letters = [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z"]
def generate_numbers(self, length: int) -> list[int]:
random_numbers = []
for i in range(length):
random_number = randint(0, 25)
random_numbers.append(random_number)
return random_numbers
def letter_to_number(self, word: str) -> list[int]:
numbers = []
for letter in word.lower().strip():
index = self.letters.index(letter)
numbers.append(index)
return numbers
def _xor(self, letter_numbers: list[int], random_numbers: list[int]):
if len(letter_numbers) != len(random_numbers):
raise Exception("Invalid length")
numbers = []
for (
letter_number,
random_number) in zip(
letter_numbers,
random_numbers):
numbers.append(letter_number ^ random_number)
return numbers
def _shift(self, _num_of_shifts: int) -> str:
new_index = _num_of_shifts % 26
return self.letters[new_index]
def encrypt(self, word: str, random_numbers: list[int]) -> str:
if len(word) != len(random_numbers):
raise Exception("invalid length")
letter_numbers = self.letter_to_number(word)
xor_numbers = self._xor(letter_numbers, random_numbers)
print(
"Encrypted:",
f"Letter numbers: {letter_numbers}",
f"Random numbers: {random_numbers}",
f"XOR numbers: {xor_numbers}")
new_word = ""
for number in xor_numbers:
new_letter = self._shift(number)
new_word += new_letter
return new_word
def decrypt(
self,
random_numbers: list[int],
original_xor_numbers: list[int]) -> str:
if len(random_numbers) != len(random_numbers):
raise Exception("invalid length")
xor_numbers = self._xor(random_numbers, original_xor_numbers)
new_word = ""
for number in xor_numbers:
new_letter = self._shift(number)
new_word += new_letter
return new_word