【问题标题】:What is the equivalent of the '^' operator when working with String of binaries in python?在 python 中处理二进制字符串时,'^' 运算符的等价物是什么?
【发布时间】:2012-11-02 09:54:32
【问题描述】:

如何应用两个二进制字符串的异或来表示两个字符的 bin?

这是一个代码

def Xor(a,b):

    ABytes = a.encode('ascii','strict')
    BBytes = b.encode('ascii','strict')

    ABinaries = bin(int(binascii.hexlify(ABytes),16))
    BBinaries = bin(int(binascii.hexlify(BBytes),16))

    #this is what i want to do:
    xor = ABinaries ^ BBinaries 

    return xor

但是由于^ 运算符不对字符串进行操作。代码不起作用,问题是我需要返回异或的二进制值。

如果它有效,我怎样才能得到 xor 的字符串值?

【问题讨论】:

  • 如果这是为了分配,我怀疑自己弄清楚如何按位异或是重点。你有没有尝试过?
  • @Blckknght 不,这不是一个任务,首先为了得到 xor,我简单地写了 xor = bin (ord(chr((ord(a) ^ ord(b))))) ,但是当我尝试获取字符串表示时遇到了一些问题,我正在尝试进行 viegner 加密,这是问题的一部分。
  • 有什么原因不能对ints 进行异或运算,然后在结果上调用bin
  • @TomSmilack:是的,我在尝试获取字符串表示时遇到了一些问题,其次我想应用另一个 XOR 以获取原始文本。

标签: python encryption python-3.x binary


【解决方案1】:

当您在 Python 3 中索引或迭代 bytes 时,您将获得 int 值,您可以使用 xor

>>> a, b = b'abc', b'def'
>>> c = bytes(x^y for x,y in zip(a, b))
>>> c
b'\x05\x07\x05'
>>> bytes(x^y for x,y in zip(a, c))
b'def'
>>> bytes(x^y for x,y in zip(b, c))
b'abc'

如果出于某种原因(表示形式?我当然不会用它计算),我想将其作为位串,我会使用内置格式,并将每个位串零填充为 8 位:

>>> ''.join(format(x, '08b') for x in c)
'000001010000011100000101'

【讨论】:

    【解决方案2】:

    这对你有用吗?

    >>> bytes(a ^ b for a, b in zip(b'qwertyuiop', b'1234567890'))
    b'@EVFAOBQV@'
    

    在应用中:

    >>> def xor(x, y):
        assert isinstance(x, bytes) and isinstance(y, bytes), 'Pass in bytes!'
        assert len(x) == len(y), 'Bytes must be of same length!'
        return bytes(a ^ b for a, b in zip(x, y))
    
    >>> xor(b'zxcvbnm,./', b'asdfghjkl;')
    b'\x1b\x0b\x07\x10\x05\x06\x07GB\x14'
    

    如何使用它的进一步应用:

    >>> import random
    >>> def crypt(data, password):
        random.seed(password)
        return xor(data, bytes(random.randrange(256) for i in range(len(data))))
    
    >>> crypt(b'This is a test string to be encrypted.', 'Gr8+ 9a$$')
    b'\x98ZE\xf2\x11\xe3=\x8b{\xf1Q"A\xd2\x8e\xb6.\xb2\xea\x81\x1b/\x8c\x15dFvHZ\xd9\x0cv8\xcd\xbe\x95\x1b\xc0'
    >>> crypt(_, 'Gr8+ 9a$$')
    b'This is a test string to be encrypted.'
    

    【讨论】:

      【解决方案3】:

      我认为可以在您的函数中使用的一些代码是这样的:

      from itertools import zip_longest
      
      reversed_bits = [str(int(x != y)) for x, y in zip_longest(ABinaries[:1:-1]),
                                                                BBinaries[:1:-1]),
                                                                "0")]
      xor = "0b" + "".join(reversed(reversed_bits))
      

      但是,这将相当缓慢。一种更快的方法是尽可能多地处理字节和整数,并完全避免使用二进制字符串。

      【讨论】:

      • 为什么要投反对票?虽然我意识到这是低效的(并在答案中这么说!),但它确实回答了所提出的具体问题。
      【解决方案4】:
      ABytes = a.encode('ascii','strict')
      BBytes = b.encode('ascii','strict')
      ABinaries =""
      BBinaries = ""
      AtempBinaries = bin(int(binascii.hexlify(ABytes),16))
      BtempBinaries = bin(int(binascii.hexlify(BBytes),16))
      if len(AtempBinaries)<10:
      
          ABinaries= '0b'+(((9-len(AtempBinaries))*'0') +AtempBinaries.split('0b')[1])
      if len(BtempBinaries)<10:
          BBinaries = '0b'+ (((9-len(BtempBinaries))*'0') +BtempBinaries.split('0b')[1])
      i = 0
      xor = ""
      for element in ABinaries:
          if (i == 0):
              xor = xor + '0'
          elif (element == 'b'):
              xor = xor + 'b'
          else:
              xor = xor + str(int(element)^int(BBinaries[i]))
          i = i + 1
      return (xor)
      

      这似乎解决了问题,没有直接的方法来异或两个二进制字符串。

      【讨论】:

      • 如果二进制字符串的长度不同,这将无法正常工作(考虑bin(ord("0"))(6 位)与bin(ord("A"))(7 位))。
      • @Blckknght:感谢您指出这一点,因为我只使用我没有想到的字符,我稍后会编辑答案。
      猜你喜欢
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-03
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多