typedef unsigned int _; _ L, l[256], I[256], O, K[256], n, y, a, r, u, k, o; #define q(code) \ code char *S = \ "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[] = "#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, EPILOGUE, END }; #include #include int main() { FILE *urandom; int output_state, flush_buffer, cursor, read_size; _ encode_block; char *output, *p, 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 */ cursor = flush_buffer = 0; output = p = NULL; for(output_state = KEY_HEADER; output_state != END;) { switch( output_state ) { case KEY_HEADER: output = KeyHeader; flush_buffer = 1; /* Next state */ output_state++; cursor = 0; p = output; /* Reuse buffer for writing */ break; case KEY: if( cursor != 12 ) { /* Fill up buffer with seed data */ p += sprintf(p, "%uU,", K[cursor++]); if( (cursor % 6) == 0 ) { flush_buffer = 1; p = KeyHeader; } } else { /* Wrote all seeds, initialize next state */ output_state++; } break; case KEY_FOOTER: output = KeyFooter; flush_buffer = 1; /* Next state */ output_state++; cursor = 0; p = output; break; case DECODER_HEADER: c = S[cursor++]; if( c != ' ' ) { if( c != '\0' ) { *p++ = c; } else { /* Next state */ output_state++; cursor = 0; S = s; } } if( p == output + 79 ) { *p = '\0'; flush_buffer = 1; p = output; } break; case ENCODED_DATA: if( p == output ) *p++ = '\"'; c = S[cursor++]; if( c != '\0' ) { /* Copy next base85 characters to output, inserting escapes for trigraphs. No trigraph handling is done near the end of the line, since ??" is not a valid trigraph. */ if( p[-1] == '?' && c == '?' && p != output + 77 ) *p++ = '\\'; *p++ = c; } else { /* Exhausted buffered base85 characters, encode next word */ read_size = fread(KeyHeader, 1, 4, stdin); if( read_size > 0 ) { /* Serialize bytes to word */ encode_block = 0; for(O = 0; O < 4; O++) encode_block |= ((KeyHeader[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); } 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 next state */ output_state++; } s[O] = '\0'; } if( p == output + 78 ) { *p++ = '\"'; *p = '\0'; flush_buffer = 1; p = output; } break; case DATA_PADDING: if( p == output ) *p++ = '\"'; c = S[cursor++]; if( c != '\0' ) { /* Copy remaining bytes */ if( p[-1] == '?' && c == '?' && p != output + 77 ) *p++ = '\\'; *p++ = c; } else { /* No more bytes from base85 stream, fill with random bytes */ c = (*x() % (127 - 33)) + 33; if( c == '\"' || c == '\\' || c == '?' ) c++; *p++ = c; cursor--; } if( p == output + 78 ) { *p++ = '\"'; *p = '\0'; flush_buffer = 1; p = output; } if( s[cursor] == '\0' && p == output + 6 ) { /* Last line */ for(cursor = 0; DecoderFooter[cursor] != '\0'; cursor++) *p++ = DecoderFooter[cursor]; *p = '\0'; /* Next state */ output_state++; flush_buffer = 1; } break; case EPILOGUE: output = Epilogue; flush_buffer = 1; /* End */ output_state++; break; default: break; } if( flush_buffer != 0 ) { puts(output); flush_buffer = 0; } } return 0; }