#include #include #include #include #include typedef unsigned int Word; typedef unsigned char Byte; const Word swap_byte_order = 1, rounds = 64, buffer_size = 0x4000; Byte buffer[buffer_size + 16], sbox[16][256], inverse_sbox[16][256]; Word iv_buffer[buffer_size / 4], *iv, key[rounds * 4], inverse_key[rounds * 4], salt[4], ibaa_memory[256], ibaa_accumulator, ibaa_index, ibaa_value, i, j, k, x, y, z; int size, s2, s3; tm *lt, t; FILE *infile, *outfile; const char *text[4] = { "h\32:,<$4~$HhVF+\16tz;Z}8^\1Mt|:0t;^OC|1h|||L|Av>jLt{H*J" "H*\nb9]zIcx3hp9n`Nm*?$F-\rzWdN{\4nC&^KEf\33;z0h\0~z25K25" "\13Tb{R7\2P8\t04KDNBZo|Lt427J27\n42KT\27\37n'Kb9\rb;\14*" "I~PzGPZ!PX\"jg\4.W\16XP;PV\r(ZeRU\16~/.(Xft\22\3h\2=$>BV" "aD&%9@.eD,e~u3&[6\10z\rr\32k(X6\n{\rzbmX\"e$J\16|t3&U1 o" "JR/9n\t\33,7\13PJ{^\21[Z\23[@\36[p^yB\37[D\32\\P$fj\rzx" "\\,\6Dj[if[;D~BjYj&?B`\16\rR1\5" "&1Af[j:_4FiDDhDF9DP>\6@\2aP\6\n4Zv@\0b^}7j\7Mh\4NTrhld", "[yyyy-mm-dd] [input] [output]", "read error", "write error" }; Word rotr(Word p, int q) { return (p >> q) | (p << (32 - q)); } Word rotl(Word p, int q) { return (p << q) | (p >> (32 - q)); } void ConvertByteOrder(Word block_count, Word *data) { if( swap_byte_order ) for(i = 0; i < block_count; i++) data[i] = (rotl(data[i], 8) & 0x00ff00ff) | (rotr(data[i], 8) & 0xff00ff00); } void NextRand() { x = ibaa_memory[ibaa_index]; ibaa_accumulator = (ibaa_accumulator << 19) ^ (ibaa_accumulator >> 13); ibaa_memory[ibaa_index] = y = ibaa_memory[x & 0xff] + ibaa_accumulator + ibaa_value; ibaa_value = ibaa_memory[(y >> 8) & 0xff] + x; ibaa_index = (ibaa_index + 1) & 0xff; } void Mix(Word &a, Word &b, Word &c, Word &d) { a = rotl(a, 13); c = rotl(c, 3); d ^= c ^ (a << 3); b ^= a ^ c; d = rotl(d, 7); b = rotl(b, 1); a ^= b ^ d; c ^= d ^ (b << 7); a = rotl(a, 5); c = rotl(c, 22); } void Unmix(Word &a, Word &b, Word &c, Word &d) { c = rotr(c, 22); a = rotr(a, 5); c ^= d ^ (b << 7); a ^= b ^ d; d = rotr(d, 7); b = rotr(b, 1); d ^= c ^ (a << 3); b ^= a ^ c; c = rotr(c, 3); a = rotr(a, 13); } void InitSbox(int group) { for(x = 0; x < 16; x++) { size = text[0][(group * 16 + x) * 3] ^ 81; s2 = text[0][(group * 16 + x) * 3 + 1] ^ 25; s3 = text[0][(group * 16 + x) * 3 + 2] ^ 16; for(i = 0; i < 256; i++) { j = ((i + size) & 0x7f) | (i & 0x80); j = (((j >> 1) + s2) & 0x7f) | ((j << 7) & 0x80); sbox[x][i] = (((j >> 1) + s3) & 0x7f) | ((j << 7) & 0x80); } for(y = 0; y < 2; y++) for(z = 0; z < 8; z++) for(i = 0; i < 256; i++) { k = sbox[x][i] ^ sbox[x][i ^ (1 << z)]; if( !(k & (k - 1)) ) { j = i ^ (1 << ((z + 1) % 8)); s3 = sbox[x][i]; sbox[x][i] = sbox[x][j]; sbox[x][j] = s3; } } } } void Decrypt(Word *data) { for(x = 0; x < rounds; x++) { Unmix(data[0], data[1], data[2], data[3]); for(y = 0; y < 4; y++) { k = data[y]; for(z = 0; z < 4; z++) { k = rotl(k, 8); k = (k & ~0xff) | inverse_sbox[x & 15][k & 0xff]; } data[y] = k ^ inverse_key[x * 4 + y]; } } for(x = 0; x < 4; x++) data[x] ^= iv[x]; } int Read(int size, void *output) { return fread(output, 1, size, infile); } void Write(int size) { fwrite(buffer, size, 1, outfile); } void Print(int msg) { puts(text[msg]); } void Close() { fclose(infile); } int main(int argc, char **argv) { if( argc < 2 ) Print(1); else { int arg_offset; memset(&t, 0, sizeof(t)); if( sscanf(argv[1], "%d-%d-%d", &t.tm_year, &t.tm_mon, &t.tm_mday) - 3 ) { arg_offset = 1; time_t s = time(NULL); lt = localtime(&s); t.tm_year = lt->tm_year; t.tm_mon = lt->tm_mon; t.tm_mday = lt->tm_mday; } else { arg_offset = 2; t.tm_year -= 1900; t.tm_mon--; } if( !(infile = fopen(argv[arg_offset], "rb")) ) { Print(2); return 1; } memset(ibaa_memory, 10, 1024); Read(1024, ibaa_memory); Close(); ConvertByteOrder(256, ibaa_memory); ibaa_accumulator = 1; for(i = ibaa_index = ibaa_value = 0; i < 4; key[i++] = ibaa_value) for(j = 0; j < 8192; j++) NextRand(); InitSbox(8); for(i = 1; i < rounds; i++) { for(j = 0; j < 4; j++) { x = key[(i - 1) * 4 + j]; for(k = 0; k < 4; k++) { x = (x & ~0xff) | sbox[i & 15][x & 0xff]; x = rotr(x, 8); } key[i * 4 + j] = x; } Mix(key[i * 4], key[i * 4 + 1], key[i * 4 + 2], key[i * 4 + 3]); } arg_offset++; if( argc > arg_offset && (argv[arg_offset][0] - '-' || argv[arg_offset][1]) ) { if( !(infile = fopen(argv[arg_offset], "rb")) ) { Print(2); return 1; } } else { infile = stdin; } arg_offset++; if( argc > arg_offset && (argv[arg_offset][0] - '-' && argv[arg_offset][1]) ) { if( !(outfile = fopen(argv[arg_offset], "wb+")) ) { Close(); Print(3); return 1; } } else { outfile = stdout; } z = 2551443; InitSbox((((mktime(&t) - 434928) % z) * 8) / z); if( arg_offset - 4 ) { for(i = 0; i < rounds; i++) for(j = 0; j < 4; j++) inverse_key[(rounds - 1 - i) * 4 + j] = key[i * 4 + j]; for(j = 0; j < 16; j++) for(i = 0; i < 256; i++) inverse_sbox[15 - j][sbox[j][i]] = (Byte)i; if( Read(16, salt) == 16 ) { ConvertByteOrder(4, salt); iv = salt; size = 16; for(j = 0; size == 16 && (size = Read(buffer_size - j, buffer + j)) > 0; j = 16) { size += j; s2 = (size & ~15) - 16; if( s2 > 0 ) { ConvertByteOrder(s2 / 4, (Word*)buffer); memcpy(iv_buffer, buffer, s2); for(i = 0; i < (Word)s2; i += 16) { Decrypt((Word*)(buffer + i)); iv = (Word*)(((Byte*)iv_buffer) + i); } ConvertByteOrder(s2 / 4, (Word*)buffer); iv = (Word*)memcpy(salt, iv, 16); Write(s2); size -= s2; memmove(buffer, buffer + s2, size); } } if( size == 17 && buffer[16] < 16 ) { if( !(j = (Word)buffer[16]) ) j = 16; ConvertByteOrder(4, (Word*)buffer); Decrypt((Word*)buffer); ConvertByteOrder(4, (Word*)buffer); Write(j); } } } else { timeval tv; gettimeofday(&tv, NULL); memcpy(ibaa_memory, &tv, sizeof(tv)); ibaa_memory[99] = getpid(); for(i = 0; i < 8192; i++) NextRand(); for(i = 0; i < 4; salt[i++] = ibaa_value) NextRand(); iv = (Word*)memcpy(iv_buffer, salt, 16); ConvertByteOrder(4, salt); memcpy(buffer, salt, 16); Write(16); for(size = 0; (size & 15) == 0 && (size = Read(buffer_size, buffer)) > 0;) { for(i = 0; i < 16; buffer[size + i++] = ibaa_value & 0xff) NextRand(); s2 = (size + 15) / 16; ConvertByteOrder(s2 * 4, (Word*)buffer); for(i = 0; i < (Word)size; i += 16) { Word *data = (Word*)(buffer + i); for(j = 0; j < 4; j++) data[j] ^= iv[j]; for(j = 0; j < rounds; j++) { for(k = 0; k < 4; k++) { x = data[k] ^ key[j * 4 + k]; for(z = 0; z < 4; z++) { x = (x & ~0xff) | sbox[j & 15][x & 0xff]; x = rotr(x, 8); } data[k] = x; } Mix(data[0], data[1], data[2], data[3]); } iv = (Word*)(buffer + i); } iv = (Word*)memcpy(iv_buffer, iv, 16); ConvertByteOrder(s2 * 4, (Word*)buffer); Write(s2 * 16); } buffer[0] = size & 15; Write(1); } Close(); infile = outfile; Close(); } return 0; }