#include typedef unsigned int _; _ L, l[256], I[256], O, K[256], n, y, a, r, u, k, o; #define q(code) \ code char *DecoderHeader = \ "0},L,O,l[256],I[256],n,y,a,r,u,k,o;" \ #code "char*S,s[]=\"", q( _ *x() { if( !L-- ) { y += ++a; for(o = 0; o < 256; y = l[o++] = I[(k >> 10) & 255] + u) { n ^= (o & 1) ? n >> ((o & 2) ? 16 : 6) : n << ((o & 2) ? 2 : 13); u = I[o]; k = I[o] = I[255 & (u >> 2)] + (n += I[(o + 128) & 255]) + y; } L = 255; } return &l[L]; } _ *X() { for(O = 0; O < 256; I[O++] = 0); for(O = 0; O < sizeof(K) / sizeof(_); O++) I[O & 255] ^= K[O]; for(n = y = a = L = O = 0; O < 1 << 24; O++) x(); r = O = 0; return &O; } ) /* KeyHeader is recycled as output buffer */ KeyHeader[256] = "#ifdef/*\n" "'true' or q{\n" "exec head -8 $0\n" "};for(open$O,$0;<$O>;print if$f){$f|=/^$/;}q{*/q", *KeyFooter = "#endif/*}||1;\n" "__DATA__ */\n" "\n" "#ifndef q\n" "#define q\n" "#include\n" "typedef unsigned int _;_ K[]={\n" "#include __FILE__\n" "#undef q", *DecoderFooter = "\";int main(){X();for(S=s+*K;*S>37;){for(o=0;o<5;o++)r=r*85+(83+*S++)%89;r", *Epilogue = "^=*x();for(o=0;o<4;o++){s[O++]=r&255;r>>=8;}}return!fwrite(s,O-*S%5,1,stdout);}\n" "#endif", s[] = "KfWWw|Z};fRo?JtJaVoRURonB}h@o?)d.X)NSTIUCz7@%"; enum OutputState { KEY_HEADER = 0, KEY, KEY_FOOTER, DECODER_HEADER, ENCODED_DATA, DATA_PADDING, PADDING_REMAINDER, EPILOGUE, END }; #include #include int main() { FILE *urandom; int state, flush_buffer, cursor, key_cursor, read_size; _ encode_block; char *copy_from, *write_to, c; /* Initialize random number generator to generate the seed */ if( (urandom = fopen("/dev/urandom", "rb")) != NULL ) { fread(K, sizeof(K), 1, urandom); fclose(urandom); } /* Always mix in current time, in case if urandom is not available */ gettimeofday((struct timeval*)K, NULL); X(); /* Generate seed for encryption stream */ for(O = 0; O < sizeof(K) / sizeof(_); O++) K[O] = 0; K[0] = 86; /* First number is the offset */ for(O = 1; O < 12; O++) K[O] = *x(); X(); /* Main output loop */ copy_from = KeyHeader; write_to = KeyHeader; cursor = key_cursor = flush_buffer = 0; for(state = KEY_HEADER; state != END;) { /* Insert quote at beginning of the line */ if( (state == ENCODED_DATA || state == DATA_PADDING) && write_to == KeyHeader ) { *write_to++ = '\"'; } /* Copy character */ c = copy_from[cursor++]; /* Skip spaces for DecoderHeader */ if( c != ' ' || state != DECODER_HEADER ) { if( c != '\0' ) { /* Copy from copy_from to output, removing trigraphs. Trigraphs only happen inside quoted strings, so we don't need to check for quotes. Don't worry about trigraphs near the end of the line, since ??" is not a valid trigraph. */ if( c == '?' && write_to[-1] == '?' && write_to != KeyHeader + 77 ) *write_to++ = '\\'; *write_to++ = c; } else { /* Exhausted copy_from, refill buffer */ switch( state ) { case KEY_HEADER: case KEY_FOOTER: case DECODER_HEADER: case PADDING_REMAINDER: case EPILOGUE: /* Initialize next state */ state++; copy_from = state == KEY ? write_to : state == DECODER_HEADER ? DecoderHeader : state == ENCODED_DATA ? s : Epilogue; assert(state != KEY || *copy_from == '\0'); cursor = 0; /* Flush fully copied data. Since the line is not yet completed when we enter ENCODED_DATA state, don't flush the line just yet. */ if( state != ENCODED_DATA ) { flush_buffer = 1; *write_to = '\0'; write_to = KeyHeader; } break; case KEY: write_to += sprintf(write_to, "%uU,", K[key_cursor++]); if( (key_cursor % 6) == 0 ) { /* Flush a single line of key values */ flush_buffer = 1; write_to = KeyHeader; if( key_cursor == 12 ) { /* Initialize KEY_FOOTER state */ state++; copy_from = KeyFooter; cursor = 0; } } break; case ENCODED_DATA: assert(copy_from == s); assert(cursor > 4); read_size = fread(s, 1, 4, stdin); if( read_size > 0 ) { /* Encode next 4 bytes */ encode_block = 0; for(O = 0; O < 4; O++) encode_block |= ((s[O] & 0xff) << (8 * O)); /* Encrypt */ encode_block ^= *x(); /* Convert to base 85 */ for(cursor = 5; cursor != 0;) { O = encode_block % 85; encode_block /= 85; s[--cursor] = (O <= 31 ? O + 95 : O + 6); } /* Insert \0 at end of base 85 string */ O = 5; } else { /* End of stdin */ O = 0; cursor = 0; } /* Append size byte for final block */ if( read_size < 4 ) { s[O++] = read_size == 0 ? '#' : read_size == 1 ? '!' : read_size == 2 ? '%' : '$'; /* Initialize DATA_PADDING state */ state++; assert(copy_from == s); } s[O] = '\0'; break; case DATA_PADDING: /* No more bytes from base85 stream */ if( write_to == KeyHeader + 6 ) { /* Initialize PADDING_REMAINDER state */ copy_from = DecoderFooter; cursor = 0; state++; } else { *write_to = (*x() % (127 - 33)) + 33; if( *write_to == '\"' || *write_to == '\\' || *write_to == '?' ) ++*write_to; write_to++; cursor--; assert(copy_from[cursor] == '\0'); } break; default: assert(0); } } } /* Closing quote */ if( (state == ENCODED_DATA || state == DATA_PADDING) && write_to == KeyHeader + 78 ) { *write_to++ = '\"'; } /* Flush completed line */ if( (state == DECODER_HEADER || state == ENCODED_DATA || state == DATA_PADDING) && write_to == KeyHeader + 79 ) { *write_to++ = '\0'; flush_buffer = 1; write_to = KeyHeader; } if( flush_buffer != 0 ) { puts(KeyHeader); flush_buffer = 0; } } return 0; }