/** * NODE-ADDRESS-ENCODING TEST PROGRAM (test.d) * * written by Anonymous-User @ bbs.shingetsu.info. * */ import std.stdio; import std.base64; import std.c.string; int main() { const char[] TEST_DATA = "IKwLoHt1JDdn9pi7+mQxqvMAdggprMYTHHpacJ80sA==";// 0.0.0.0:0001 ubyte[] src_data; // port 0001 src_data ~= 0x01; src_data ~= 0x00; // address 0.0.0.0 src_data ~= cast(ubyte[])"0.0.0.0"; // format: [][SHA1-HASH][IPAddress] writef(" TEST_DATA: %s\n", (cast(ubyte[])std.base64.decode(TEST_DATA))[22 .. length]); // encode RC6Stream crypter = new RC6Stream(SHARE_NODE_KEY); ubyte[9] enc; crypter.streamEncrypt(src_data, enc); writef("ENCODE_DATA: %s\n", enc); // output: // TEST_DATA: [198,19,28,122,90,112,159,52,176] // ENCODE_DATA: [198,19,28,122,90,112,159,52,176] return 0; } /** * RC6-NODE-KEY * */ static const ubyte[] SHARE_NODE_KEY = [ 0x9E, 0xED, 0x11, 0x7C, 0x85, 0xCD, 0x12, 0x8A, 0x63, 0xAF, 0x45, 0x9B, 0x96, 0xD6, 0xFB, 0x8F, 0x09, 0x4D, 0x3A, 0x09 ]; /** * RC6-OFBC-STREAM-CIPHER-ALGORITHM * * This algorithm is compatible with the Share-EX2. * */ class RC6Exception: Exception { this(char[] msg) { super(msg); } } class RC6Stream { protected: const uint DWORD_BITS = uint.sizeof * 8; const uint ROUNDS = 20; const uint SBOX[] = [ 0xB7E15163, 0x5618CB1C, 0xF45044D5, 0x9287BE8E, 0x30BF3847, 0xCEF6B200, 0x6D2E2BB9, 0x0B65A572, 0xA99D1F2B, 0x47D498E4, 0xE60C129D, 0x84438C56, 0x227B060F, 0xC0B27FC8, 0x5EE9F981, 0xFD21733A, 0x9B58ECF3, 0x399066AC, 0xD7C7E065, 0x75FF5A1E, 0x1436D3D7, 0xB26E4D90, 0x50A5C749, 0xEEDD4102, 0x8D14BABB, 0x2B4C3474, 0xC983AE2D, 0x67BB27E6, 0x05F2A19F, 0xA42A1B58, 0x42619511, 0xE0990ECA, 0x7ED08883, 0x1D08023C, 0xBB3F7BF5, 0x5976F5AE, 0xF7AE6F67, 0x95E5E920, 0x341D62D9, 0xD254DC92, 0x708C564B, 0x0EC3D004, 0xACFB49BD, 0x4B32C376, 0xE96A3D2F, 0x87A1B6E8, 0x25D930A1, 0xC410AA5A, 0x62482413, 0x007F9DCC, 0x9EB71785, 0x3CEE913E ]; ubyte[16] m_initial_iv; ubyte[16] m_current_iv; uint[ROUNDS * 2 + 4] m_state; uint rotl(uint x, uint y) { version(X86) { int r; asm { mov EAX, x ; mov ECX, y ; rol EAX, CL ; mov r, EAX ; }; return r; } else { return (x << (y & (DWORD_BITS - 1))) | (x >> (DWORD_BITS - (y & (DWORD_BITS - 1)))); } } uint rotr(uint x, uint y) { version(X86) { int r; asm { mov EAX, x ; mov ECX, y ; ror EAX, CL ; mov r, EAX ; }; return r; } else { return (x >> (y & (DWORD_BITS - 1))) | (x << (DWORD_BITS - (y & (DWORD_BITS - 1)))); } } void incrementBlock(ubyte[] block) { ++block[length - 1]; if (block[length - 1] == 0 && block.length > 1) { incrementBlock(block[0 .. length - 1]); } } public: this(ubyte[] key, ubyte[] iv = null) { uint[] lkey; int key_index, state_index; uint x, y, ecx; if (key.length == 0 || key.length > 256) { throw new RC6Exception("RC6: Key length must be between 1 and 256 bytes"); } if (iv.length == m_initial_iv.length) { // if iv.length != 0 m_initial_iv[] = iv; m_current_iv[] = m_initial_iv; } m_state[] = SBOX[0 .. m_state.length]; if (key.length % 4) { lkey = new uint[key.length / 4 + 1]; } else { lkey = new uint[key.length / 4]; } (cast(ubyte*)lkey.ptr)[0 .. key.length] = key;; key_index = state_index = x = y = 0; if (lkey.length > m_state.length) { ecx = lkey.length * 3; } else { ecx = m_state.length * 3; } while(ecx--) { x = rotl(m_state[state_index] + x + y, 3); m_state[state_index] = x; y = rotl(lkey[key_index] + x + y, x + y); lkey[key_index] = y; state_index = (state_index + 1) % m_state.length; key_index = (key_index + 1) % lkey.length; } lkey = null; } void blockEncrypt(uint[4] input, uint[4] data) { uint x, y; data[] = input; data[1] += m_state[0]; data[3] += m_state[1]; for (int i = 1; i <= ROUNDS; ++i) { x = rotl(data[1] * ((data[1] * 2) + 1), 5); y = rotl(data[3] * ((data[3] * 2) + 1), 5); data[0] = rotl(data[0] ^ x, y) + m_state[i * 2]; data[2] = rotl(data[2] ^ y, x) + m_state[(i * 2) + 1]; x = data[0]; data[0] = data[1]; data[1] = data[2]; data[2] = data[3]; data[3] = x; } data[0] = data[0] + m_state[(ROUNDS * 2) + 2]; } void blockDecrypt(uint[4] input, uint[4] data) { uint x, y; data[] = input; // data[2] -= m_state[ROUNDS * 2 + 3]; // removed data[0] -= m_state[ROUNDS * 2 + 2]; for (int i = 1; i <= ROUNDS; ++i) { x = data[0]; data[0] = data[3]; data[3] = data[2]; data[2] = data[1]; data[1] = x; x = rotl(data[1] * (data[1] * 2 + 1), 5); y = rotl(data[3] * (data[3] * 2 + 1), 5); data[2] = rotr(data[2] - m_state[i * 2 + 1], x) ^ y; data[0] = rotr(data[0] - m_state[i * 2], y) ^ x; } data[3] -= m_state[1]; data[1] -= m_state[0]; } void streamEncrypt(ubyte[] input, ubyte[] data) in { assert(input.length == data.length); } body { ubyte[16] temp; uint[4] scrb; uint[4] current; uint x; for (int i = 0; i < input.length; ++i) { current[] = (cast(uint*)m_current_iv.ptr)[0 .. 4]; blockEncrypt(current, scrb); temp[] = (cast(ubyte*)scrb.ptr)[0 .. 16]; data[i] = input[i] ^ temp[0]; memcpy(&m_current_iv[0], &m_current_iv[1], m_current_iv.length -1); m_current_iv[length-1] = data[i]; } } void streamDecrypt(ubyte[] input, ubyte[] data) { // not implemented } }