cryptopals

https://cryptopals.com/
Log | Files | Refs

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:]