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'))
这消除了所有使事情变得更难理解的模数废话。
我一直在查看重复密钥 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'))
这消除了所有使事情变得更难理解的模数废话。