-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchallenge17.py
82 lines (52 loc) · 1.97 KB
/
challenge17.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
import challenge12 as c12
import challenge11 as c11
import challenge9 as c9
import challenge6 as c6
import challenge10 as c10
import challenge15 as c15
import base64
import random as rd
plaintest = b"IRISHMAN AND IRISHWOMEN: In the name of God and of the dead generations from which she receives her old tradition of nationhood, Ireland, through us, summons her children to her flag and strikes for her freedom"
KEY = c12.randbytes(16)
IV = c12.randbytes(16)
with open("data/17.txt", "r") as f:
text = f.read().split("\n")
plaintext = base64.b64decode(rd.choice(text[:-1]))
def encrypt(plaintext: str) -> bytes:
plaintext = c9.PKCS7(bytes(plaintext), len(key))
return c11.CBC_encrypt(plaintext, key, iv)
def padding_oracle(cyphertext: bytes) -> bool:
plaintext = c10.CBC_decrypt(cyphertext, key, iv)
return c15.is_PKCS7(plaintext)
def break_byte(block: bytes, prev_block: bytes, found: bytes, n_byte, n):
pad_byte = (n - n_byte) + 1
c1_pre = bytes([0] * (n_byte - 1))
c1_post = bytes([pad_byte ^ f ^ (len(found) - i)
for i, f in enumerate(found[::-1])])
for i in range(256):
c1_dash = c1_pre + bytes([i]) + c1_post
if padding_oracle(c1_dash + block):
found_byte = i
plain_byte = bytes([prev_block[n_byte - 1] ^ pad_byte ^ found_byte])
return plain_byte, found_byte
def break_blocks(c1, c2, oracle, n):
known = []
found = []
for i in range(16):
p, f = break_byte(c2, c1, found, n - i, n)
known.append(p)
found.append(f)
return known
def break_CBC(cyphertext, oracle, n):
blocks = c6.chunks(cyphertext, n)
ans = ""
for i in range(len(blocks) - 1):
c1 = blocks[i]
c2 = blocks[i + 1]
a = break_blocks(c1, c2, oracle, n)
ans += "".join([i.decode() for i in a[::-1]])
return ans
if __name__ == "__main__":
n = len(key)
cyphertext = encrypt(plain_test)
decyphered = break_CBC(cyphertext, padding_oracle, n)