2010-04-10 21 views
35

Tôi muốn thực hiện một chút độc quyền hoặc hai chuỗi trong python, nhưng xor của chuỗi không được phép trong python. Tôi làm nó như thế nào ?làm thế nào để làm bitwise độc ​​quyền hoặc hai chuỗi trong python?

+3

Ý của bạn là gì bởi "độc quyền bitwise hoặc từ"? Không có ý nghĩa với tôi ... –

+0

Liên quan: [Thử nghiệm Python đơn giản: Bitwise XOR nhanh nhất trên bộ đệm dữ liệu] (http://stackoverflow.com/q/2119761/4279) – jfs

Trả lời

50

Bạn có thể chuyển đổi các ký tự để số nguyên và xor những thay:

l = [ord(a)^ord(b) for a,b in zip(s1,s2)] 

Dưới đây là một chức năng được cập nhật trong trường hợp bạn cần một chuỗi như là kết quả của XOR:

def sxor(s1,s2):  
    # convert strings to a list of character pair tuples 
    # go through each tuple, converting them to ASCII code (ord) 
    # perform exclusive or on the ASCII code 
    # then convert the result back to ASCII (chr) 
    # merge the resulting array of characters as a string 
    return ''.join(chr(ord(a)^ord(b)) for a,b in zip(s1,s2)) 

Xem nó làm việc trực tuyến: ideone

+18

Tôi không đồng ý. Nếu thực hiện các thao tác thao tác dữ liệu mật mã hoặc tương tự khác trong Python, bạn muốn có thể thực hiện điều này trên các chuỗi byte. Theo tôi Python3 nên hỗ trợ hoạt động này trên chuỗi byte. – Omnifarious

+7

hoặc một cái gì đó như 'byte (x^y cho x, y trong zip (s1, s2))' trong python3 như bạn có thể thấy bên dưới :) http://stackoverflow.com/questions/2612720/how-to-do- bitwise-exclusive-or-of-hai-strings-in-python/28481974 # 28481974 – yota

2

Bạn có ý nghĩa như sau:

s1 = '00000001' 
s2 = '11111110' 
int(s1,2)^int(s2,2) 
+0

đầu ra của điều này là dài: >>> type (int (bin_c, 2)^int (bin_m, 2))

+0

in int (s1,2) 2 nghĩa là gì ??? – Alex

1

Dưới đây minh họa XORing chuỗi s với m, và sau đó một lần nữa để đảo ngược quá trình:

>>> s='hello, world' 
>>> m='markmarkmark' 
>>> s=''.join(chr(ord(a)^ord(b)) for a,b in zip(s,m)) 
>>> s 
'\x05\x04\x1e\x07\x02MR\x1c\x02\x13\x1e\x0f' 
>>> s=''.join(chr(ord(a)^ord(b)) for a,b in zip(s,m)) 
>>> s 
'hello, world' 
>>> 
8

Đây là chuỗi XOR'er của bạn, có lẽ đối với một số hình thức nhẹ của mã hóa:

>>> src = "Hello, World!" 
>>> code = "secret" 
>>> xorWord = lambda ss,cc: ''.join(chr(ord(s)^ord(c)) for s,c in zip(ss,cc*100)) 
>>> encrypt = xorWord(src, code) 
>>> encrypt 
';\x00\x0f\x1e\nXS2\x0c\x00\t\x10R' 
>>> decrypt = xorWord(encrypt,code) 
>>> print decrypt 
Hello, World! 

Lưu ý rằng đây là cực kỳ hình thức mã hóa yếu. Xem điều gì sẽ xảy ra khi được cung cấp một chuỗi trống để mã hóa:

>>> codebreak = xorWord("  ", code) 
>>> print codebreak 
SECRET 
+3

Mã hóa XOR không thể phá vỡ nếu khóa lớn hơn thư. http://en.wikipedia.org/wiki/One_time_pad –

+6

Điều đó chỉ đúng nếu bạn sử dụng phím một lần. –

+0

chỉ khi nó có entropy cao. –

24

Nếu bạn muốn hoạt động trên byte hoặc từ thì bạn nên sử dụng loại mảng của Python thay vì chuỗi. Nếu bạn đang làm việc với các khối độ dài cố định sau đó bạn có thể sử dụng định dạng H hoặc L để hoạt động trên lời nói chứ không phải là byte, nhưng tôi chỉ sử dụng 'B' ví dụ này:

>>> import array 
>>> a1 = array.array('B', 'Hello, World!') 
>>> a1 
array('B', [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]) 
>>> a2 = array.array('B', ('secret'*3)) 
>>> for i in range(len(a1)): 
    a1[i] ^= a2[i] 


>>> a1.tostring() 
';\x00\x0f\x1e\nXS2\x0c\x00\t\x10R' 
+5

Tôi tin rằng đây là câu trả lời mà hầu hết có thể tương ứng với những gì OP muốn hỏi. – tzot

1
def xor_strings(s1, s2): 
    max_len = max(len(s1), len(s2)) 
    s1 += chr(0) * (max_len - len(s1)) 
    s2 += chr(0) * (max_len - len(s2)) 
    return ''.join([chr(ord(c1)^ord(c2)) for c1, c2 in zip(s1, s2)]) 
4
def strxor (s0, s1): 
    l = [ chr (ord (a)^ord (b)) for a,b in zip (s0, s1) ] 
    return ''.join (l) 

(Dựa trên Đánh dấu Byers câu trả lời.)

+1

khi s0 và s1 không cùng kích thước, chúng tôi hoặc sử dụng izip_longest hoặc itertools.islice trên itertools.cycle của hai chuỗi –

12

Đối bytearrays bạn có thể trực tiếp sử dụng XOR:

>>> b1 = bytearray("test123") 
>>> b2 = bytearray("321test") 
>>> b = bytearray(len(b1)) 
>>> for i in range(len(b1)): 
... b[i] = b1[i]^b2[i] 

>>> b 
bytearray(b'GWB\x00TAG') 
2

Nếu chuỗi không phải là thậm chí chiều dài bằng nhau , Bạn có thể sử dụng này

def strxor(a, b):  # xor two strings of different lengths 
    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)])]) 
1

Tôi đã phát hiện ra rằng '' .join (chr (ord (a)^ord (b)) cho a, b trong zip (s, m)) phương pháp là khá chậm.Thay vào đó, tôi đã làm điều này:

fmt = '%dB' % len(source) 
s = struct.unpack(fmt, source) 
m = struct.unpack(fmt, xor_data) 
final = struct.pack(fmt, *(a^b for a, b in izip(s, m))) 
+0

bạn có thể [sử dụng 'bytearray()' thay vì gói/giải nén] (http: // stackoverflow. com/a/20570990/4279). – jfs

7

một lót cho python3 là:

def bytes_xor(a, b) : 
    return bytes(x^y for x, y in zip(a, b)) 

nơi a, b và giá trị trả về là bytes() thay vì str() tất nhiên

thể 't được dễ dàng hơn, tôi yêu python3 :)

0

Dựa trên câu trả lời của William McBrine, đây là một giải pháp cho chiều dài cố định các chuỗi nhanh hơn 9% cho trường hợp sử dụng của tôi:

import itertools 
import struct 
def make_strxor(size): 
    def strxor(a, b, izip=itertools.izip, pack=struct.pack, unpack=struct.unpack, fmt='%dB' % size): 
     return pack(fmt, *(a^b for a, b in izip(unpack(fmt, a), unpack(fmt, b)))) 
    return strxor 
strxor_3 = make_strxor(3) 
print repr(strxor_3('foo', 'bar')) 
Các vấn đề liên quan