def decryption_via_oracle(): encryption = cbc_encrypt_random_line() target_ciphertext = encryption[0] target_iv = encryption[1] target_blocks = slice_target(target_ciphertext, 16) plaintext = b"" for i in range(len(target_blocks)): plaintext += recover_block_plaintext(target_blocks[i], target_iv) target_iv = target_blocks[i] return plaintext
def ctr(self, target): # Slice plaintext into blocks target_blocks = slice_target(target, self.keysize) # Initialize plaintext variable plaintext = b'' # Slice target into blocks blocks = slice_target(target, 16) # Iterate on each block for i in range(len(blocks)): # Expand counter to 64 bit little endian block_counter = struct.pack('<Q', i) # Generate block stream # format=64 bit unsigned little endian nonce, 64 bit little endian block count (byte count / 16) block_stream = self.nonce + block_counter # Generate keystream ciphertext = self.cipher.encrypt(block_stream) # Generate plaintext plaintext += xor_strings(blocks[i], ciphertext[:len(blocks[i])]) return plaintext
def ecb_encrypt(self, plaintext, key): # Slice plaintext into blocks plaintext_blocks = slice_target(plaintext, 16) # Initialize plaintext variable for padding plaintext_padded = b"" # Apply PKCS7 Padding if len(plaintext_blocks[-1]) < 16: plaintext_blocks[-1] = pkcs7_padding(plaintext_blocks[-1], 16) # Add blocks together for i in plaintext_blocks: plaintext_padded += bytes(i) # Encrypt under given key return self.cipher.encrypt(plaintext_padded)
def cbc_decrypt(self, ciphertext): plaintext = b"" ciphertext = slice_target(ciphertext, self.keysize) previous_block = self.iv plainblocks = [b"" for i in ciphertext] for i in range(len(ciphertext)): plainblocks[i] = xor_strings(self.cipher.decrypt(ciphertext[i]), previous_block) previous_block = ciphertext[i] for i in plainblocks: plaintext += i return plaintext
def ecb_decrypt(self, ciphertext, key): # Slice ciphertext into blocks ciphertext_blocks = slice_target(ciphertext, 16) # Initialize plaintext list for blocks plaintext_blocks = [b"" for i in range(len(ciphertext_blocks))] # Decrypt each block and add it to the plaintext list for i in range(len(ciphertext_blocks)): plaintext_blocks[i] = self.cipher.decrypt(ciphertext_blocks[i]) # Get last block and identify padding padding = plaintext_blocks[-1][-1] # Remove padding from last block plaintext_blocks[-1] = plaintext_blocks[-1][:-padding] # Initialize plaintext variable plaintext = b"" # Add blocks together for i in plaintext_blocks: plaintext += i return plaintext
def cbc_encrypt(self, plaintext): ciphertext = b"" plaintext = slice_target(plaintext, self.keysize) previous_block = self.iv if len(plaintext[-1]) != self.keysize: plaintext[-1] = pkcs7_padding(plaintext[-1], self.keysize) cipherblocks = [b"" for i in plaintext] for i in range(len(plaintext)): cipherblocks[i] = self.cipher.encrypt( xor_strings(plaintext[i], previous_block)) previous_block = cipherblocks[i] ciphertext = b"" for i in cipherblocks: ciphertext += i return ciphertext
def detect_ecb_mode(ciphertexts): result = [] # Iterate through all ciphertexts for ciphertext in ciphertexts: # Break ciphertext in blocks of 16 bytes target = slice_target(ciphertext, 16) # Total number of block in a given cipher is the length of the list number_of_blocks = len(target) # Initialize a dictionary to keep tracks of repeating blocks distinct_blocks = {} # Iterate through all blocks for i in target: # Assign value 1 to each distinct blocks distinct_blocks[i] = 1 # Total number of distinct blocks is the length of the dictionary number_of_distinct_blocks = len(distinct_blocks) # Look for only ciphertexts with repeating blocks if number_of_distinct_blocks < number_of_blocks: # Append result to the result list result.append(ciphertext) return result