2013-07-01 62 views
9

我已經在這裏發表了類似的問題幾天了,但是好像我並沒有問正確的東西,所以如果我已經用我的異或問題使你筋疲力盡了。如何異或兩個十六進制字符串,以便每個字節分別異或?

重點 - 我有兩個十六進制字符串,我想XOR這些字符串,使每個字節分別XORed(即每對數字分別XORed)。我想在python中這樣做,我想能夠有不同長度的字符串。我會做手工的例子來說明我的觀點(我使用的代碼環境,因爲它可以讓我把在空間,我希望他們能):

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 

因此,要總結,我希望能夠到輸入兩個不同或相等長度的十六進制字符串(這些字符串通常是以十六進制編碼的ASCII字母),並獲得它們的XOR,使得每個字節分別異或。

+1

爲什麼不循環's2'鍵並將其應用於's1'的* all *字符?爲什麼只應用到最後3? –

回答

11

使用binascii.unhexlify()把你的十六進制字符串的二進制數據,然後XOR,與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' 

實際XOR每解碼數據的字節應用(使用ord()chr()到去往和來自整數)。

請注意,與您的示例中一樣,我截短了s1,其長度與s2(忽略來自s1開頭的字符)的長度相同。您可以通過循環字節編碼s1所有用較短的鍵s2

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

你不使用unhexlify(),但它比遍歷s1s2 2個字符容易得多一次使用int(twocharacters, 16)將其轉換爲XOR操作的整數值。

以上的Python 3版本稍微輕一些;使用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' 
+1

謝謝你的回答!我不明白,是這部分: 對於c1,c2在zip(unhexlify(s1),cycle(unhexlify(s2))))) 事情是,我是新來的蟒蛇,很容易混淆。我認爲zip函數與數組有關,但我不知道這些在Python中是如何工作的。此外,我認爲循環只有一個計數器,但在這裏你有兩個--C1和C2,這也使我困惑。 –

+1

'zip()'需要多個輸入序列,並將它們的元素配對。因此,它給出了一個[[s1 [0],s2 [0]),(s1 [1],s2 [1]),...]的序列,每個元組通過將每個輸入序列中的元素同樣的指數。 –

+1

@NorsulRonsul:因爲在這種情況下'zip()'有兩個輸入列表,每個輸出元素都是一個有兩個值的元組。 for循環把它們解包成兩個值(就像你可以在常規任務中做tuple解包,foo,bar =('spam','eggs')'assign'foo ='spam''和'bar =' eggs'' –

1

我不知道什麼是你到底尋找,但希望這對您有用。

>>> 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' 

有兩個正常的字符串開始,你可以找到你的結果做這樣的事情:

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

我發現了一個很簡單的解決方案:

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 

將異或字符,直到主題結尾之一

+1

當人們不使用內置格式時,它總是讓我感到困惑。 '返回格式(結果,'x')'。 – Veky

相關問題