typedef unsigned int _; _ L, l[256], I[256], O, K[256], n, y, a, r, u, k, o; #define q(code) \ code \ char *write_to, *copy_from, s[] = \ "KfWWw|Z};fRo?JtJaVoRURonB}h@o?)d.X)NSTIUCz7@%", \ *StringTable[] = \ { \ s, \ "#endif/*}||1;\n" \ "__DATA__ */\n" \ "\n" \ "#ifndef q\n" \ "#define q\n" \ "#include\n" \ "typedef unsigned int _;_ K[]={\n" \ "#include __FILE__\n" \ "#undef q", \ "0},L,O,l[256],I[256],n,y,a,r,u,k,o;" \ #code "char*S,s[]=\"", \ s, \ s, \ "\";int main(){X();for(S=s+*K;*S>37;){for(o=0;o<5;o++)r=r*85+(83+*S++)%89;r", \ "^=*x();for(o=0;o<4;o++){s[O++]=r&255;r>>=8;}}return!fwrite(s,O-*S%5,1,stdout);}\n" \ "#endif", \ s \ }, \ /* 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", c; 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; } ) 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; /* 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 */ if( state == 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 ) flush_buffer |= 2; } } else if( state == ENCODED_DATA ) { 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 */ flush_buffer |= 2; } s[O] = '\0'; } else if( state == DATA_PADDING ) { /* No more bytes from base85 stream */ if( write_to == KeyHeader + 6 ) { /* Initialize PADDING_REMAINDER state */ flush_buffer |= 2; } else { *write_to = (*x() % (127 - 33)) + 33; if( *write_to == '\"' || *write_to == '\\' || *write_to == '?' ) ++*write_to; write_to++; cursor--; } } else { /* Initialize next state */ StringTable[0] = write_to; flush_buffer |= 2; } } } /* Initialize next state */ if( flush_buffer > 1 ) { flush_buffer -= 2; copy_from = StringTable[state]; if( state < DECODER_HEADER || state > DATA_PADDING ) { flush_buffer = 1; if( state != KEY ) *write_to = '\0'; write_to = KeyHeader; } if( state != ENCODED_DATA ) cursor = 0; state++; } /* 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; }