Python: XOR hex strings

Kok Leong Fong picture Kok Leong Fong · Jan 25, 2013 · Viewed 60.9k times · Source

Possible Duplicate:
bitwise XOR of hex numbers in python

I am trying to XOR two hex strings in Python and did not really know where to start from.

I have two hex strings:

a = "32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de81230b59b7afb5f41afa8d661cb"
b = "32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f90"

Should I be using this ?

  1. return "".join([chr((x) ^ (y)) for (x,y) in zip(a[:len(b)], b)])
  2. return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])

I don't understand the difference with the two codes above. Why chr and ord? I have also seen people using int(hex,16).

Answer

phant0m picture phant0m · Jan 25, 2013

You are missing a couple of things here.

First, you will not want to XOR those strings. You have the strings in an encoded form, therefore, you need to .decode() them first:

binary_a = a.decode("hex")
binary_b = b.decode("hex")

Then, as already mentioned, the zip() function stops iterating as soon as one of the two sequences is exhausted. No slicing is needed.

You need the second version of the loop: First, you want to get the ASCII value of the characters: ord() produces a number. This is necessary because ^ only works on numbers.

After XORing the numbers, you then convert the number back into a character with chr:

def xor_strings(xs, ys):
    return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys))

xored = xor_strings(binary_a, binary_b).encode("hex")

Using .encode() at the end, we get the binary string back into a form, that prints nicely.