def test_encrypt_decrypt_aes_ecb_mode(): plaintext = os.urandom(64) key = os.urandom(16) ciphertext = set1.encrypt_aes_ecb_mode(plaintext, key) assert set1.decrypt_aes_ecb_mode( ciphertext, key) == plaintext, "Encrypting and decrypting should give us plaintext"
def encrypt_aes_cbc_mode(plaintext, key, iv): """Encrypt plaintext with AES in CBC mode, using provided key and iv (initialization vector) """ assert len(key) == len(iv), "Key and initialization vector must be same length" pt_blocks = bytes_to_padded_blocks(plaintext, len(key)) ciphertext = b'' xor_with = iv # Initially, we XOR plaintext with IV # For each block, xor plaintext with xor_with, then encrypt and append to ciphertext. # Each successive plaintext block is XORed with the previous ciphertext block before encryption. for pt_block in pt_blocks: new_ct_block = set1.encrypt_aes_ecb_mode(set1.fixed_xor(pt_block, xor_with), key) ciphertext = ciphertext + new_ct_block xor_with = new_ct_block return ciphertext
def encrypt_aes_cbc_mode(plaintext, key, iv): """Encrypt plaintext with AES in CBC mode, using provided key and iv (initialization vector) """ assert len(key) == len( iv), "Key and initialization vector must be same length" pt_blocks = bytes_to_padded_blocks(plaintext, len(key)) ciphertext = b'' xor_with = iv # Initially, we XOR plaintext with IV # For each block, xor plaintext with xor_with, then encrypt and append to ciphertext. # Each successive plaintext block is XORed with the previous ciphertext block before encryption. for pt_block in pt_blocks: new_ct_block = set1.encrypt_aes_ecb_mode( set1.fixed_xor(pt_block, xor_with), key) ciphertext = ciphertext + new_ct_block xor_with = new_ct_block return ciphertext
def byte_at_time_ecb_oracle(plaintext): """Challenge 12 - Encrypts given plaintext using a random but consistent key - Appends 'secret' base64-encoded string to plaintext before encryption - Returns ciphertext Using the random package rather than os.urandom() because it can be seeded for testing """ global key_for_byte_at_time_ecb_oracle secret_string_b64 = b'Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg' \ b'aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq' \ b'dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg' \ b'YnkK' secret_string_bytes = base64.b64decode(secret_string_b64) padded_combined_pt = pkcs7_pad(plaintext + secret_string_bytes, 16) return set1.encrypt_aes_ecb_mode(padded_combined_pt, key_for_byte_at_time_ecb_oracle)
def encrypt_ecb_or_cbc_oracle(plaintext): """Challenge 11 - Encrypts plaintext using a random key - Pre-pends 5-10 random bytes to plaintext, appends 5-10 bytes to plaintext - With 50% probability of each, encrypts plaintext using ECB mode or CBC mode - Returns ciphertext We're using the random package rather than os.urandom() because it can be seeded for testing """ key = generate_random_aes_key(16) plaintext = _get_random_bytes(random.randint(5, 10)) \ + plaintext \ + _get_random_bytes(random.randint(5, 10)) if random.random() < 0.5: padded_pt = pkcs7_pad(plaintext, 16) return set1.encrypt_aes_ecb_mode(padded_pt, key) else: iv = _get_random_bytes(16) return encrypt_aes_cbc_mode(plaintext, key, iv)
def encrypt_profile(profile): """Challenge 13 Encrypts user profile with AES in ECB mode """ return set1.encrypt_aes_ecb_mode(pkcs7_pad(profile), key_for_ecb_cut_and_paste)
def test_encrypt_decrypt_aes_ecb_mode(): plaintext = os.urandom(64) key = os.urandom(16) ciphertext = set1.encrypt_aes_ecb_mode(plaintext, key) assert set1.decrypt_aes_ecb_mode(ciphertext, key) == plaintext, "Encrypting and decrypting should give us plaintext"