byte_at_a_time_ecb_decryption_harder.py (2435B)
1 from Crypto.Cipher import AES 2 from Crypto import Random 3 from Crypto.Random import random 4 5 pt1 = "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgn" 6 pt2 = "aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqn" 7 pt3 = "dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgn" 8 pt4 = "YnkK" 9 10 key = Random.new().read(AES.block_size) 11 plaintext = str(pt1 + pt2 + pt3 + pt4).decode("base64") # no peeking! 12 rand_buffer = Random.new().read(random.randint(0, 100)) 13 14 def encryption_oracle(msg): 15 pad_len = AES.block_size - (len(rand_buffer + msg + plaintext) % AES.block_size) 16 return AES.new(key, AES.MODE_ECB).encrypt(rand_buffer + msg + plaintext + ''.join([chr(pad_len) for i in range(pad_len)])) 17 18 def len_of_prefix(): 19 prefix_len = -1 20 a_blocks = b_blocks = [] 21 22 for i in range(AES.block_size): 23 estimate = 0 24 cipher_a = encryption_oracle(''.join('x00' for j in range(i))) 25 cipher_b = encryption_oracle(''.join("x00" for j in range(i + 1))) 26 a_blocks = [cipher_a[j:j + AES.block_size] for j in range(0, len(cipher_a), AES.block_size)] 27 b_blocks = [cipher_b[j:j + AES.block_size] for j in range(0, len(cipher_b), AES.block_size)] 28 29 for a, b in zip(a_blocks, b_blocks): 30 if a == b: 31 estimate += AES.block_size 32 else: 33 if prefix_len == -1: 34 prefix_len = estimate 35 if prefix_len != estimate: 36 return prefix_len + AES.block_size - i 37 break 38 39 return sum([AES.block_size if a == b else 0 for a, b in zip(a_blocks, b_blocks)]) 40 41 def len_of_padding(): 42 for i in range(AES.block_size): 43 if len(encryption_oracle(''.join('x00' for j in range(i)))) != len(encryption_oracle(''.join('x00' for j in range(i + 1)))): 44 return i + 1 45 46 prefix = len_of_prefix() 47 mod = AES.block_size - prefix % AES.block_size 48 buf = aaa = "AAAAAAAAAAAAAAA" 49 aa = ''.join("A" for i in range(mod)) 50 51 for i in range(len(encryption_oracle('')) - prefix - len_of_padding()): 52 dict = {encryption_oracle(aa + aaa[i:] + chr(j))[mod + prefix : mod + prefix + AES.block_size] : chr(j) for j in range(256)} 53 cipher = encryption_oracle(aa + buf[i % AES.block_size:]) 54 aaa += dict[cipher[mod + prefix + (AES.block_size * (i / AES.block_size)) : mod + prefix + (AES.block_size * ((i + AES.block_size) / AES.block_size))]] 55 56 print aaa[AES.block_size - 1:]