Skip to content

Commit 1d6f614

Browse files
committed
process xor/rol optimised and fully implemented
1 parent 14b9bd8 commit 1d6f614

2 files changed

Lines changed: 67 additions & 12 deletions

File tree

kaitai/kaitaistream.cpp

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -432,41 +432,96 @@ std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool in
432432
// ========================================================================
433433

434434
std::string kaitai::kstream::process_xor_one(std::string data, uint8_t key) {
435+
if (key == 0)
436+
return data;
437+
435438
size_t len = data.length();
436439
std::string result(len, ' ');
437440

438-
for (size_t i = 0; i < len; i++)
441+
for (size_t i = 0; i < len; i++) {
439442
result[i] = data[i] ^ key;
443+
}
440444

441445
return result;
442446
}
443447

444448
std::string kaitai::kstream::process_xor_many(std::string data, std::string key) {
445449
size_t len = data.length();
446450
size_t kl = key.length();
451+
if (len == 1)
452+
return process_xor_one(data, key[0]);
453+
447454
std::string result(len, ' ');
448455

449-
size_t ki = 0;
450456
for (size_t i = 0; i < len; i++) {
451-
result[i] = data[i] ^ key[ki];
452-
ki++;
453-
if (ki >= kl)
454-
ki = 0;
457+
result[i] = data[i] ^ key[i % kl];
455458
}
456459

457460
return result;
458461
}
459462

460-
std::string kaitai::kstream::process_rotate_left(std::string data, int amount) {
463+
std::string kaitai::kstream::process_rotate_left(std::string data, int amount, int groupSize = 1) {
464+
if (groupSize < 1)
465+
throw std::runtime_error("process_rotate_left: groupSize must be at least 1");
466+
467+
amount = mod(amount, groupSize * 8);
468+
if (amount == 0)
469+
return data;
470+
471+
int amount_bytes = amount / 8;
461472
size_t len = data.length();
462473
std::string result(len, ' ');
463474

464-
for (size_t i = 0; i < len; i++) {
465-
uint8_t bits = data[i];
466-
result[i] = (bits << amount) | (bits >> (8 - amount));
475+
if (groupSize == 1) {
476+
int anti_amount = 8 - amount;
477+
uint8_t translate[256];
478+
for (uint8_t i = 0; i < 256; i++) {
479+
translate[i] = (uint8_t)((i << amount) | (i >> anti_amount));
480+
}
481+
482+
for (size_t i = 0; i < len; i++) {
483+
result[i] = translate[data[i]];
484+
}
485+
486+
return result;
467487
}
468488

469-
return result;
489+
if (len % groupSize != 0)
490+
throw std::runtime_error("process_rotate_left: data length must be a multiple of group size");
491+
492+
if (amount % 8 == 0) {
493+
size_t[groupSize] indices;
494+
for (size_t i = 0; i < groupSize; i++) {
495+
indices[i] = (size_t)((i + amount_bytes) % groupSize);
496+
}
497+
498+
for (size_t i = 0; i < len; i += groupSize) {
499+
for (size_t k = 0; k < groupSize; k++) {
500+
result[i+k] = data[i + indices[k]];
501+
}
502+
}
503+
504+
return result;
505+
}
506+
507+
{
508+
int amount1 = amount % 8;
509+
int amount2 = 8 - amount1;
510+
size_t[groupSize] indices1;
511+
size_t[groupSize] indices2;
512+
for (size_t i = 0; i < groupSize; i++) {
513+
indices1[i] = (size_t)((i + amount_bytes) % groupSize);
514+
indices2[i] = (size_t)((i + 1 + amount_bytes) % groupSize);
515+
}
516+
517+
for (size_t i = 0; i < len; i += groupSize) {
518+
for (size_t k = 0; k < groupSize; k++) {
519+
result[i+k] = (uint8_t)((data[i + indices1[k]] << amount1) | (data[i + indices2[k]] >> amount2));
520+
}
521+
}
522+
523+
return result;
524+
}
470525
}
471526

472527
#ifdef KS_ZLIB

kaitai/kaitaistream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class kstream {
196196
* @param amount number of bits to shift by
197197
* @return copy of source array with requested shift applied
198198
*/
199-
static std::string process_rotate_left(std::string data, int amount);
199+
static std::string process_rotate_left(std::string data, int amount, int groupSize = 1);
200200

201201
#ifdef KS_ZLIB
202202
/**

0 commit comments

Comments
 (0)