Skip to content

Instantly share code, notes, and snippets.

@bricef
Created September 8, 2016 20:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bricef/f6e39b09dc0e9f7c287fdab0beb66545 to your computer and use it in GitHub Desktop.
Save bricef/f6e39b09dc0e9f7c287fdab0beb66545 to your computer and use it in GitHub Desktop.
Padding Oracle attack example in python
#!/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