#include #include #include static int seed, i, max_step_bits, b2, b3, b5, size, bit_indices[16]; static void Output(unsigned bytecode) { static const char *string_table[] = { /* 0..3 */ "#ifdef %c\n", "#undef %c\n", "#ifndef %c\n", "#define %c\n", /* 4 */ "#endif", /* 5 */ "#else", /* 6 */ "static const unsigned char Z[] = {", /* 7 */ "};", /* 8 */ "0,", /* 9 */ "-~", /* 10 */ "#define _ __FILE__", /* 11 */ "#ifndef PIN\n#error Please compile with -DPIN=", }; int opcode = bytecode % 256 / 37 % 7, operand = bytecode % 256 % 37; opcode < 4 ? printf(string_table[opcode], operand == 0 ? '_' : operand < 27 ? 'a' + operand - 1 : 'A' + operand - 27) : opcode == 4 ? puts(string_table[operand]) : opcode == 5 ? printf(operand < 16 ? "#if PIN %% %d > %d\n" : "int main() { return !fwrite(Z, %d, %d, stdout); }\n", operand < 16 ? 2 << operand : size, operand < 16 ? (1 << operand) - 1 : 1) : /* opcode == 6 */ printf("#include%s\n", operand ? "" : " _"); if( bytecode >>= 8 ) Output(bytecode); } static void GenerateShuffledArray(int count, int *output) { int i, tmp; for(i = 0; i < count; i++) output[i] = i; for(; --count > 1;) { i = rand() % (count + 1); tmp = output[i]; output[i] = output[count]; output[count] = tmp; } } static int ExtractBits(int seed, int *bit_indices) { int i, o; for(i = o = 0; i < 8; i++) { if( (seed & (1 << bit_indices[i])) != 0 ) o |= 1 << i; } return o; } int main(int argc, char **argv) { if( argc != 2 || sscanf(argv[1], "%d", &seed) != 1 || seed < 1 || seed > 65535 ) { return printf("%s [16-bit PIN] < input.txt > output.c\n", *argv); } srand(time(NULL)); GenerateShuffledArray(16, bit_indices); /* Decoder header. */ Output(/* "#ifndef PIN\n" "#error Please compile with -DPIN=\n" */ (4 * 37 + 11) | /* #else */ ((4 * 37 + 5) << 8) | /* #ifndef _ */ ((2 * 37 + 0) << 16) | /* #define _ __FILE__ */ ((4 * 37 + 10) << 24)); /* Initialize PIN bits. */ for(i = 0; i < 16; i++) { Output(/* #if PIN %% %d > %d */ (5 * 37 + i) | /* #define BIT%d */ ((3 * 37 + 18 + i) << 8) | /* #endif */ ((4 * 37 + 4) << 16)); } /* Initialize maximum number of steps to be at least 8 bits. This is needed since we use the step counter for both running PRNG and also for building characters, so we need at least 8 bits to support all possible character outputs even if the maximum number of steps between PRNG runs can be represented in less than 8 bits. */ max_step_bits = 8; /* Data array. */ Output(/* static const unsigned char Z[] = { */ 4 * 37 + 6); size = 0; while( (i = getchar()) != EOF ) { /* Count number of steps needed to advance PRNG, with a minimum bound so that consecutive equal bytes will still advance the PRNG some number of times. */ b2 = (rand() % 16) + 1; for(b3 = 0; b3 < b2 || ExtractBits(seed, bit_indices) != i; b3++) { b5 = seed ^ (seed >> 2) ^ (seed >> 3) ^ (seed >> 5); seed = ((seed >> 1) | (b5 << 15)) & 0xffff; } /* Output directives to advance PRNG steps. */ Output(/* #define OUTPUT_BYTE */ 3 * 37 + 35); for(b2 = 0; b3 >= (1 << b2); b2++) { if( (b3 & (1 << b2)) != 0 ) Output(/* #define STEP%d */ 3 * 37 + 1 + b2); } if( max_step_bits < b2 ) max_step_bits = b2; Output(/* #include _ */ 6 * 37 + 0); size++; } /* Decoder footer. */ Output(/* }; */ (4 * 37 + 7) | /* #include */ ((6 * 37 + 1) << 8) | /* int main() { return !fwrite(data, %d, 1, stdout); } */ ((5 * 37 + 16) << 16) | /* #else */ ((4 * 37 + 5) << 24)); Output(/* #ifdef OUTPUT_BYTE */ (0 * 37 + 35) | /* #undef OUTPUT_BYTE */ ((1 * 37 + 35) << 8) | /* #define RUN_PRNG */ ((3 * 37 + 36) << 16) | /* #include _ */ ((6 * 37 + 0) << 24)); /* Convert PRNG bits to byte increment bits. */ for(i = 0; i < 8; i++) { Output(/* #ifdef BIT%d */ (0 * 37 + 18 + bit_indices[i]) | /* #define STEP%d */ ((3 * 37 + 1 + i) << 8) | /* #endif */ ((4 * 37 + 4) << 16)); } /* Generate byte and start next byte. */ Output(/* #undef RUN_PRNG */ (1 * 37 + 36) | /* #include _ */ ((6 * 37 + 0) << 8) | /* 0, */ ((4 * 37 + 8) << 16) | /* #else */ ((4 * 37 + 5) << 24)); /* Run PRNG steps. */ for(i = max_step_bits - 1; i > 0; i--) { Output(/* #ifdef STEP%d */ (0 * 37 + 1 + i) | /* #undef STEP%d */ ((1 * 37 + 1 + i) << 8) | /* #include _ */ ((6 * 37 + 0) << 16) | /* #define STEP(%d-1) */ ((3 * 37 + 1 + i - 1) << 24)); Output(/* #include _ */ (6 * 37 + 0) | /* #define STEP(%d-1) */ ((3 * 37 + 1 + i - 1) << 8) | /* #endif */ ((4 * 37 + 4) << 16)); } /* Run a single step of PRNG, or increment pending byte by 1. */ Output(/* #ifdef STEP0 */ (0 * 37 + 1) | /* #undef STEP0 */ ((1 * 37 + 1) << 8) | /* #ifdef RUN_PRNG */ ((0 * 37 + 36) << 16) | /* #undef BIT16 */ ((1 * 37 + 18 + 16) << 24)); /* Using linear feedback shift register, bit16 = bit0^bit2^bit3^bit5 */ for(b2 = 2; b2--;) { Output(b2 ? /* #ifdef BIT2 */ 0 * 37 + 18 + 2 : /* #else */ 4 * 37 + 5); for(b3 = 2; b3--;) { Output(b3 ? /* #ifdef BIT3 */ 0 * 37 + 18 + 3 : /* #else */ 4 * 37 + 5); for(b5 = 2; b5--;) { Output((b5 ? /* #ifdef BIT5 */ 0 * 37 + 18 + 5 : /* #else */ 4 * 37 + 5) | (((b2 ^ b3 ^ b5) == 1 ? /* #ifndef BIT0 */ (2 * 37 + 18) : /* #ifdef BIT0 */ (0 * 37 + 18)) << 8) | /* #define BIT16 */ ((3 * 37 + 18 + 16) << 16) | /* #endif */ ((4 * 37 + 4) << 24)); if( !b5 ) Output(/* #endif */ 4 * 37 + 4); } if( !b3 ) Output(/* #endif */ 4 * 37 + 4); } if( !b2 ) Output(/* #endif */ 4 * 37 + 4); } /* seed = (bit16 | seed) >> 1 */ for(i = 0; i < 16; i++) { Output(/* #undef BIT%d */ (1 * 37 + 18 + i) | /* #ifdef BIT(%d + 1) */ ((0 * 37 + 18 + i + 1) << 8) | /* #define BIT%d */ ((3 * 37 + 18 + i) << 16) | /* #endif */ ((4 * 37 + 4) << 24)); } Output(/* #else */ (4 * 37 + 5) | /* -~ */ ((4 * 37 + 9) << 8) | /* #endif */ ((4 * 37 + 4) << 16)); Output(/* #endif */ (4 * 37 + 4) | /* #endif */ ((4 * 37 + 4) << 8) | /* #endif */ ((4 * 37 + 4) << 16) | /* #endif */ ((4 * 37 + 4) << 24)); return 0; }