def ctr_bitflip_attack(): k = os.urandom(16) nonce = os.urandom(8) #"comment1=cooking" "%20MCs;userdata=" #";comment2=%%0lik" "e%20a%20pound%20of%20bacon" # ctr mode is a simple XOR of keystream byte and plaintext byte # If we use this: "0admin0true" as the plaintext # We want to flip the first 0 to ';' and the second 0 to '=' # So if we use \x00 as 0, then we will get the keystream byte # in the ciphertext. Then we just XOR with the desired byte. s1 = "comment1=cooking%20MCs;userdata=" s2 = ";comment2=%20like%20a%20pound%20of%20bacon" plaintext = 'A' + "\x00admin\x00true" print "plaintext: ", repr(s1 + plaintext + s2) ciphertext = aes_ctr_oracle(k, plaintext, nonce) # offsets are len(s1)+1 and len(s1)+8 off1 = len(s1)+1 off2 = len(s1)+7 ciphertext = ciphertext[:off1] + xor(ciphertext[off1], ';') + ciphertext[off1+1:off2] + xor(ciphertext[off2], '=') + ciphertext[off2+1:] assert len(ciphertext) == len(s1+plaintext+s2) print "Check returns ", check_ctr_bitflip(k, ciphertext, nonce)
def recover_key_from_iv_equals_key(): k = os.urandom(16) print "Key is ", repr(k) ciphertext = aes_cbc_enc_oracle(k, 'A') #print aes_cbc_dec_oracle(k, ciphertext) c1 = ciphertext[:16] c2 = '\x00'*16 c3 = c1 # receiver would throw an error here p = aes_cbc_dec_oracle(k, c1+c2+c3) p1 = p[:16] p3 = p[32:48] recovered_key = xor(p1,p3) print "Recovered key ", repr(recovered_key) return k == recovered_key
def aes_cbc_decrypt(key, text, iv): block_size = len(key) if block_size != 16: raise "Block size for AES must be 16" out = [] assert len(iv) == 16 carry = iv for i in range(0, len(text), block_size): block = text[i:i+block_size] # do the crypto out_block = aes_ecb_decrypt_no_padding(key, block) # take out the carry over out_block = xor(carry, out_block) out.append(out_block) # new carry carry = block return "".join(out)