-
Notifications
You must be signed in to change notification settings - Fork 0
/
cryptopals_18.py
executable file
·53 lines (35 loc) · 1.28 KB
/
cryptopals_18.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
#!/usr/bin/env python
from base64 import b64decode
from cryptopals_10 import xor
from cryptopals_13 import aes_encrypt
BLOCK_SIZE = 16
KEY = b'YELLOW SUBMARINE'
NONCE = 0
TEST_INPUT = b'L77na/nrFsKvynd6HzOoG7GHTLXsTVu9qvY/2syLXzhPweyyMTJULu/6/kXX0KSvoOLSFQ=='
EXPECTED_OUTPUT = b"Yo, VIP Let's kick it Ice, Ice, baby Ice, Ice, baby "
def aes_keystream(key: bytes, nonce: int) -> bytes:
"""Generator returning blocks of keystream.
"""
nonce_chunk = nonce.to_bytes(BLOCK_SIZE // 2, byteorder='little')
counter = 0
while True:
block = nonce_chunk + counter.to_bytes(BLOCK_SIZE // 2, byteorder='little')
yield aes_encrypt(key, block)
counter += 1
def aes_ctr(key: bytes, nonce: int, msg: bytes) -> bytes:
"""Encrypts or decrypts a message using AES in CTR mode.
"""
output = []
i = 0
for keystream in aes_keystream(KEY, NONCE):
block = msg[i:i+BLOCK_SIZE]
output.append(xor(block, keystream))
i += BLOCK_SIZE
if i >= len(msg):
break
return b''.join(output)
if __name__ == '__main__':
print('Challenge #18 - Implement CTR, the stream cipher mode')
ciphertext = b64decode(TEST_INPUT)
plaintext = aes_ctr(KEY, NONCE, ciphertext)
assert plaintext == EXPECTED_OUTPUT