Skip to content

Commit 3511a6a

Browse files
committed
rotations of larger groups
1 parent bbf212d commit 3511a6a

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

kaitaistruct.py

+34-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717

1818
if PY2:
19+
range = xrange
1920
def integers2bytes(ints):
2021
return bytes(bytearray(ints))
2122
def bytes2integers(data):
@@ -362,15 +363,42 @@ def process_xor_many(data, key):
362363
return integers2bytes(a ^ b for a, b in zip(bytes2integers(data), itertools.cycle(bytes2integers(key))))
363364

364365
# formula taken from: http://stackoverflow.com/a/812039
365-
precomputed_rotations = {amount:[(i << amount) & 0xff | (i >> (-amount & 7)) for i in range(256)] for amount in range(8)}
366+
precomputed_single_rotations = {amount: [(i << amount) & 0xff | (i >> (8-amount)) for i in range(256)] for amount in range(1,8)}
366367

367368
@staticmethod
368369
def process_rotate_left(data, amount, group_size):
369-
if group_size != 1:
370-
raise Exception("unable to rotate groups other than 1 byte")
371-
amount = amount % 8
370+
if group_size < 1:
371+
raise Exception("group size must be at least 1 to be valid")
372+
373+
amount = amount % (group_size * 8)
372374
if amount == 0:
373375
return data
374376

375-
translate = KaitaiStream.precomputed_rotations[amount]
376-
return integers2bytes(translate[a] for a in bytes2integers(data))
377+
amount_bytes = amount // 8
378+
data_ints = bytes2integers(data)
379+
380+
if group_size == 1:
381+
translate = KaitaiStream.precomputed_single_rotations[amount]
382+
return integers2bytes(translate[a] for a in data_ints)
383+
384+
if len(data) % group_size != 0:
385+
raise Exception("data length must be a multiple of group size")
386+
387+
if amount % 8 == 0:
388+
indices = [(i + amount_bytes) % group_size for i in range(group_size)]
389+
return integers2bytes(data_ints[i+k] for i in range(0,len(data),group_size) for k in indices)
390+
391+
amount1 = amount % 8
392+
amount2 = 8 - amount1
393+
indices_pairs = [ ((i+amount_bytes) % group_size, (i+1+amount_bytes) % group_size) for i in range(group_size)]
394+
return integers2bytes((data_ints[i+k1] << amount1) & 0xff | (data_ints[i+k2] >> amount2) for i in range(0,len(data),group_size) for k1,k2 in indices_pairs)
395+
396+
# NOTE: unused implementation, left for reference
397+
#
398+
# cap = (1 << 8 * group_size) - 1
399+
# anti_amount = -amount & (8 * group_size - 1)
400+
# for i in range(0,len(data),group_size):
401+
# group = bytes2combinedinteger(data[i:i+group_size])
402+
# group = (group << amount) & cap | (group >> anti_amount)
403+
# r.append(combinedinteger2bytes(group, group_size))
404+
# return b''.join(r)

0 commit comments

Comments
 (0)