简体   繁体   English

如何对两个十六进制字符串进行异或,以便每个字节分别进行异或?

[英]How to XOR two hex strings so that each byte is XORed separately?

I have been posting similar questions here for a couple of days now, but it seems like I was not asking the right thing, so excuse me if I have exhausted you with my XOR questions :D. 我已经在这里发了几天类似的问题,但似乎我没有问正确的事情,所以请原谅我,如果我用XOR问题让你筋疲力尽:D。

To the point - I have two hex strings and I want to XOR these strings such that each byte is XORed separately (ie each pair of numbers is XORed separately). 要点 - 我有两个十六进制字符串,我想对这些字符串进行异或,以便每个字节分别进行异或(即每对数字分别进行异或)。 And I want to do this in python, and I want to be able to have strings of different lengths. 我想在python中这样做,我希望能够拥有不同长度的字符串。 I will do an example manually to illustrate my point (I used the code environment because it allows me to put in spaces where I want them to be): 我将手动做一个例子来说明我的观点(我使用了代码环境,因为它允许我放入我希望它们的空间):

Input:
s1 = "48656c6c6f"
s2 = "61736b"

Encoding in binary:
48 65 6c 6c 6f = 01001000 01100101 01101100 01101100 01101111
61 73 6b       = 01100001 01110011 01101011

XORing the strings:
01001000 01100101 01101100 01101100 01101111
                  01100001 01110011 01101011
                  00001101 00011111 00000100

Converting the result to hex:
00001101 00011111 00000100 = 0d 1f 04

Output:
0d1f04

So, to summarize, I want to be able to input two hex strings (these will usually be ASCII letters encoded in hex) of different or equal length, and get their XOR such that each byte is XORed separately. 因此,总而言之,我希望能够输入两个不同或相等长度的十六进制字符串(这些字符串通常是以十六进制编码的ASCII字母),并获得它们的XOR,使得每个字节分别进行异或。

Use binascii.unhexlify() to turn your hex strings to binary data, then XOR that, going back to hex with binascii.hexlify() : 使用binascii.unhexlify()将十六进制字符串转换为二进制数据,然后异或,使用binascii.hexlify()返回十六进制:

>>> from binascii import unhexlify, hexlify
>>> s1 = "48656c6c6f"
>>> s2 = "61736b"
>>> hexlify(''.join(chr(ord(c1) ^ ord(c2)) for c1, c2 in zip(unhexlify(s1[-len(s2):]), unhexlify(s2))))
'0d1f04'

The actual XOR is applied per byte of the decoded data (using ord() and chr() to go to and from integers). 实际的XOR应用于解码数据的每个字节(使用ord()chr()chr()整数)。

Note that like in your example, I truncated s1 to be the same length as s2 (ignoring characters from the start of s1 ). 请注意,在您的示例中,我将s1截断为与s2相同的长度(忽略s1开头的字符)。 You can encode all of s1 with a shorter key s2 by cycling the bytes: 您可以通过循环字节来使用较短的密钥s2所有 s1进行编码:

>>> from itertools import cycle
>>> hexlify(''.join(chr(ord(c1) ^ ord(c2)) for c1, c2 in zip(unhexlify(s1), cycle(unhexlify(s2)))))
'2916070d1c'

You don't have to use unhexlify() , but it is a lot easier than looping over s1 and s2 2 characters at a time and using int(twocharacters, 16) to turn that into integer values for XOR operations. 不必使用unhexlify()但它比遍历一个更容易s1s2在时间2个字符,并使用int(twocharacters, 16)以将其转换成用于XOR运算整数值。

The Python 3 version of the above is a little lighter; 上面的Python 3版本更轻一些; use bytes() instead of str.join() and you can drop the chr() and ord() calls as you get to iterate over integers directly: 使用bytes()而不是str.join() ,你可以在你直接迭代整数时删除chr()ord()调用:

>>> from binascii import unhexlify, hexlify
>>> s1 = "48656c6c6f"
>>> s2 = "61736b"
>>> hexlify(bytes(c1 ^ c2 for c1, c2 in zip(unhexlify(s1[-len(s2):]), unhexlify(s2)))) 
b'0d1f04'
>>> from itertools import cycle
>>> hexlify(bytes(c1 ^ c2 for c1, c2 in zip(unhexlify(s1), cycle(unhexlify(s2)))))
b'2916070d1c'

I found a very simple solution: 我发现了一个很简单的解决方案

def xor_str(a,b):
    result = int(a, 16) ^ int(b, 16) # convert to integers and xor them
    return '{:x}'.format(result)     # convert back to hexadecimal

It will xor the string until one of theme ends 它将xor字符串直到其中一个主题结束

I'm not sure of what are you exactly searching for, but hopefully this be useful for you. 我不确定你到底在寻找什么,但希望这对你有用。

>>> def getstr(encoded):
     return "".join([chr(int(i+k, 16))for (i,k) in zip(encoded[0::2], encoded[1::2])])

>>> getstr(s1)
'Hello'

>>> getstr(s2)
'ask'

Starting with two normal strings, you can find your results doing something like this: 从两个普通字符串开始,您可以找到类似这样的结果:

>>> "".join(reversed(["%02X" % (ord(c1) ^ ord(c2)) for c1, c2 in zip(reversed(getstr(s1)),       reversed(getstr(s2)))]))
'0D1F04'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM