python - Break bytes object into n equally sized blocks based on index -
i'm working on writing script break repeating-key xor (vigenère) cipher.
this involves determining number (0 < n < maybe 50) splitting bytes object n smaller blocks, first block contains (from original object) indexes n, 2n, 3n, next 1 contains n+1, 2n+1, 3n+1... n+y, 2n+y, 3n+y y < n.
if n = 3, bytes [0, 2, 5, 8 etc] should in 1 block, bytes [1,3,6,9] in next block, , bytes [2,4,7,10] in final block.
i implement strings, don't know how make work bytes objects. searched , found , adapted code:
blocks = [ciphertext[i:i+most_likely_keylength] in range(0, len(ciphertext)+1, most_likely_keylength)] transposedblocks = list(zip_longest(*blocks, fillvalue=0)) ##ciphertext bytes object resulting following line: ##ciphertext = base64.b64decode(open('q6.txt', 'r').read())
this returns list of tuples filled integers, , don't know how 'join' integers again they'll long binary objects before. (so can run nice crypto.util.strxor_c on each tuple.
any 'string manipulation' bytes objects?
note: i'm working on break repeating-key xor challenge @ cryptopals.com – have looked @ other people's solutions on github, use specialised crypto modules , want see guts of i'm doing.
conceptually, bytes
object is sequence of integers:
>>> tuple(b'ciphertext') (99, 105, 112, 104, 101, 114, 116, 101, 120, 116)
... constructor happily accept one:
>>> bytes((99, 105, 112, 104, 101, 114, 116, 101, 120, 116)) b'ciphertext'
knowing that, can change second line this:
transposed = [bytes(t) t in zip_longest(*blocks, fillvalue=0))]
... , you'll bytes
objects back:
from itertools import zip_longest ciphertext = b'ciphertext' keylength = 3 blocks = [ciphertext[i:i+keylength] in range(0, len(ciphertext)+1, keylength)] # [b'cip', b'her', b'tex', b't'] transposed = [bytes(t) t in zip_longest(*blocks, fillvalue=0)] # [b'chtt', b'iee\x00', b'prx\x00']
however, there's error in code – because you're using len(ciphertext)+1
rather len(ciphertext)
in call range()
, final empty bytestring in blocks
if ciphertext exact multiple of keylength
:
ciphertext = b'splitsevenly' blocks = [ciphertext[i:i+keylength] in range(0, len(ciphertext)+1, keylength)] # [b'spl', b'its', b'eve', b'nly', b'']
... results in null bytes @ end of elements in transposed
:
transposed = [bytes(t) t in zip_longest(*blocks, fillvalue=0)] # [b'sien\x00', b'ptvl\x00', b'lsey\x00']
if drop +1
, works correctly in both cases:
ciphertext = b'ciphertext' blocks = [ciphertext[i:i+keylength] in range(0, len(ciphertext), keylength)] # [b'cip', b'her', b'tex', b't'] transposed = [bytes(t) t in zip_longest(*blocks, fillvalue=0)] # [b'chtt', b'iee\x00', b'prx\x00']
ciphertext = b'splitsevenly' blocks = [ciphertext[i:i+keylength] in range(0, len(ciphertext), keylength)] # [b'spl', b'its', b'eve', b'nly'] transposed = [bytes(t) t in zip_longest(*blocks, fillvalue=0)] # [b'sien', b'ptvl', b'lsey']
Comments
Post a Comment