HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMajor

Exhaustive search for encryption keys

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
encryptionsearchkeysforexhaustive

Problem

This does the job, but is not especially elegant.

What is the preferred Pythonic idiom to my childish nests?

def bytexor(a, b):
    res = ""
    for x, y in zip(a, b):
        if (x == "1" and y == "0") or (y =="1" and x == "0"):
            res += "1"
        else:
            res += "0"

    return res

def get_all():
    res = []
    bit = ["0","1"]
    for i in bit:
        for j in bit:
            for k in bit:
                for l in bit:
                    res.append(i+j+k+l)
    return res

if __name__=="__main__":

    for k0 in get_all():
        for k1 in get_all():
            for k2 in get_all():
                for k3 in get_all():
                    for k4 in get_all():
                        if bytexor(bytexor(k0, k2), k3) == "0011":
                            if bytexor(bytexor(k0, k2), k4) == "1010":
                                if bytexor(bytexor(bytexor(k0,k1),k2),k3) == "0110":
                                    print k0, k1, k2, k3, k4
                                    print bytexor(bytexor(bytexor(k0, k1),k2),k4)

Solution

To convert an integer to a bit string with a particular number of digits, use string.format with the b format type. For example:

>>> ['{0:04b}'.format(i) for i in range(16)]
['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
 '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']


But really it looks to me as though you don't want to be working with bit strings at all. You just want to be working with integers.

So instead of get_all, just write range(16) and instead of bytexor, write ^. Your entire program can be written like this:

from itertools import product
for a, b, c, d, e in product(range(16), repeat=5):
    if a ^ c ^ d == 3 and a ^ c ^ e == 10 and a ^ b ^ c ^ d == 6:
        print a, b, c, d, e, a ^ b ^ c ^ e


(This will also run a lot faster without all that fiddling about with strings.)

Code Snippets

>>> ['{0:04b}'.format(i) for i in range(16)]
['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
 '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']
from itertools import product
for a, b, c, d, e in product(range(16), repeat=5):
    if a ^ c ^ d == 3 and a ^ c ^ e == 10 and a ^ b ^ c ^ d == 6:
        print a, b, c, d, e, a ^ b ^ c ^ e

Context

StackExchange Code Review Q#18828, answer score: 29

Revisions (0)

No revisions yet.