patternpythonMinor
Matasano CryptoPals Problem 8: Detecting ECB encryption
Viewed 0 times
problemmatasanoencryptioncryptopalsecbdetecting
Problem
For the Matasano CryptoPals Challenges Set 1 Problem 8, which states:
In this file are a bunch of hex-encoded ciphertexts.
One of them has been encrypted with ECB.
Detect it.
Remember that the problem with ECB is that it is stateless and deterministic; the same 16 byte plaintext block will always produce the same 16 byte ciphertext.
I have written the following Python Code. Since I'm a programmer coming from C++ to Python, some of it might be reminiscent of that transfer. Can I be more Pythonic than the code I've written? Any more suggestions?
In this file are a bunch of hex-encoded ciphertexts.
One of them has been encrypted with ECB.
Detect it.
Remember that the problem with ECB is that it is stateless and deterministic; the same 16 byte plaintext block will always produce the same 16 byte ciphertext.
I have written the following Python Code. Since I'm a programmer coming from C++ to Python, some of it might be reminiscent of that transfer. Can I be more Pythonic than the code I've written? Any more suggestions?
#! /usr/bin/env python
from binascii import a2b_hex
def is_ECB_encoded(data, block_size):
block_count = len(data)/block_size
for i in range(block_count):
for j in range(i+1,block_count):
if data[i*block_size:(i+1)*block_size] == data[j*block_size:(j+1)*block_size]:
return True
return False
filename = '8.txt'
for line in open(filename):
line = line.strip()
if is_ECB_encoded(a2b_hex(line), 16):
print lineSolution
Assuming your algorithm is correct:
Since iterators and generator expressions are lazy evaluated, it won't create any intermediate arrays. This makes it very fast but also very readable.
- Follow the pep8 style guide.
- You should use
range(0, len(data), block_size)so you don't have to do all the multiplication over and over.
- You can use
itertools.combinationsto reduce it to only one loop.
- You don't close the file. You should use
withto open and close the file.
- You can use
zip(or for python2itertools.izip) to get both the first and second index at the same time.
- You can simplify the whole thing using
anyand a generator expressions.
- You can use
str.jointo simplify the printing.
Since iterators and generator expressions are lazy evaluated, it won't create any intermediate arrays. This makes it very fast but also very readable.
from binascii import a2b_hex
from itertools import combinations, izip
def is_ecb_encoded(data, block_size):
myrange = range(0, len(data), block_size)
inds = combinations(zip(myrange, myrange[1:])), 2)
return any(data[i1:i2] == data[j1:j2] for (i1, i2), (j1, j2) in inds)
filename = '8.txt'
with open(filename) as fobj:
lines = (line.rstrip() for line in fobj)
lines = (a2b_hex(line) for line in lines)
lines = (line for line in lines if is_ecb_encoded(line, 16))
print '\n'.join(lines)Code Snippets
from binascii import a2b_hex
from itertools import combinations, izip
def is_ecb_encoded(data, block_size):
myrange = range(0, len(data), block_size)
inds = combinations(zip(myrange, myrange[1:])), 2)
return any(data[i1:i2] == data[j1:j2] for (i1, i2), (j1, j2) in inds)
filename = '8.txt'
with open(filename) as fobj:
lines = (line.rstrip() for line in fobj)
lines = (a2b_hex(line) for line in lines)
lines = (line for line in lines if is_ecb_encoded(line, 16))
print '\n'.join(lines)Context
StackExchange Code Review Q#97205, answer score: 2
Revisions (0)
No revisions yet.