Generator 用于重复密钥 XOR 密码时的混淆

Confusion when Generator is being used in repeating key XOR cipher

我一直在查看重复密钥 XOR 密码的代码,但我无法掌握代码的某些功能。据我了解,密钥的每个字节都应该与字符串消息的每个字节一起使用,并且应该在它们之间应用 XOR 操作。为此,您似乎只需要迭代字符串的长度,循环遍历密钥的每个字节并应用异或运算。

出于某种原因,代码使用生成器函数(在另一个函数内部)循环访问密钥。创建函数的实例并将其保存在变量中,然后将其与消息的字节值列表一起压缩,然后应用异或运算。

我不明白的是,因为这个函数循环 while TRUE zip 函数将如何在两个列表之间的每对字节之间生成元组?也许我误解了生成器的功能,但这可以解决吗?

函数如下:

def mc_part5():

      def cycle_key(key):
        idx = 0
        while True:
          yield ord(key[idx%len(key)])
          idx += 1

      g = cycle_key('ICE')
      s = "Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal"
      hh = bytes(s,'ascii')
      xored = bytes([a^b for (a,b) in zip(hh, g)])

      c = '0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f'
      expected = bytes.fromhex(c)
      assert( xored == expected )

我认为您不是对生成器的工作方式感到困惑,而是对 zip 的工作方式感到困惑。你是完全正确的,在那里定义的生成器可以永远循环——但是,当最短的输入迭代耗尽时,zip 将停止生成元组。例如(在 python2.x):

>>> def count():
...   i = 0
...   while True:
...     yield i
...     i += 1
... 
>>> zip(count(), 'foo')
[(0, 'f'), (1, 'o'), (2, 'o')]

在这种情况下,两个可迭代对象中较短的一个是字符串 (hh),因为 g 具有无限长度。

就清理而言...可能不会好多少,但您可以使用 itertools.cycle 和生成器表达式:

g = (ord(c) for c in itertools.cycle('ICE'))

这消除了所有使事情变得更难理解的模数废话。