根据索引将字节对象分成 n 个大小相等的块
Break bytes object into n equally sized blocks based on index
我正在编写一个脚本来破解重复密钥 XOR (Vigenère) 密码。
这涉及确定一些数字(0 < n < 可能是 50),然后将字节对象拆分为 n 个更小的块,其中第一个块包含(来自原始对象)索引 n、2n、3n,下一个包含n+1、2n+1、3n+1... 然后是 n+y、2n+y、3n+y,其中 y < n。
如果 n = 3,字节 [0、2、5、8 等] 应该在一个块中,字节 [1,3,6,9] 在下一个块中,字节 [2,4,7 ,10] 在最后一个块中。
我可以用字符串很容易地实现它,但我不知道如何让它与字节对象一起工作。我搜索并找到并改编了这段代码:
blocks = [ciphertext[i:i+most_likely_keylength] for i in range(0, len(ciphertext)+1, most_likely_keylength)]
transposedBlocks = list(zip_longest(*blocks, fillvalue=0))
##ciphertext is a bytes object resulting from the following line:
##ciphertext = base64.b64decode(open('Q6.txt', 'r').read())
然而,这是一个 returns 一个充满整数的元组列表,我不知道如何再次 'join' 这些整数,所以它们将像以前一样是长二进制对象。 (这样我就可以在每个元组上 运行 像 Crypto.Util.strxor_c 这样的好东西。
字节对象的 'string manipulation' 有任何帮助吗?
注意:我正在 cryptopals.com 上进行 Break repeating-key XOR 挑战 – 我看过其他人在 Github 上的解决方案,但他们大多使用专门的加密模块,我想要看看我在做什么的胆量。
从概念上讲,bytes
对象是一个整数序列:
>>> tuple(b'ciphertext')
(99, 105, 112, 104, 101, 114, 116, 101, 120, 116)
...所以它的构造函数会很乐意接受一个:
>>> bytes((99, 105, 112, 104, 101, 114, 116, 101, 120, 116))
b'ciphertext'
知道这一点后,您可以将第二行更改为:
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0))]
... 你会得到 bytes
个对象:
from itertools import zip_longest
ciphertext = b'ciphertext'
keylength = 3
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext)+1, keylength)]
# [b'cip', b'her', b'tex', b't']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'chtt', b'iee\x00', b'prx\x00']
但是,您的代码中存在一个错误 – 因为您在调用 range()
时使用的是 len(ciphertext)+1
而不仅仅是 len(ciphertext)
,您在 blocks
如果密文是 keylength
的整数倍:
ciphertext = b'SplitsEvenly'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext)+1, keylength)]
# [b'Spl', b'its', b'Eve', b'nly', b'']
... 这会导致 transposed
:
中所有元素末尾出现额外的空字节
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'SiEn\x00', b'ptvl\x00', b'lsey\x00']
如果删除 +1
,它在两种情况下都能正常工作:
ciphertext = b'ciphertext'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext), keylength)]
# [b'cip', b'her', b'tex', b't']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'chtt', b'iee\x00', b'prx\x00']
ciphertext = b'SplitsEvenly'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext), keylength)]
# [b'Spl', b'its', b'Eve', b'nly']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'SiEn', b'ptvl', b'lsey']
我正在编写一个脚本来破解重复密钥 XOR (Vigenère) 密码。
这涉及确定一些数字(0 < n < 可能是 50),然后将字节对象拆分为 n 个更小的块,其中第一个块包含(来自原始对象)索引 n、2n、3n,下一个包含n+1、2n+1、3n+1... 然后是 n+y、2n+y、3n+y,其中 y < n。
如果 n = 3,字节 [0、2、5、8 等] 应该在一个块中,字节 [1,3,6,9] 在下一个块中,字节 [2,4,7 ,10] 在最后一个块中。
我可以用字符串很容易地实现它,但我不知道如何让它与字节对象一起工作。我搜索并找到并改编了这段代码:
blocks = [ciphertext[i:i+most_likely_keylength] for i in range(0, len(ciphertext)+1, most_likely_keylength)]
transposedBlocks = list(zip_longest(*blocks, fillvalue=0))
##ciphertext is a bytes object resulting from the following line:
##ciphertext = base64.b64decode(open('Q6.txt', 'r').read())
然而,这是一个 returns 一个充满整数的元组列表,我不知道如何再次 'join' 这些整数,所以它们将像以前一样是长二进制对象。 (这样我就可以在每个元组上 运行 像 Crypto.Util.strxor_c 这样的好东西。
字节对象的 'string manipulation' 有任何帮助吗?
注意:我正在 cryptopals.com 上进行 Break repeating-key XOR 挑战 – 我看过其他人在 Github 上的解决方案,但他们大多使用专门的加密模块,我想要看看我在做什么的胆量。
从概念上讲,bytes
对象是一个整数序列:
>>> tuple(b'ciphertext')
(99, 105, 112, 104, 101, 114, 116, 101, 120, 116)
...所以它的构造函数会很乐意接受一个:
>>> bytes((99, 105, 112, 104, 101, 114, 116, 101, 120, 116))
b'ciphertext'
知道这一点后,您可以将第二行更改为:
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0))]
... 你会得到 bytes
个对象:
from itertools import zip_longest
ciphertext = b'ciphertext'
keylength = 3
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext)+1, keylength)]
# [b'cip', b'her', b'tex', b't']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'chtt', b'iee\x00', b'prx\x00']
但是,您的代码中存在一个错误 – 因为您在调用 range()
时使用的是 len(ciphertext)+1
而不仅仅是 len(ciphertext)
,您在 blocks
如果密文是 keylength
的整数倍:
ciphertext = b'SplitsEvenly'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext)+1, keylength)]
# [b'Spl', b'its', b'Eve', b'nly', b'']
... 这会导致 transposed
:
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'SiEn\x00', b'ptvl\x00', b'lsey\x00']
如果删除 +1
,它在两种情况下都能正常工作:
ciphertext = b'ciphertext'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext), keylength)]
# [b'cip', b'her', b'tex', b't']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'chtt', b'iee\x00', b'prx\x00']
ciphertext = b'SplitsEvenly'
blocks = [ciphertext[i:i+keylength] for i in range(0, len(ciphertext), keylength)]
# [b'Spl', b'its', b'Eve', b'nly']
transposed = [bytes(t) for t in zip_longest(*blocks, fillvalue=0)]
# [b'SiEn', b'ptvl', b'lsey']