how to do bitwise exclusive or of two strings in python?

后端 未结 12 1733
攒了一身酷
攒了一身酷 2020-12-01 02:34

I would like to perform a bitwise exclusive or of two strings in python, but xor of strings are not allowed in python. How can I do it ?

相关标签:
12条回答
  • 2020-12-01 03:06

    You can convert the characters to integers and xor those instead:

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

    Here's an updated function in case you need a string as a result of the 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))
    

    See it working online: ideone

    0 讨论(0)
  • 2020-12-01 03:07

    the one liner for python3 is :

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

    where a, b and the returned value are bytes() instead of str() of course

    can't be easier, I love python3 :)

    0 讨论(0)
  • 2020-12-01 03:10

    For bytearrays you can directly use 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')
    
    0 讨论(0)
  • 2020-12-01 03:12

    Based on William McBrine's answer, here is a solution for fixed-length strings which is 9% faster for my use case:

    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'))
    
    0 讨论(0)
  • 2020-12-01 03:13

    If the strings are not even of equal length, you can use this

    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)])])
    
    0 讨论(0)
  • 2020-12-01 03:20

    I've found that the ''.join(chr(ord(a)^ord(b)) for a,b in zip(s,m)) method is pretty slow. Instead, I've been doing this:

    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 讨论(0)
提交回复
热议问题