在Python中对两个十六进制字符串进行异或 - 哪种方法正确?

时间:2013-06-30 11:48:40

标签: python string hex ascii xor

我一直在努力找到一种方法来正确地存储在字符串中的两个十六进制数字现在正好几天,并且我遇到了两种方法,这两种方法对我来说都有意义但产生了不同的结果。我不熟悉Python(因为我有3天的经验:D),所以我无法弄清楚哪种方法是正确的。

方法1:

s1 = #hex number stored in a string 1
s2 = #hex number stored in a string 2

#Decoding the hex strings into ASCII symbols
s3 = s1.decode('hex')
s4 = s2.decode('hex')

#strxor - see the next code segment for the code of this function
xor1 = strxor(s3, s4)

#Encode the result back into ASCII
xor2 = xor1.encode('hex')

strxor函数:

#This was given in my assignment and I am not entirely sure what is going on in
#here. I've been told that it takes two ASCII strings as input, converts them to
#numbers, XORs the numbers and converts the result back to ASCII again.

def strxor(a, b):     
    if len(a) > len(b):
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
    else:
        return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])

方法2:

s1 = #ciphertext 1 - hex number in a string
s2 = #ciphertext 2 - hex number in a string

#convert the string to integers, xor them
#and convert back to hex
xor = hex(int(s1, 16) ^ int(s2, 16))

正如我之前所说,对于我有限的大脑,这两种解决方案看起来完全相同,但它们会产生完全不同的结果。问题是什么?我的系统上有Python 2.7.3和3.3.2,我都试过了(虽然不是方法1,因为python 3不再有字符串的解码功能)

4 个答案:

答案 0 :(得分:2)

your_string.encode('hex')将使用十六进制替换your_string的每个字符及其ASCII值。

例如,知道ASCII中的'A'字母是0x41:

>>> 'AAAA'.encode('hex')
'41414141'

您可以使用decode执行其他方式:

>>> '41414141'.decode('hex')
'AAAA'

但这不是你真正想要的。你想要的是0x12转换成18(16 + 2)。要做到这一点,正确的方法是使用int(your_string, 16)将your_string解释为以16为基数编码的数字。

所以,正确的解决方案是最后一个。

xor = hex(int(s1, 16) ^ int(s2, 16))

s1s2是包含数字的十六进制表示的字符串,您将它们解码为int告诉Python它的基数为16.然后您执行xor并最终将其转换回来使用十六进制表示形式(使用hex)。

答案 1 :(得分:1)

第一种方法的直接问题是您将strxor应用于s1s2

xor1 = strxor(s1, s2)

而您可能意味着s3s4

xor1 = strxor(s3, s4)

通过这种更改,我从两种方法得到相同的结果(在一个简单的测试用例中)。

答案 2 :(得分:0)

  

......这两种解决方案看起来完全相同,但却产生了完全不同的结果。有什么问题?

对我来说结果是一样的:

def strxor(a, b):
    len_ = min(len(a), len(b))
    return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len_], b[:len_])])


def work(s1, s2):
    #strxor - see the next code segment for the code of this function
    xor1 = strxor(s1.decode('hex'), s2.decode('hex')).encode('hex')

    #convert the string to integers, xor them
    #and convert back to hex
    xor2 = hex(int(s1, 16) ^ int(s2, 16))[2:]

    print xor1
    print xor2

work('A0', '0A')
work('A0', 'A0')
work('00', 'AA')
work('00A0', 'A000')

给出:

aa
aa
00
0
aa
aa
a0a0
a0a0

答案 3 :(得分:0)

如果您定义了解答案的测试用例,那将会有所帮助。例如:

0x0f0f0f ^ 0xf0f0f0  -> 0xffffff
0x101010 ^ 0x000000  -> 0x101010

等等。您的“方法2”是有效且正确的,并且在Python 2和3中是合法的(但您应该确保您的测试用例证实了这一点)。

函数strxor有缺陷,因为您的测试会显示。它需要两个输入字符串将每个字符串中的相应字符转换为其ord inal表示,将它们XOR一起,将其转换回带有chr的ASCII并再次将整个混乱连接在一起。需要一个测试用例来表明它可能适用于十进制数字,但混合大小写十六进制的炸弹:

strxor('b', 'B')

不应该产生#

方法2是最干净的,当str.decodehex已经存在时,使用int可能会被视为代码滥用。教师可能对list comprehensions更感兴趣,但有更好的例子可以选择。