2013-07-01 39 views
9

Tôi đã đăng các câu hỏi tương tự ở đây trong một vài ngày, nhưng có vẻ như tôi đã không hỏi điều đúng, vì vậy xin lỗi nếu tôi đã kiệt sức bạn với các câu hỏi XOR của tôi: D.Làm thế nào để XOR hai chuỗi hex sao cho mỗi byte được XOR riêng biệt?

Đến điểm - tôi có hai chuỗi hex và tôi muốn XOR các chuỗi sao cho mỗi byte được XOR riêng biệt (nghĩa là mỗi cặp số được XOR riêng biệt). Và tôi muốn làm điều này trong python, và tôi muốn có thể có các chuỗi có độ dài khác nhau. Tôi sẽ làm một ví dụ bằng tay để minh họa cho quan điểm của tôi (tôi đã sử dụng môi trường mã vì nó cho phép tôi để đưa vào không gian nơi tôi muốn họ được):

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 

Vì vậy, để tóm tắt, tôi muốn để có thể nhập hai chuỗi hex (thường sẽ là các chữ cái ASCII được mã hóa bằng hex) có độ dài khác nhau hoặc bằng nhau và nhận được XOR của chúng sao cho mỗi byte được XOR riêng biệt.

+1

Tại sao không chu kỳ khóa 's2' và áp dụng nó cho * tất cả * ký tự của' s1'? Tại sao chỉ áp dụng nó cho 3 cuối cùng? –

Trả lời

11

Sử dụng binascii.unhexlify() để biến chuỗi hex của bạn để dữ liệu nhị phân, sau đó XOR rằng, từ nay trở về hex với 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' 

Các XOR thực tế được áp dụng cho mỗi byte của dữ liệu được giải mã (sử dụng ord()chr() để đi đến và đi từ số nguyên).

Lưu ý rằng như trong ví dụ của bạn, tôi đã cắt bớt s1 có cùng độ dài như s2 (bỏ qua các ký tự từ đầu s1). Bạn có thể mã hóa tất cả của s1 với một chìa khóa ngắn hơn s2 bằng xe đạp các byte:

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

Bạn không sử dụng unhexlify(), nhưng nó là dễ dàng hơn rất nhiều so với Looping trên s1s2 2 ký tự tại một thời điểm và sử dụng int(twocharacters, 16) để biến nó thành các giá trị số nguyên cho các hoạt động XOR.

Phiên bản Python 3 ở trên nhẹ hơn một chút; sử dụng bytes() thay vì str.join() và bạn có thể thả chr()ord() cuộc gọi khi bạn nhận được để lặp qua các số nguyên trực tiếp:

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

Cảm ơn bạn đã trả lời! Những gì tôi không hiểu, là phần này: cho c1, c2 theo zip (không giải thích (s1), chu kỳ (không giải thích (s2)))) Điều này là mới mẻ với python và dễ nhầm lẫn .Tôi nghĩ rằng các chức năng zip có cái gì để làm với mảng, nhưng tôi không biết làm thế nào những công việc trong Python. Bên cạnh đó, tôi nghĩ cho vòng chỉ có một truy cập, nhưng ở đây bạn có hai - c1 và c2, mà cũng confuses tôi. –

+1

'zip()' lấy nhiều chuỗi đầu vào và ghép nối các phần tử của chúng. Vì vậy, nó cung cấp cho bạn một chuỗi các '[(s1 [0], s2 [0]), (s1 [1], s2 [1]), ...]' với mỗi tuple được tạo thành bằng cách lấy các phần tử từ mỗi chuỗi đầu vào tại cùng một chỉ mục. –

+1

@NorsulRonsul: Bởi vì trong trường hợp này 'zip()' có hai danh sách đầu vào, mỗi phần tử đầu ra là một bộ tuple có hai giá trị. Vòng lặp 'for' đưa các giá trị đó thành hai giá trị (giống như bạn có thể thực hiện việc giải nén thông thường,' foo, bar = ('spam', 'eggs') 'assigns' foo = 'spam'' và 'bar =' –

1

Tôi không chắc chắn về những gì được bạn biết chính xác tìm kiếm, nhưng hy vọng này có ích cho bạn .

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

Bắt đầu với hai chuỗi bình thường, bạn có thể tìm thấy kết quả của bạn làm điều gì đó như thế này:

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

Tôi tìm thấy một giải pháp rất đơn giản:

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 

Nó sẽ xor chuỗi cho đến khi một trong những chủ đề kết thúc

+1

Nó luôn luôn lỗi tôi khi mọi người không sử dụng định dạng dựng sẵn. 'định dạng trả về (kết quả, 'x')'. – Veky

Các vấn đề liên quan