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

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -