/* container.c - Don Yang (uguu.org) Branched from nyaruko12.c 08/26/12 */ #include #include #include static char 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", *DecoderHeader = " 0" "}, L, O, l[256], I[256], n, y, a, r, u, k, o;" "_ *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];" /* patch: (u >> 2) & 255 */ "k = I[o] = I[255 & (u >> 2)] + (n += I[(o + 128) & 255]) + y;" "}" "L = 255;" "}" "return &l[L];" "}" "void /**/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;" "}" "char *S, s[] =\"", *DecoderFooter = /* "; 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); } 012345 */ "\";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", Base85Buffer[] = "KfWWw|Z};fRo?JtJaVoRURonB}h@o?)d.X)NSTIUCz7@%"; typedef unsigned int _; _ K[256] = { 86, 0 }, L, O, l[256], I[256], n, y, a, r, u, k, o; _ *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[(u >> 2) & 255] + (n += I[(o + 128) & 255]) + y; } L = 255; } return &l[L]; } void /**/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; } enum OutputState { OUTPUT_KEY_HEADER = 0, OUTPUT_KEY, OUTPUT_KEY_FOOTER, OUTPUT_DECODER_HEADER, OUTPUT_ENCODED_DATA, OUTPUT_ENCODED_DATA_PADDING, OUTPUT_EPILOGUE, OUTPUT_END }; int main() { FILE *urandom; int output_state; int flush_output_buffer; int stream_cursor = -1; int read_size; _ encode_block; char *output_buffer = NULL; char *write_output_buffer = NULL; char 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 */ assert(sizeof(K) >= sizeof(struct timeval)); gettimeofday((struct timeval*)K, NULL); X(); /* Generate a few numbers to be the seed for encrypting input stream. The first number is always fixed since it's the offset to encrypted data. */ for(O = 0; O < sizeof(K) / sizeof(_); O++) K[O] = 0; K[0] = 86; for(O = 1; O < 12; O++) K[O] = *x(); X(); /* Output loop. We use a state machine that advances cursors on multiple streams that fills the hierarchical buffers. The upshot of this is that only a single puts call is needed for all output. */ for(output_state = OUTPUT_KEY_HEADER; output_state != OUTPUT_END;) { /* Fill buffer */ switch( output_state ) { case OUTPUT_KEY_HEADER: /* {{{ Output key header */ output_buffer = KeyHeader; flush_output_buffer = 1; /* Initialize next state */ output_state++; stream_cursor = 0; write_output_buffer = KeyHeader; break; /* }}} */ case OUTPUT_KEY: /* {{{ Output key data */ if( stream_cursor != 12 ) { /* Fill up buffer for seed data. First fixed string is reused as buffer space. */ assert(output_buffer == KeyHeader); write_output_buffer += sprintf(write_output_buffer, "%uU,", K[stream_cursor++]); if( (stream_cursor % 6) == 0 ) { flush_output_buffer = 1; write_output_buffer = KeyHeader; } } else { /* Initialize next state */ output_state++; output_buffer = KeyFooter; } break; /* }}} */ case OUTPUT_KEY_FOOTER: /* {{{ Output key footer */ assert(output_buffer == KeyFooter); flush_output_buffer = 1; /* Initialize next state */ output_state++; stream_cursor = 0; write_output_buffer = output_buffer; break; /* }}} */ case OUTPUT_DECODER_HEADER: /* {{{ Output decoder header */ assert(output_buffer == KeyFooter); c = DecoderHeader[stream_cursor++]; if( c != ' ' ) { if( c != '\0' ) { *write_output_buffer++ = c; } else { /* Initialize next state */ output_state++; stream_cursor = 0; } } if( write_output_buffer == output_buffer + 79 ) { *write_output_buffer = '\0'; flush_output_buffer = 1; write_output_buffer = output_buffer; } break; /* }}} */ case OUTPUT_ENCODED_DATA: /* {{{ Output encoded data */ assert(output_buffer == KeyFooter); if( write_output_buffer == output_buffer ) *write_output_buffer++ = '\"'; c = Base85Buffer[stream_cursor++]; if( c == '\0' ) { /* Exhausted buffered characters, fetch next word from stdin */ read_size = fread(KeyHeader, 1, 4, stdin); if( read_size > 0 ) { /* Convert byte order and encrypt */ encode_block = 0; for(O = 0; O < 4; O++) encode_block |= ((KeyHeader[O] & 0xff) << (8 * O)); encode_block ^= *x(); /* Convert to base 85 */ for(stream_cursor = 5; stream_cursor != 0;) { O = encode_block % 85; encode_block /= 85; Base85Buffer[--stream_cursor] = (O <= 31 ? O + 95 : O + 6); } O = 5; } else { O = 0; stream_cursor = 0; } /* Append size byte for final block */ if( read_size < 4 ) { assert(O == 0 || O == 5); Base85Buffer[O++] = read_size == 0 ? '#' : read_size == 1 ? '!' : read_size == 2 ? '%' : '$'; /* Initialize next state */ output_state++; } Base85Buffer[O] = '\0'; assert(stream_cursor == 0); } else { assert(write_output_buffer > output_buffer); if( write_output_buffer[-1] == '?' && c == '?' && write_output_buffer != output_buffer + 77 ) { /* Don't worry about trigraphs at the end of the line, since ??" is not a valid trigraph sequence. */ *write_output_buffer++ = '\\'; } *write_output_buffer++ = c; } if( write_output_buffer >= output_buffer + 78 ) { *write_output_buffer++ = '\"'; *write_output_buffer = '\0'; flush_output_buffer = 1; write_output_buffer = output_buffer; } break; /* }}} */ case OUTPUT_ENCODED_DATA_PADDING: /* {{{ Extra padding after final block for alignment */ assert(output_buffer == KeyFooter); if( write_output_buffer == output_buffer ) *write_output_buffer++ = '\"'; c = Base85Buffer[stream_cursor]; if( c != '\0' ) { if( write_output_buffer[-1] == '?' && c == '?' && write_output_buffer != output_buffer + 77 ) { *write_output_buffer++ = '\\'; } *write_output_buffer++ = c; stream_cursor++; } else { c = (*x() % (127 - 33)) + 33; if( c == '\"' || c == '\\' || c == '?' ) c++; *write_output_buffer++ = c; } if( write_output_buffer == output_buffer + 78 ) { *write_output_buffer++ = '\"'; *write_output_buffer = '\0'; flush_output_buffer = 1; write_output_buffer = output_buffer; } else if( write_output_buffer == output_buffer + 6 ) { /* Last line */ for(stream_cursor = 0; DecoderFooter[stream_cursor] != '\0'; stream_cursor++) { *write_output_buffer++ = DecoderFooter[stream_cursor]; } assert(write_output_buffer == output_buffer + 79); *write_output_buffer = '\0'; /* Next state */ output_state++; flush_output_buffer = 1; } break; /* }}} */ case OUTPUT_EPILOGUE: /* {{{ Output final lines */ assert(output_buffer == KeyFooter); output_buffer = Epilogue; flush_output_buffer = 1; /* End */ output_state++; break; /* }}} */ default: assert(0); break; } /* Flush pending buffer */ if( flush_output_buffer != 0 ) { puts(output_buffer); flush_output_buffer = 0; } } return 0; }