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