Created
May 24, 2012 15:19
-
-
Save kik/2782177 to your computer and use it in GitHub Desktop.
cipher0x
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <cstring> | |
#include <algorithm> | |
using namespace std; | |
typedef unsigned char u8; | |
typedef unsigned short u16; | |
typedef unsigned int u32; | |
class Cipher0X | |
{ | |
private: | |
static u32 load_be32(const u8 *p) | |
{ | |
u32 v; | |
v = p[0] << 24; | |
v |= p[1] << 16; | |
v |= p[2] << 8; | |
v |= p[3] << 0; | |
return v; | |
} | |
static void store_be32(u8 *p, u32 v) | |
{ | |
p[0] = v >> 24; | |
p[1] = v >> 16; | |
p[2] = v >> 8; | |
p[3] = v >> 0; | |
} | |
static u32 Fadd(u32 a, u32 b, u16 c) | |
{ | |
u16 x = (a >> 16) + (b >> 16) + c; | |
u16 y = (a & 0xFFFF) + (b & 0xFFFF) + c; | |
return (x << 16) | y; | |
} | |
static u32 Fswap(u32 x) | |
{ | |
return ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4); | |
} | |
static u32 Frot(u32 x) | |
{ | |
return (x << 1) | (x >> 31); | |
} | |
static bool Fodd(u32 x) | |
{ | |
x ^= x >> 16; | |
x ^= x >> 8; | |
x ^= x >> 4; | |
x ^= x >> 2; | |
x ^= x >> 1; | |
return x & 1; | |
} | |
static u32 Fbitperm(u32 x, bool flag) | |
{ | |
if (flag) { | |
return | |
((x & 0x00AA0000) << 7) | | |
((x & 0x00005500) << 9) | | |
((x & 0x00000055) << 16) | | |
((x & 0xAA000000) >> 0) | | |
((x & 0x000000AA) >> 1) | | |
((x & 0x0055AA00) >> 8) | | |
((x & 0x55000000) >> 15); | |
} else { | |
return | |
((x & 0x00000055) << 1) | | |
((x & 0x0000AA00) << 7) | | |
((x & 0x00550000) << 9) | | |
((x & 0x000000AA) << 16) | | |
((x & 0x55000000) >> 0) | | |
((x & 0x00AA5500) >> 8) | | |
((x & 0xAA000000) >> 17); | |
} | |
} | |
static u32 F(u32 r, u32 sk, u16 cc, bool bitperm) | |
{ | |
u32 X = Fadd(r, sk, cc); | |
u32 Y = Fswap(X); | |
u32 M = Frot(sk); | |
if (Fodd(Y & M)) { | |
Y ^= ~M; | |
} | |
u32 T = Fbitperm(Y, bitperm); | |
return T ^ ((T << 8) | (T >> 24)) ^ Frot(T); | |
} | |
static u32 F0(u32 r, u32 sk) | |
{ | |
return F(r, sk, 0, false); | |
} | |
static u32 F1(u32 r, u32 sk) | |
{ | |
return F(r, sk, 0, true); | |
} | |
static u32 F2(u32 r, u32 sk) | |
{ | |
return F(r, sk, 0x5353, false); | |
} | |
static u32 F3(u32 r, u32 sk) | |
{ | |
return F(r, sk, 0x5353, true); | |
} | |
u8 protocol; | |
u32 skey[4]; | |
void Feistel0(u32& L, u32& R, int ski) | |
{ | |
L ^= F0(R, skey[ski]); | |
swap(L, R); | |
} | |
void Feistel1(u32& L, u32& R, int ski) | |
{ | |
L ^= F1(R, skey[ski]); | |
swap(L, R); | |
} | |
void Feistel2(u32& L, u32& R, int ski) | |
{ | |
L ^= F2(R, skey[ski]); | |
swap(L, R); | |
} | |
void Feistel3(u32& L, u32& R, int ski) | |
{ | |
L ^= F3(R, skey[ski]); | |
swap(L, R); | |
} | |
void enc_dec(u32 InL, u32 InR, | |
u32& OutL, u32& OutR, | |
bool dec) | |
{ | |
u32 L, R; | |
L = InL; | |
R = InR; | |
if (dec) { | |
Feistel1(L, R, 3); Feistel0(L, R, 2); Feistel0(L, R, 1); Feistel1(L, R, 0); | |
Feistel2(L, R, 3); Feistel0(L, R, 2); Feistel3(L, R, 1); Feistel1(L, R, 0); | |
Feistel2(L, R, 3); Feistel0(L, R, 2); Feistel2(L, R, 1); Feistel2(L, R, 0); | |
Feistel2(L, R, 3); Feistel1(L, R, 2); Feistel0(L, R, 1); Feistel1(L, R, 0); | |
} else { | |
Feistel1(L, R, 0); Feistel0(L, R, 1); Feistel1(L, R, 2); Feistel2(L, R, 3); | |
Feistel2(L, R, 0); Feistel2(L, R, 1); Feistel0(L, R, 2); Feistel2(L, R, 3); | |
Feistel1(L, R, 0); Feistel3(L, R, 1); Feistel0(L, R, 2); Feistel2(L, R, 3); | |
Feistel1(L, R, 0); Feistel0(L, R, 1); Feistel0(L, R, 2); Feistel1(L, R, 3); | |
} | |
swap(L, R); | |
OutL = L; | |
OutR = R; | |
} | |
void encrypt(u32 InL, u32 InR, u32& OutL, u32& OutR) | |
{ | |
enc_dec(InL, InR, OutL, OutR, false); | |
} | |
void decrypt(u32 InL, u32 InR, u32& OutL, u32& OutR) | |
{ | |
enc_dec(InL, InR, OutL, OutR, true); | |
} | |
void schedule(u32 KeyL, u32 KeyR) | |
{ | |
skey[0] = KeyL; | |
skey[1] = KeyR; | |
skey[2] = 0x08090A0B; | |
skey[3] = 0x0C0D0E0F; | |
u32 R; | |
if (protocol & 0x0c) { | |
R = 0x84E5C4E7; | |
} else { | |
R = 0x6AA32B6F; | |
} | |
for (int i = 0 ; i < 8 ; i++) { | |
R = skey[i % 4] = F0(skey[i % 4], R); | |
} | |
} | |
public: | |
void cbc_encdec(const u8 *Key, | |
const u8 *Input, | |
int Size, | |
u8 *Output, | |
const u8* IV, | |
bool dec) | |
{ | |
u32 KeyL = load_be32(&Key[0]); | |
u32 KeyR = load_be32(&Key[4]); | |
schedule(KeyL, KeyR); | |
u32 fbL = load_be32(&IV[0]); | |
u32 fbR = load_be32(&IV[4]); | |
for (; Size >= 8; Size -= 8, Input += 8, Output += 8) { | |
if (dec) { | |
u32 CL = load_be32(&Input[0]); | |
u32 CR = load_be32(&Input[4]); | |
u32 PL, PR; | |
decrypt(CL, CR, PL, PR); | |
store_be32(&Output[0], PL ^ fbL); | |
store_be32(&Output[4], PR ^ fbR); | |
fbL = CL; | |
fbR = CR; | |
} else { | |
u32 PL = load_be32(&Input[0]); | |
u32 PR = load_be32(&Input[4]); | |
u32 CL, CR; | |
encrypt(PL ^ fbL, PR ^ fbR, CL, CR); | |
store_be32(&Output[0], CL); | |
store_be32(&Output[4], CR); | |
fbL = CL; | |
fbR = CR; | |
} | |
} | |
if (Size > 0) { | |
u32 CL, CR; | |
encrypt(fbL, fbR, CL, CR); | |
u8 tmp[8]; | |
store_be32(&tmp[0], CL); | |
store_be32(&tmp[4], CR); | |
for (u32 i = 0 ; i < Size ; i++) { | |
Output[i] = Input[i] ^ tmp[i]; | |
} | |
} | |
} | |
void cbc_decrypt(const u8 *Key, | |
const u8 *Input, | |
int Size, | |
u8 *Output, | |
const u8* IV) | |
{ | |
cbc_encdec(Key, Input, Size, Output, IV, true); | |
} | |
void cbc_encrypt(const u8 *Key, | |
const u8 *Input, | |
int Size, | |
u8 *Output, | |
const u8* IV) | |
{ | |
cbc_encdec(Key, Input, Size, Output, IV, false); | |
} | |
explicit Cipher0X(u8 protocol) | |
: protocol(protocol) | |
{ | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment