如何在python中进行按位独占或两个字符串?

时间:2010-04-10 08:15:15

标签: python string bitwise-operators

我想在python中执行按位异或两个字符串,但python中不允许使用xor字符串。我该怎么办?

12 个答案:

答案 0 :(得分:58)

您可以将字符转换为整数,然后转换为xor:

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

这是一个更新的函数,以防您因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))

查看在线工作:ideone

答案 1 :(得分:24)

如果你想对字节或单词进行操作,那么你最好使用Python的数组类型而不是字符串。如果你正在使用固定长度的块,那么你可以使用H或L格式来操作单词而不是字节,但我在这个例子中只使用了'B':

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

答案 2 :(得分:15)

对于字节数组,您可以直接使用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')

答案 3 :(得分:12)

这是你的字符串XOR'er,大概是为了一些温和的加密形式:

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

请注意,这是一种弱加密形式。观察给出空白字符串进行编码时会发生什么:

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

答案 4 :(得分:9)

python3的一个衬里是:

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

其中ab和返回值bytes()而不是str()当然

可以更轻松,我喜欢python3:)

答案 5 :(得分:4)

def strxor (s0, s1):
  l = [ chr ( ord (a) ^ ord (b) ) for a,b in zip (s0, s1) ]
  return ''.join (l)

(根据Mark Byers回答。)

答案 6 :(得分:3)

如果字符串长度不相等,则可以使用此

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

答案 7 :(得分:2)

你的意思是这样的:

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

答案 8 :(得分:1)

下面用m表示异或字符串s,然后再次反转该过程:

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

答案 9 :(得分: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)])

答案 10 :(得分:1)

我发现' .join(chr(ord(a)^ ord(b))for a,b in zip(s,m))方法很慢。相反,我一直这样做:

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

答案 11 :(得分:0)

根据William McBrine的回答,这里是一个固定长度字符串的解决方案,对我的用例来说快了9%:

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