Created
September 8, 2016 20:56
-
-
Save bricef/f6e39b09dc0e9f7c287fdab0beb66545 to your computer and use it in GitHub Desktop.
Padding Oracle attack example in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import random | |
import sys | |
from Crypto.Cipher import AES | |
BLOCK_SIZE = 16 # bytes | |
INIT_VEC = 'This is an IV456' # hardcoding this is a terrible idea | |
EXAMPLE_TEXT = """Friends, Romans, countrymen, lend me your ears; | |
I come to bury Caesar, not to praise him. | |
The evil that men do lives after them; | |
The good is oft interred with their bones; | |
So let it be with Caesar. The noble Brutus | |
Hath told you Caesar was ambitious: | |
If it were so, it was a grievous fault, | |
And grievously hath Caesar answer’d it. | |
Here, under leave of Brutus and the rest– | |
For Brutus is an honourable man; | |
So are they all, all honourable men– | |
Come I to speak in Caesar’s funeral. | |
He was my friend, faithful and just to me: | |
But Brutus says he was ambitious; | |
And Brutus is an honourable man. | |
He hath brought many captives home to Rome | |
Whose ransoms did the general coffers fill: | |
Did this in Caesar seem ambitious? | |
When that the poor have cried, Caesar hath wept: | |
Ambition should be made of sterner stuff: | |
Yet Brutus says he was ambitious; | |
And Brutus is an honourable man. | |
You all did see that on the Lupercal | |
I thrice presented him a kingly crown, | |
Which he did thrice refuse: was this ambition? | |
Yet Brutus says he was ambitious; | |
And, sure, he is an honourable man. | |
I speak not to disprove what Brutus spoke, | |
But here I am to speak what I do know. | |
You all did love him once, not without cause: | |
What cause withholds you then, to mourn for him? | |
O judgment! thou art fled to brutish beasts, | |
And men have lost their reason. Bear with me; | |
My heart is in the coffin there with Caesar, | |
And I must pause till it come back to me.""" | |
class InvalidPadding(Exception): | |
pass | |
def blockify(text, block_size=BLOCK_SIZE): | |
return [text[i:i+block_size] for i in range(0, len(text), block_size)] | |
def key_gen(): | |
return "".join([chr(random.getrandbits(8)) for _ in xrange(BLOCK_SIZE)]) | |
def validate_padding(padded_text): | |
return all([n == padded_text[-1] for n in padded_text[-ord(padded_text[-1]):]]) | |
def pkcs7_pad(text): | |
length = BLOCK_SIZE - (len(text) % BLOCK_SIZE) | |
text += chr(length) * length | |
return text | |
def pkcs7_depad(text): | |
if not validate_padding(text): | |
raise InvalidPadding() | |
return text[:-ord(text[-1])] | |
def encrypt(plaintext, key, init_vec): | |
cipher = AES.new(key, AES.MODE_CBC, init_vec) | |
padded_text = pkcs7_pad(plaintext) | |
ciphertext = cipher.encrypt(padded_text) | |
return ciphertext | |
def decrypt(ciphertext, key, init_vec): | |
cipher = AES.new(key, AES.MODE_CBC, init_vec) | |
padded_text = cipher.decrypt(ciphertext) | |
plaintext = pkcs7_depad(padded_text) | |
return plaintext | |
def numberify(characters): | |
return map(lambda x: ord(x), characters) | |
def stringify(numbers): | |
return "".join(map(lambda x: chr(x), numbers)) | |
if __name__ == "__main__": | |
my_key = key_gen() | |
IV = numberify(INIT_VEC) | |
ciphertext = numberify(encrypt(EXAMPLE_TEXT, my_key, INIT_VEC)) | |
blocks = blockify(ciphertext) | |
cleartext = [] | |
for block_num, (c1, c2) in enumerate(zip([IV]+blocks, blocks)): | |
print "cracking block {} out of {}".format(block_num+1, len(blocks)) | |
i2 = [0] * 16 | |
p2 = [0] * 16 | |
for i in xrange(15,-1,-1): | |
for b in xrange(0,256): | |
prefix = c1[:i] | |
pad_byte = (BLOCK_SIZE-i) | |
suffix = [pad_byte ^ val for val in i2[i+1:]] | |
evil_c1 = prefix + [b] + suffix | |
try: | |
decrypt(stringify(c2), my_key, stringify(evil_c1)) | |
except InvalidPadding: | |
pass | |
else: | |
i2[i] = evil_c1[i] ^ pad_byte | |
p2[i] = c1[i] ^ i2[i] | |
break | |
cleartext+=p2 | |
# print "i2:", i2 | |
# print "c2:", c2 | |
# print "p2:", p2 | |
# print "block:[{}]".format(stringify(p2)) | |
# print "expected:[{}]".format(EXAMPLE_TEXT[(16 * block_num):(16 * block_num)+16]) | |
print "=========================" | |
print stringify(cleartext) | |
print "=========================" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment