-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathchallenge24.py
More file actions
66 lines (53 loc) · 1.91 KB
/
challenge24.py
File metadata and controls
66 lines (53 loc) · 1.91 KB
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
from Cryptodome.Util.strxor import strxor
from Cryptodome.Random import get_random_bytes
from Cryptodome.Random.random import getrandbits, randint
import challenge21
import struct
import time
class MT19937Cipher:
def __init__(self, key):
self._rng = challenge21.MT19937(key & 0xffff)
self._keybytes = b''
def encrypt(self, plaintext):
# Work around strxor() not handling zero-length strings
# gracefully.
if len(plaintext) == 0:
return b''
keystream = self._keybytes
while len(keystream) < len(plaintext):
keyblock = struct.pack('<L', self._rng.uint32())
keystream += keyblock
if len(keystream) > len(plaintext):
self._keybytes = keystream[len(plaintext):]
keystream = keystream[:len(plaintext)]
return strxor(plaintext, keystream)
def decrypt(self, ciphertext):
return self.encrypt(ciphertext)
key = getrandbits(16)
def encryption_oracle(plaintext):
prefix = get_random_bytes(randint(4, 20))
cipher = MT19937Cipher(key)
return cipher.encrypt(prefix + plaintext)
def recover_key(encryption_oracle):
plaintext = b'0' * 14
ciphertext = encryption_oracle(plaintext)
prefix_len = len(ciphertext) - len(plaintext)
for i in range(2**16-1):
cipher = MT19937Cipher(i)
s = cipher.encrypt(b'0' * len(ciphertext))
if ciphertext[prefix_len:] == s[prefix_len:]:
return i
raise Exception('unexpected')
print(key, recover_key(encryption_oracle))
def token_oracle():
seed = int(time.time())
cipher = MT19937Cipher(seed)
plaintext = b'0' * randint(4, 20)
return cipher.encrypt(plaintext)
def is_token_for_current_time(token):
seed = int(time.time())
cipher = MT19937Cipher(seed)
plaintext = b'0' * len(token)
return cipher.encrypt(plaintext) == token
x = token_oracle()
print(x, is_token_for_current_time(x))