Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pwang00
GitHub Repository: pwang00/Cryptographic-Attacks
Path: blob/master/Symmetric Key/AES/padding_oracle/padding_oracle.py
336 views
1
from Crypto.Cipher import AES
2
from os import urandom
3
from base64 import b64decode
4
from pkcs7 import pkcs7
5
import random
6
7
BLOCKSIZE = 16
8
9
def xor(ctr, plaintext):
10
return bytearray((ctr[i] ^ plaintext[i] for i in range(len(ctr))))
11
12
def encrypt(key, ptext):
13
iv = urandom(16)
14
c = AES.new(key, AES.MODE_CBC, iv)
15
return iv + c.encrypt(bytes(pkcs7(ptext, BLOCKSIZE), "latin1"))
16
17
def decrypt(key, ctext):
18
iv = ctext[:16]
19
c = AES.new(key, AES.MODE_CBC, iv)
20
return c.decrypt(ctext)
21
22
def is_valid_pad(data):
23
return data[-data[-1]:].decode("latin1") == data[-1] * chr(data[-1])
24
25
def oracle(data):
26
key = open("key", "rb").read()
27
return is_valid_pad(decrypt(key, data))
28
29
def choose_message():
30
key = open("key", "rb").read()
31
data = encrypt(key, b64decode(random.choice(open("data").readlines())))
32
return data
33
34
def set_pad(Cn_1, I, lbound, target_pad):
35
for i in range(15, lbound, -1):
36
t = target_pad ^ target_pad - 1
37
Cn_1[i] = Cn_1[i] ^ t
38
I[i] = Cn_1[i] ^ target_pad
39
return Cn_1, I
40
41
def pkcs7_unpad(data):
42
return data[:-data[-1]]
43
44
def break_cbc(iv, prevblock, target):
45
P = bytearray(16)
46
prevblock = bytearray(prevblock)
47
Cn_1 = bytearray(urandom(16))
48
index = BLOCKSIZE - 1
49
pad = 1
50
I = bytearray(16)
51
while index >= 0:
52
for guess in range(256):
53
Cn_1[index] = guess
54
concat = iv + Cn_1 + target
55
if oracle(concat):
56
Cn_1, I = set_pad(Cn_1, I, index - 1, pad + 1)
57
break
58
pad += 1
59
index -= 1
60
61
P = xor(prevblock, I)
62
return P
63
64
def padding_oracle(data):
65
iv = data[:16]
66
data = [data[i:i+16] for i in range(16, len(data), 16)]
67
prev_block = iv
68
recovered = bytearray()
69
for block in data:
70
recovered += break_cbc(iv, prev_block, block)
71
prev_block = block
72
73
return pkcs7_unpad(recovered)
74
75
if __name__ == "__main__":
76
msg = choose_message()
77
print(padding_oracle(msg))
78
79
80