|
17 | 17 |
|
18 | 18 |
|
19 | 19 | if PY2:
|
| 20 | + range = xrange |
20 | 21 | def integers2bytes(ints):
|
21 | 22 | return bytes(bytearray(ints))
|
22 | 23 | def bytes2integers(data):
|
@@ -363,15 +364,42 @@ def process_xor_many(data, key):
|
363 | 364 | return integers2bytes(a ^ b for a, b in zip(bytes2integers(data), itertools.cycle(bytes2integers(key))))
|
364 | 365 |
|
365 | 366 | # 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)} |
367 | 368 |
|
368 | 369 | @staticmethod
|
369 | 370 | 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) |
373 | 375 | if amount == 0:
|
374 | 376 | return data
|
375 | 377 |
|
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