Skip to content

Commit 8ce12b5

Browse files
committed
rotations of larger groups
1 parent c340e40 commit 8ce12b5

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
@@ -17,6 +17,7 @@
1717

1818

1919
if PY2:
20+
range = xrange
2021
def integers2bytes(ints):
2122
return bytes(bytearray(ints))
2223
def bytes2integers(data):
@@ -363,15 +364,42 @@ def process_xor_many(data, key):
363364
return integers2bytes(a ^ b for a, b in zip(bytes2integers(data), itertools.cycle(bytes2integers(key))))
364365

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

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

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

0 commit comments

Comments
 (0)