@@ -432,41 +432,104 @@ std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool in
432
432
// ========================================================================
433
433
434
434
std::string kaitai::kstream::process_xor_one (std::string data, uint8_t key) {
435
+ if (key == 0 )
436
+ return data;
437
+
435
438
size_t len = data.length ();
436
439
std::string result (len, ' ' );
437
440
438
- for (size_t i = 0 ; i < len; i++)
441
+ for (size_t i = 0 ; i < len; i++) {
439
442
result[i] = data[i] ^ key;
443
+ }
440
444
441
445
return result;
442
446
}
443
447
444
448
std::string kaitai::kstream::process_xor_many (std::string data, std::string key) {
445
449
size_t len = data.length ();
446
450
size_t kl = key.length ();
451
+ if (len == 1 )
452
+ return process_xor_one (data, key[0 ]);
453
+
447
454
std::string result (len, ' ' );
448
455
449
- size_t ki = 0 ;
450
456
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];
455
458
}
456
459
457
460
return result;
458
461
}
459
462
460
- std::string kaitai::kstream::process_rotate_left (std::string data, int amount) {
463
+ uint8_t precomputedSingleRotations[8 ][256 ];
464
+
465
+ // NOTE: code based on StackOverflow answer at https://stackoverflow.com/a/34321324/2375119
466
+ computeSingleRotations {
467
+ for (int amount = 1 ; amount < 8 ; amount++) {
468
+ int anti_amount = 8 - amount;
469
+ for (uint8_t i = 0 ; i < 256 ; i++) {
470
+ precomputedSingleRotations[amount][i] = (uint8_t )((i << amount) | (i >> anti_amount));
471
+ }
472
+ }
473
+ }
474
+
475
+ std::string kaitai::kstream::process_rotate_left (std::string data, int amount, int groupSize = 1 ) {
476
+ if (groupSize < 1 )
477
+ throw std::runtime_error (" process_rotate_left: groupSize must be at least 1" );
478
+
479
+ amount = mod (amount, groupSize * 8 );
480
+ if (amount == 0 )
481
+ return data;
482
+
483
+ int amount_bytes = amount / 8 ;
461
484
size_t len = data.length ();
462
485
std::string result (len, ' ' );
463
486
464
- for (size_t i = 0 ; i < len; i++) {
465
- uint8_t bits = data[i];
466
- result[i] = (bits << amount) | (bits >> (8 - amount));
487
+ if (groupSize == 1 ) {
488
+ uint8_t *translate = &precomputedSingleRotations[amount][0 ];
489
+
490
+ for (size_t i = 0 ; i < len; i++) {
491
+ result[i] = translate[data[i]];
492
+ }
493
+
494
+ return result;
467
495
}
468
496
469
- return result;
497
+ if (len % groupSize != 0 )
498
+ throw std::runtime_error (" process_rotate_left: data length must be a multiple of group size" );
499
+
500
+ if (amount % 8 == 0 ) {
501
+ size_t indices[groupSize];
502
+ for (size_t i = 0 ; i < groupSize; i++) {
503
+ indices[i] = (size_t )((i + amount_bytes) % groupSize);
504
+ }
505
+
506
+ for (size_t i = 0 ; i < len; i += groupSize) {
507
+ for (size_t k = 0 ; k < groupSize; k++) {
508
+ result[i+k] = data[i + indices[k]];
509
+ }
510
+ }
511
+
512
+ return result;
513
+ }
514
+
515
+ {
516
+ int amount1 = amount % 8 ;
517
+ int amount2 = 8 - amount1;
518
+ size_t indices1[groupSize];
519
+ size_t indices2[groupSize];
520
+ for (size_t i = 0 ; i < groupSize; i++) {
521
+ indices1[i] = (size_t )((i + amount_bytes) % groupSize);
522
+ indices2[i] = (size_t )((i + 1 + amount_bytes) % groupSize);
523
+ }
524
+
525
+ for (size_t i = 0 ; i < len; i += groupSize) {
526
+ for (size_t k = 0 ; k < groupSize; k++) {
527
+ result[i+k] = (uint8_t )((data[i + indices1[k]] << amount1) | (data[i + indices2[k]] >> amount2));
528
+ }
529
+ }
530
+
531
+ return result;
532
+ }
470
533
}
471
534
472
535
#ifdef KS_ZLIB
0 commit comments