-
Notifications
You must be signed in to change notification settings - Fork 121
/
separator_oracle.py
45 lines (40 loc) · 1.38 KB
/
separator_oracle.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
def _find_separator_positions(separator_oracle, c):
separator_positions = []
c = bytearray(c)
for i in range(len(c)):
c[i] ^= 1
valid = separator_oracle(c)
c[i] ^= 1
if not valid:
c[i] ^= 2
valid = separator_oracle(c)
c[i] ^= 2
if not valid:
separator_positions.append(i)
return separator_positions
def attack(separator_oracle, separator_byte, c):
"""
Recovers the plaintext using the separator oracle attack.
:param separator_oracle: the separator oracle, returns True if the separators are correct, False otherwise
:param separator_byte: the separator which is used in the separator oracle
:param c: the ciphertext
:return: the plaintext
"""
separator_positions = _find_separator_positions(separator_oracle, c)
c = bytearray(c)
# Ensure that at least 1 separator is missing.
c[separator_positions[0]] ^= 1
p = bytearray(len(c))
for i in range(len(c)):
if i in separator_positions:
p[i] = separator_byte
else:
c_i = c[i]
# Try every byte until an additional separator is created.
for b in range(256):
c[i] = b
if separator_oracle(c):
p[i] = c_i ^ c[i] ^ separator_byte
break
c[i] = c_i
return p