895 lines
24 KiB
C#
895 lines
24 KiB
C#
|
using System;
|
||
|
|
||
|
namespace Payroll.BO
|
||
|
{
|
||
|
public class AES
|
||
|
{
|
||
|
private int _nNk, _nNb, _nNr;
|
||
|
private int[] _nOnBits, _n2Power, _nFKey, _nRKey, _nFTable, _nRTable, _nRCo;
|
||
|
private byte[] _bytOnBits, _byt2Power, _nInCo, _nFbSub, _nRbSub, _nPTab, _nLTab, _nFi, _nRi;
|
||
|
|
||
|
public AES()
|
||
|
{
|
||
|
_nInCo=new byte[4];
|
||
|
_nOnBits=new int[32];
|
||
|
_n2Power=new int[32];
|
||
|
_nFKey=new int[128];
|
||
|
_nRKey=new int[120];
|
||
|
_nFTable=new int[256];
|
||
|
_nRTable=new int[256];
|
||
|
_nRCo=new int[30];
|
||
|
_bytOnBits=new byte[8];
|
||
|
_byt2Power=new byte[8];
|
||
|
_nFi=new byte[24];
|
||
|
_nRi=new byte[24];
|
||
|
_nInCo=new byte[4];
|
||
|
_nFbSub=new byte[256];
|
||
|
_nRbSub=new byte[256];
|
||
|
_nPTab=new byte[256];
|
||
|
_nLTab=new byte[256];
|
||
|
|
||
|
_nInCo[0]=0xB;
|
||
|
_nInCo[1]=0xD;
|
||
|
_nInCo[2]=0x9;
|
||
|
_nInCo[3]=0xE;
|
||
|
|
||
|
// Could have done this with a loop calculating each value, but simply
|
||
|
// assigning the values is quicker - BITS SET FROM RIGHT
|
||
|
_bytOnBits[0]=1; // 00000001
|
||
|
_bytOnBits[1]=3; // 00000011
|
||
|
_bytOnBits[2]=7; // 00000111
|
||
|
_bytOnBits[3]=15; // 00001111
|
||
|
_bytOnBits[4]=31; // 00011111
|
||
|
_bytOnBits[5]=63; // 00111111
|
||
|
_bytOnBits[6]=127; // 01111111
|
||
|
_bytOnBits[7]=255; // 11111111
|
||
|
|
||
|
// Could have done this with a loop calculating each value, but simply
|
||
|
// assigning the values is quicker - POWERS OF 2
|
||
|
_byt2Power[0]=1; // 00000001
|
||
|
_byt2Power[1]=2; // 00000010
|
||
|
_byt2Power[2]=4; // 00000100
|
||
|
_byt2Power[3]=8; // 00001000
|
||
|
_byt2Power[4]=16; // 00010000
|
||
|
_byt2Power[5]=32; // 00100000
|
||
|
_byt2Power[6]=64; // 01000000
|
||
|
_byt2Power[7]=128; // 10000000
|
||
|
|
||
|
// Could have done this with a loop calculating each value, but simply
|
||
|
// assigning the values is quicker - BITS SET FROM RIGHT
|
||
|
_nOnBits[0]=1; // 00000000000000000000000000000001
|
||
|
_nOnBits[1]=3; // 00000000000000000000000000000011
|
||
|
_nOnBits[2]=7; // 00000000000000000000000000000111
|
||
|
_nOnBits[3]=15; // 00000000000000000000000000001111
|
||
|
_nOnBits[4]=31; // 00000000000000000000000000011111
|
||
|
_nOnBits[5]=63; // 00000000000000000000000000111111
|
||
|
_nOnBits[6]=127; // 00000000000000000000000001111111
|
||
|
_nOnBits[7]=255; // 00000000000000000000000011111111
|
||
|
_nOnBits[8]=511; // 00000000000000000000000111111111
|
||
|
_nOnBits[9]=023; // 00000000000000000000001111111111
|
||
|
_nOnBits[10]=2047; // 00000000000000000000011111111111
|
||
|
_nOnBits[11]=4095; // 00000000000000000000111111111111
|
||
|
_nOnBits[12]=8191; // 00000000000000000001111111111111
|
||
|
_nOnBits[13]=16383; // 00000000000000000011111111111111
|
||
|
_nOnBits[14]=32767; // 00000000000000000111111111111111
|
||
|
_nOnBits[15]=65535; // 00000000000000001111111111111111
|
||
|
_nOnBits[16]=131071; // 00000000000000011111111111111111
|
||
|
_nOnBits[17]=262143; // 00000000000000111111111111111111
|
||
|
_nOnBits[18]=524287; // 00000000000001111111111111111111
|
||
|
_nOnBits[19]=1048575; // 00000000000011111111111111111111
|
||
|
_nOnBits[20]=2097151; // 00000000000111111111111111111111
|
||
|
_nOnBits[21]=4194303; // 00000000001111111111111111111111
|
||
|
_nOnBits[22]=8388607; // 00000000011111111111111111111111
|
||
|
_nOnBits[23]=16777215; // 00000000111111111111111111111111
|
||
|
_nOnBits[24]=33554431; // 00000001111111111111111111111111
|
||
|
_nOnBits[25]=67108863; // 00000011111111111111111111111111
|
||
|
_nOnBits[26]=134217727; // 00000111111111111111111111111111
|
||
|
_nOnBits[27]=268435455; // 00001111111111111111111111111111
|
||
|
_nOnBits[28]=536870911; // 00011111111111111111111111111111
|
||
|
_nOnBits[29]=1073741823; // 00111111111111111111111111111111
|
||
|
_nOnBits[30]= 2147483647; // 01111111111111111111111111111111
|
||
|
|
||
|
// Could have done this with a loop calculating each value, but simply
|
||
|
// assigning the values is quicker - POWERS OF 2
|
||
|
_n2Power[0]=1; // 00000000000000000000000000000001
|
||
|
_n2Power[1]=2; // 00000000000000000000000000000010
|
||
|
_n2Power[2]=4; // 00000000000000000000000000000100
|
||
|
_n2Power[3]=8; // 00000000000000000000000000001000
|
||
|
_n2Power[4]=16; // 00000000000000000000000000010000
|
||
|
_n2Power[5]=32; // 00000000000000000000000000100000
|
||
|
_n2Power[6]=64; // 00000000000000000000000001000000
|
||
|
_n2Power[7]=128; // 00000000000000000000000010000000
|
||
|
_n2Power[8]=256; // 00000000000000000000000100000000
|
||
|
_n2Power[9]=512; // 00000000000000000000001000000000
|
||
|
_n2Power[10]=1024; // 00000000000000000000010000000000
|
||
|
_n2Power[11]=2048; // 00000000000000000000100000000000
|
||
|
_n2Power[12]=4096; // 00000000000000000001000000000000
|
||
|
_n2Power[13]=8192; // 00000000000000000010000000000000
|
||
|
_n2Power[14]=16384; // 00000000000000000100000000000000
|
||
|
_n2Power[15]=32768; // 00000000000000001000000000000000
|
||
|
_n2Power[16]=65536; // 00000000000000010000000000000000
|
||
|
_n2Power[17]=131072; // 00000000000000100000000000000000
|
||
|
_n2Power[18]=262144; // 00000000000001000000000000000000
|
||
|
_n2Power[19]=524288; // 00000000000010000000000000000000
|
||
|
_n2Power[20]=1048576; // 00000000000100000000000000000000
|
||
|
_n2Power[21]=2097152; // 00000000001000000000000000000000
|
||
|
_n2Power[22]=4194304; // 00000000010000000000000000000000
|
||
|
_n2Power[23]=8388608; // 00000000100000000000000000000000
|
||
|
_n2Power[24]=16777216; // 00000001000000000000000000000000
|
||
|
_n2Power[25]=33554432; // 00000010000000000000000000000000
|
||
|
_n2Power[26]=67108864; // 00000100000000000000000000000000
|
||
|
_n2Power[27]=134217728; // 00001000000000000000000000000000
|
||
|
_n2Power[28]=268435456; // 00010000000000000000000000000000
|
||
|
_n2Power[29]=536870912; // 00100000000000000000000000000000
|
||
|
_n2Power[30]=1073741824; // 01000000000000000000000000000000
|
||
|
}
|
||
|
private int LShift(int nValue, int nShiftBits)
|
||
|
{
|
||
|
return (nValue<<nShiftBits);
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// RShift (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int RShift(int lValue, int iShiftBits)
|
||
|
{
|
||
|
int nRShift=0;
|
||
|
if(iShiftBits==0)
|
||
|
{
|
||
|
nRShift=lValue;
|
||
|
}
|
||
|
else if(iShiftBits==31)
|
||
|
{
|
||
|
if((lValue & -2147483648)!=0)
|
||
|
{nRShift=1;}
|
||
|
else
|
||
|
{nRShift=0;}
|
||
|
}
|
||
|
else if(iShiftBits<0 || iShiftBits>31)
|
||
|
{
|
||
|
nRShift=-1;
|
||
|
}
|
||
|
nRShift=((lValue & 2147483646)/_n2Power[iShiftBits]);
|
||
|
if((lValue & -2147483648)!=0)
|
||
|
{
|
||
|
nRShift=(nRShift | (1073741824/_n2Power[iShiftBits-1]));
|
||
|
}
|
||
|
return nRShift;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// LShiftByte (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte LShiftByte(byte bytValue, byte bytShiftBits)
|
||
|
{
|
||
|
byte nLShiftByte=0;
|
||
|
if(bytShiftBits==0)
|
||
|
{
|
||
|
nLShiftByte=bytValue;
|
||
|
}
|
||
|
else if(bytShiftBits==7)
|
||
|
{
|
||
|
if((bytValue & 1)!=0)
|
||
|
{nLShiftByte = 0x80;}
|
||
|
else
|
||
|
{nLShiftByte=0;}
|
||
|
}
|
||
|
else if(bytShiftBits<0 || bytShiftBits>7)
|
||
|
{
|
||
|
nLShiftByte=0;
|
||
|
}
|
||
|
nLShiftByte=(byte)((bytValue & _bytOnBits[7-bytShiftBits])*_byt2Power[bytShiftBits]);
|
||
|
|
||
|
return nLShiftByte;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// RShiftByte (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte RShiftByte(byte bytValue, byte bytShiftBits)
|
||
|
{
|
||
|
byte nRShiftByte=0;
|
||
|
if(bytShiftBits==0)
|
||
|
{
|
||
|
nRShiftByte=bytValue;
|
||
|
}
|
||
|
else if(bytShiftBits==7)
|
||
|
{
|
||
|
if((bytValue & 0x80)!=0)
|
||
|
{nRShiftByte=1;}
|
||
|
else
|
||
|
{nRShiftByte=0;}
|
||
|
}
|
||
|
else if(bytShiftBits<0 || bytShiftBits>7)
|
||
|
{
|
||
|
nRShiftByte=0;
|
||
|
}
|
||
|
nRShiftByte=(byte)(bytValue/_byt2Power[bytShiftBits]);
|
||
|
|
||
|
return nRShiftByte;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// RotateLeft (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int RotateLeft(int lValue, int iShiftBits)
|
||
|
{
|
||
|
return (LShift(lValue, iShiftBits)|RShift(lValue, (int)(32-iShiftBits)));
|
||
|
}
|
||
|
|
||
|
////*******************************************************************************
|
||
|
//// RotateLeftByte (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte RotateLeftByte(byte bytValue, byte bytShiftBits)
|
||
|
{
|
||
|
return (byte)(LShiftByte(bytValue, bytShiftBits) | RShiftByte(bytValue, (byte)(8-bytShiftBits)));
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// Pack (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int Pack(byte[] b)
|
||
|
{
|
||
|
int nTemp=0, nPack=0;
|
||
|
for(int nCount=0; nCount<=3; nCount++)
|
||
|
{
|
||
|
nTemp=b[nCount];
|
||
|
nPack=nPack | LShift(nTemp, (int)(nCount*8));
|
||
|
}
|
||
|
return nPack;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// PackFrom (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int PackFrom(byte[] b, int k)
|
||
|
{
|
||
|
int nPackFrom=0, nTemp=0;
|
||
|
for(int nCount=0; nCount<=3; nCount++)
|
||
|
{
|
||
|
nTemp=b[nCount+k];
|
||
|
nPackFrom=nPackFrom | LShift(nTemp, (int)(nCount*8));
|
||
|
}
|
||
|
return nPackFrom;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// Unpack (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void Unpack(int a, ref byte[] b)
|
||
|
{
|
||
|
b[0]=(byte)(a & _nOnBits[7]);
|
||
|
b[1]=(byte)(RShift(a, 8) & _nOnBits[7]);
|
||
|
b[2]=(byte)(RShift(a, 16) & _nOnBits[7]);
|
||
|
b[3]=(byte)(RShift(a, 24) & _nOnBits[7]);
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// UnpackFrom (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void UnpackFrom(int a, ref byte[] b, int k)
|
||
|
{
|
||
|
b[0+k]=(byte)(a & _nOnBits[7]);
|
||
|
b[1+k]=(byte)(RShift(a, 8) & _nOnBits[7]);
|
||
|
b[2+k]=(byte)(RShift(a, 16) & _nOnBits[7]);
|
||
|
b[3+k]=(byte)(RShift(a, 24) & _nOnBits[7]);
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// xtime (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte xTime(byte a)
|
||
|
{
|
||
|
byte b=0;
|
||
|
if((a & 0x80)!=0)
|
||
|
{b=0x1B;}
|
||
|
else
|
||
|
{b=0;}
|
||
|
a=LShiftByte(a, 1);
|
||
|
a=(byte)(a^b);
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// bmul (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte bMul(byte x, byte Y)
|
||
|
{
|
||
|
byte nbmul=0;
|
||
|
if(x!=0 && Y!=0)
|
||
|
{
|
||
|
nbmul=(byte)(_nPTab[(_nLTab[x]+ _nLTab[Y]) % 255]);
|
||
|
}
|
||
|
return nbmul;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// SubByte (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int SubByte(int a)
|
||
|
{
|
||
|
byte[] b=new byte[4];
|
||
|
Unpack(a, ref b);
|
||
|
b[0]=_nFbSub[b[0]];
|
||
|
b[1]=_nFbSub[b[1]];
|
||
|
b[2]=_nFbSub[b[2]];
|
||
|
b[3]=_nFbSub[b[3]];
|
||
|
|
||
|
return (Pack(b));
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// product (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int Product(int x, int y)
|
||
|
{
|
||
|
byte[] xb=new Byte[4];
|
||
|
byte[] yb=new Byte[4];
|
||
|
|
||
|
Unpack(x, ref xb);
|
||
|
Unpack(y, ref yb);
|
||
|
|
||
|
return (bMul(xb[0], yb[0]) ^ bMul(xb[1], yb[1]) ^ bMul(xb[2], yb[2]) ^ bMul(xb[3], yb[3]));
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// InvMixCol (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private int InvMixCol(int x)
|
||
|
{
|
||
|
int m=0;
|
||
|
byte[] b=new byte[4];
|
||
|
|
||
|
m=Pack(_nInCo);
|
||
|
b[3]=(byte)Product(m, x);
|
||
|
m=RotateLeft(m, 24);
|
||
|
b[2]=(byte)Product(m, x);
|
||
|
m=RotateLeft(m, 24);
|
||
|
b[1]=(byte)Product(m, x);
|
||
|
m=RotateLeft(m, 24);
|
||
|
b[0]=(byte)Product(m, x);
|
||
|
|
||
|
return Pack(b);
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// ByteSub (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private byte ByteSub(byte x)
|
||
|
{
|
||
|
byte Y=0;
|
||
|
Y=_nPTab[255-_nLTab[x]];
|
||
|
x=Y;
|
||
|
x=RotateLeftByte(x, 1);
|
||
|
Y=(byte)(Y ^ x);
|
||
|
x=RotateLeftByte(x, 1);
|
||
|
Y=(byte)(Y ^ x);
|
||
|
x=RotateLeftByte(x, 1);
|
||
|
Y=(byte)(Y ^ x);
|
||
|
x=RotateLeftByte(x, 1);
|
||
|
Y=(byte)(Y ^ x);
|
||
|
Y=(byte)(Y ^ 0x63);
|
||
|
|
||
|
return Y;
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// gentables (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void GenTables()
|
||
|
{
|
||
|
int i=0;
|
||
|
byte Y=0, ib=0;
|
||
|
byte[] b=new byte[4];
|
||
|
|
||
|
_nLTab[0]=0;
|
||
|
_nPTab[0]=1;
|
||
|
_nLTab[1]=0;
|
||
|
_nPTab[1]=3;
|
||
|
_nLTab[3]=1;
|
||
|
|
||
|
for(i=2; i<=255; i++)
|
||
|
{
|
||
|
_nPTab[i]= (byte)(_nPTab[i-1] ^ xTime(_nPTab[i-1]));
|
||
|
_nLTab[_nPTab[i]]=(byte)i;
|
||
|
}
|
||
|
|
||
|
_nFbSub[0]=0x63;
|
||
|
_nRbSub[0x63]=0;
|
||
|
|
||
|
for(i=1; i<=255; i++)
|
||
|
{
|
||
|
ib=(byte)i;
|
||
|
Y=ByteSub(ib);
|
||
|
_nFbSub[i]=Y;
|
||
|
_nRbSub[Y]=(byte)i;
|
||
|
}
|
||
|
|
||
|
Y=1;
|
||
|
for(i=0; i<=29; i++)
|
||
|
{
|
||
|
_nRCo[i]=Y;
|
||
|
Y=xTime(Y);
|
||
|
}
|
||
|
for(i=0; i<=255; i++)
|
||
|
{
|
||
|
Y=_nFbSub[i];
|
||
|
b[3]=(byte)(Y ^ xTime(Y));
|
||
|
b[2]=Y;
|
||
|
b[1]=Y;
|
||
|
b[0]=xTime(Y);
|
||
|
_nFTable[i]=Pack(b);
|
||
|
|
||
|
Y=_nRbSub[i];
|
||
|
b[3]=bMul(_nInCo[0], Y);
|
||
|
b[2]=bMul(_nInCo[1], Y);
|
||
|
b[1]=bMul(_nInCo[2], Y);
|
||
|
b[0]=bMul(_nInCo[3], Y);
|
||
|
_nRTable[i]=Pack(b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// gkey (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void GenKey(int nb, int nk, byte[] KEY)
|
||
|
{
|
||
|
int i=0, j=0, k=0, m=0, N=0, C1=0, C2=0, C3=0;
|
||
|
int[] CipherKey=new int[8];
|
||
|
|
||
|
_nNb = nb;
|
||
|
_nNk = nk;
|
||
|
|
||
|
if(_nNb>=_nNk)
|
||
|
{_nNr=6+_nNb;}
|
||
|
else
|
||
|
{_nNr=6+_nNk;}
|
||
|
|
||
|
C1 = 1;
|
||
|
if(_nNb<8)
|
||
|
{C2=2; C3=3;}
|
||
|
else
|
||
|
{C2=3; C3=4;}
|
||
|
|
||
|
for(j=0; j<=(nb-1); j++)
|
||
|
{
|
||
|
m=j*3;
|
||
|
_nFi[m] =(byte)((j +C1) % nb);
|
||
|
_nFi[m+1]=(byte)((j +C2) % nb);
|
||
|
_nFi[m+2]=(byte)((j +C3) % nb);
|
||
|
_nRi[m] =(byte)((nb+j-C1) % nb);
|
||
|
_nRi[m+1]=(byte)((nb+j-C2) % nb);
|
||
|
_nRi[m+2]=(byte)((nb+j-C3) % nb);
|
||
|
}
|
||
|
|
||
|
N=_nNb*(_nNr+1);
|
||
|
|
||
|
for(i=0; i<=(_nNk-1); i++)
|
||
|
{
|
||
|
j=i*4;
|
||
|
CipherKey[i]= PackFrom(KEY, j);
|
||
|
}
|
||
|
|
||
|
for(i=0; i<=(_nNk-1); i++)
|
||
|
{
|
||
|
_nFKey[i]=CipherKey[i];
|
||
|
}
|
||
|
|
||
|
j=_nNk;
|
||
|
k=0;
|
||
|
while(j<N)
|
||
|
{
|
||
|
_nFKey[j]=_nFKey[j-_nNk] ^ SubByte(RotateLeft(_nFKey[j-1], 24)) ^ _nRCo[k];
|
||
|
if(_nNk<=6)
|
||
|
{
|
||
|
i=1;
|
||
|
while((i<_nNk) && ((i+j)< N))
|
||
|
{
|
||
|
_nFKey[i+j]=_nFKey[i+j-_nNk] ^ _nFKey[i+j-1];
|
||
|
i=i+1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Problem fixed here
|
||
|
i=1;
|
||
|
while((i<4) && (i+j)<N)
|
||
|
{
|
||
|
_nFKey[i+j]=_nFKey[i+j-_nNk] ^ _nFKey[i+j-1];
|
||
|
i=i+1;
|
||
|
}
|
||
|
if((j+4)<N)
|
||
|
{
|
||
|
_nFKey[j+4]=_nFKey[j+4-_nNk] ^ SubByte(_nFKey[j+3]);
|
||
|
}
|
||
|
|
||
|
i = 5;
|
||
|
while((i<_nNk) && (i+j)<N)
|
||
|
{
|
||
|
_nFKey[i+j]=_nFKey[i+j-_nNk] ^ _nFKey[i+j-1];
|
||
|
i=i+1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
j=j+_nNk;
|
||
|
k=k+1;
|
||
|
}
|
||
|
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
_nRKey[j+N-nb]=_nFKey[j];
|
||
|
}
|
||
|
|
||
|
i = _nNb;
|
||
|
while(i<(N-_nNb))
|
||
|
{
|
||
|
k=N-_nNb-i;
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
_nRKey[k+j]=InvMixCol(_nFKey[i+j]);
|
||
|
}
|
||
|
i=i+_nNb;
|
||
|
}
|
||
|
|
||
|
j=N-_nNb;
|
||
|
while(j<N)
|
||
|
{
|
||
|
_nRKey[j-N+_nNb]=_nFKey[j];
|
||
|
j=j+1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// encrypt (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void Encrypt(byte[] buff)
|
||
|
{
|
||
|
int i=0, j=0, k=0, m=0;
|
||
|
int[] a=new int[8];
|
||
|
int[] b=new int[8];
|
||
|
int[] x, Y, t;
|
||
|
|
||
|
for(i=0; i<=(_nNb-1); i++)
|
||
|
{
|
||
|
j=i*4;
|
||
|
a[i]=PackFrom(buff, j);
|
||
|
a[i]=a[i] ^ _nFKey[i];
|
||
|
}
|
||
|
|
||
|
k=_nNb;
|
||
|
x=a;
|
||
|
Y=b;
|
||
|
|
||
|
for(i=1; i<=(_nNr-1); i++)
|
||
|
{
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
m=j*3;
|
||
|
Y[j]=_nFKey[k] ^ _nFTable[x[j] & _nOnBits[7]]
|
||
|
^ RotateLeft(_nFTable[RShift(x[_nFi[m]], 8) & _nOnBits[7]], 8)
|
||
|
^ RotateLeft(_nFTable[RShift(x[_nFi[m+1]], 16) & _nOnBits[7]], 16)
|
||
|
^ RotateLeft(_nFTable[RShift(x[_nFi[m+2]], 24) & _nOnBits[7]], 24);
|
||
|
k=k+1;
|
||
|
}
|
||
|
t=x;
|
||
|
x=Y;
|
||
|
Y=t;
|
||
|
}
|
||
|
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
m=j*3;
|
||
|
Y[j]=_nFKey[k] ^ _nFbSub[x[j] & _nOnBits[7]]
|
||
|
^ RotateLeft(_nFbSub[RShift(x[_nFi[m]], 8) & _nOnBits[7]], 8)
|
||
|
^ RotateLeft(_nFbSub[RShift(x[_nFi[m+1]], 16) & _nOnBits[7]], 16)
|
||
|
^ RotateLeft(_nFbSub[RShift(x[_nFi[m+2]], 24) & _nOnBits[7]], 24);
|
||
|
k = k + 1;
|
||
|
}
|
||
|
|
||
|
for(i=0; i<=(_nNb-1); i++)
|
||
|
{
|
||
|
j=i*4;
|
||
|
UnpackFrom(Y[i], ref buff, j);
|
||
|
x[i]=0;
|
||
|
Y[i]=0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// decrypt (SUB)
|
||
|
//*******************************************************************************
|
||
|
private void Decrypt(byte[] buff)
|
||
|
{
|
||
|
int i=0, j=0, k=0, m=0;
|
||
|
int [] a=new int[8];
|
||
|
int [] b=new int[8];
|
||
|
int [] x, Y, t;
|
||
|
|
||
|
for(i=0; i<=(_nNb-1); i++)
|
||
|
{
|
||
|
j=i*4;
|
||
|
a[i]=PackFrom(buff, j);
|
||
|
a[i]=a[i] ^ _nRKey[i];
|
||
|
}
|
||
|
|
||
|
k=_nNb;
|
||
|
x=a;
|
||
|
Y=b;
|
||
|
|
||
|
for(i=1; i<=(_nNr-1); i++)
|
||
|
{
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
m=j*3;
|
||
|
Y[j]=_nRKey[k] ^ _nRTable[x[j] & _nOnBits[7]] ^
|
||
|
RotateLeft(_nRTable[RShift(x[_nRi[m]], 8) & _nOnBits[7]], 8) ^
|
||
|
RotateLeft(_nRTable[RShift(x[_nRi[m+1]], 16) & _nOnBits[7]], 16) ^
|
||
|
RotateLeft(_nRTable[RShift(x[_nRi[m+2]], 24) & _nOnBits[7]], 24);
|
||
|
k = k + 1;
|
||
|
}
|
||
|
t = x;
|
||
|
x = Y;
|
||
|
Y = t;
|
||
|
}
|
||
|
|
||
|
for(j=0; j<=(_nNb-1); j++)
|
||
|
{
|
||
|
m=j*3;
|
||
|
Y[j]=_nRKey[k] ^ _nRbSub[x[j] & _nOnBits[7]]
|
||
|
^ RotateLeft(_nRbSub[RShift(x[_nRi[m]], 8) & _nOnBits[7]], 8)
|
||
|
^ RotateLeft(_nRbSub[RShift(x[_nRi[m+1]], 16) & _nOnBits[7]], 16)
|
||
|
^ RotateLeft(_nRbSub[RShift(x[_nRi[m+2]], 24) & _nOnBits[7]], 24);
|
||
|
k = k + 1;
|
||
|
}
|
||
|
|
||
|
for(i=0; i<=(_nNb-1); i++)
|
||
|
{
|
||
|
j=i*4;
|
||
|
UnpackFrom(Y[i], ref buff, j);
|
||
|
x[i]=0;
|
||
|
Y[i]=0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// IsInitialized (FUNCTION)
|
||
|
//*******************************************************************************
|
||
|
private bool IsInitialized(byte [] bArray)
|
||
|
{
|
||
|
return (bArray.Length>0);
|
||
|
}
|
||
|
|
||
|
//*******************************************************************************
|
||
|
// EncryptData (FUNCTION)
|
||
|
// Takes the message, whatever the size, and password in one call and does
|
||
|
// everything for you to return an encoded/encrypted message
|
||
|
//*******************************************************************************
|
||
|
public byte[] EncryptData(byte[] bytMessage, byte [] bytPassword)
|
||
|
{
|
||
|
byte[] bytIn, bytOut;
|
||
|
byte[] bytLen=new byte[4];
|
||
|
byte[] bytKey=new byte[32];
|
||
|
byte[] bytTemp=new byte[32];
|
||
|
int lCount=0, lLength=0, lEncodedLength=0;
|
||
|
|
||
|
if(!IsInitialized(bytMessage))
|
||
|
{
|
||
|
return bytMessage;
|
||
|
}
|
||
|
if(!IsInitialized(bytPassword))
|
||
|
{
|
||
|
return bytPassword;
|
||
|
}
|
||
|
|
||
|
// Use first 32 bytes of the password for the key
|
||
|
for(lCount=0; lCount<bytPassword.Length; lCount++)
|
||
|
{
|
||
|
bytKey[lCount]=bytPassword[lCount];
|
||
|
if(lCount==31)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Prepare the key; assume 256 bit block and key size
|
||
|
GenTables();
|
||
|
GenKey(8, 8, bytKey);
|
||
|
|
||
|
// We are going to put the message size on the front of the message
|
||
|
// in the first 4 bytes. If the length is more than a max int we are
|
||
|
// in trouble
|
||
|
lLength=bytMessage.Length;
|
||
|
lEncodedLength=lLength+4;
|
||
|
|
||
|
// The encoded length includes the 4 bytes stuffed on the front
|
||
|
// and is padded out to be modulus 32
|
||
|
if((lEncodedLength % 32)!= 0)
|
||
|
{
|
||
|
lEncodedLength=lEncodedLength+32-(lEncodedLength % 32);
|
||
|
}
|
||
|
|
||
|
bytIn=new byte[lEncodedLength];
|
||
|
bytOut=new byte[lEncodedLength];
|
||
|
IntToByte(lLength, ref bytIn);
|
||
|
|
||
|
//bytMessage.CopyTo(bytIn, 4);
|
||
|
Copy(ref bytIn, 4, bytMessage, 0, lLength);
|
||
|
|
||
|
for(lCount=0; lCount<=(lEncodedLength-1); lCount=lCount+32)
|
||
|
{
|
||
|
Copy(ref bytTemp, 0, bytIn, lCount,32);
|
||
|
//Encrypt Block by Block
|
||
|
Encrypt(bytTemp);
|
||
|
Copy(ref bytOut, lCount, bytTemp, 0, 32);
|
||
|
}
|
||
|
|
||
|
return bytOut;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Decrypt Function /Oposite of Encrypt
|
||
|
/// </summary>
|
||
|
/// <param name="bytIn"></param>
|
||
|
/// <param name="bytPassword"></param>
|
||
|
/// <returns></returns>
|
||
|
public byte[] DecryptData(byte[] bytIn, byte[] bytPassword)
|
||
|
{
|
||
|
byte[] bytMessage, bytOut;
|
||
|
byte[] bytLen=new byte[4];
|
||
|
byte[] bytKey=new byte[32];
|
||
|
byte[] bytTemp=new byte[32];
|
||
|
int lCount=0, lLength=0, lEncodedLength=0;
|
||
|
|
||
|
if(!IsInitialized(bytIn))
|
||
|
{
|
||
|
return bytIn;
|
||
|
}
|
||
|
if(!IsInitialized(bytPassword))
|
||
|
{
|
||
|
return bytPassword;
|
||
|
}
|
||
|
|
||
|
lEncodedLength=bytIn.Length;
|
||
|
|
||
|
if((lEncodedLength % 32) !=0)
|
||
|
{
|
||
|
return bytIn;
|
||
|
}
|
||
|
|
||
|
// Use first 32 bytes of the password for the key
|
||
|
for(lCount=0; lCount<bytPassword.Length; lCount++)
|
||
|
{
|
||
|
bytKey[lCount]=bytPassword[lCount];
|
||
|
if(lCount==31)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Prepare the key; assume 256 bit block and key size
|
||
|
GenTables();
|
||
|
GenKey(8, 8, bytKey);
|
||
|
|
||
|
// The output array needs to be the same size as the input array
|
||
|
bytOut=new byte[lEncodedLength];
|
||
|
|
||
|
for(lCount=0; lCount<lEncodedLength; lCount=lCount+32)
|
||
|
{
|
||
|
Copy(ref bytTemp, 0, bytIn, lCount, 32);
|
||
|
//Decrypt Block by Block
|
||
|
Decrypt(bytTemp);
|
||
|
Copy(ref bytOut, lCount, bytTemp, 0, 32);
|
||
|
}
|
||
|
|
||
|
lLength=ByteToInt(bytOut);
|
||
|
|
||
|
// Make sure the length is consistent with our data
|
||
|
if(lLength>lEncodedLength-4)
|
||
|
{
|
||
|
return bytIn;
|
||
|
}
|
||
|
|
||
|
// Prepare the output message byte array
|
||
|
bytMessage=new byte[lLength];
|
||
|
Copy(ref bytMessage, 0, bytOut, 4, lLength);
|
||
|
|
||
|
return bytMessage;
|
||
|
}
|
||
|
|
||
|
|
||
|
//Sum Function to help CopyMemory, Hex, Int, Byte Conversion
|
||
|
private void Copy(ref byte[] Destination, int DestIndex, byte[] Source, int SrcIndex, int Length)
|
||
|
{
|
||
|
for(int j=0; j<Length; j++)
|
||
|
{
|
||
|
Destination[DestIndex+j]=Source[j+SrcIndex];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void IntToByte(int nNumber, ref byte[] bytOut)
|
||
|
{
|
||
|
string sText=Convert.ToString(nNumber,16);
|
||
|
|
||
|
if(sText.Length<8)
|
||
|
{
|
||
|
sText=new String('0',(8-sText.Length))+sText;
|
||
|
}
|
||
|
char[] cChars=sText.ToCharArray();
|
||
|
byte[] nByteOut=new byte[4];
|
||
|
|
||
|
for(int nCount=0; nCount<cChars.Length; nCount=nCount+2)
|
||
|
{
|
||
|
byte b=(byte)(Convert.ToByte(cChars[nCount].ToString(), 16)<<4);
|
||
|
b=(byte)(b | Convert.ToByte(cChars[nCount+1].ToString(), 16) & 0x0F);
|
||
|
nByteOut[nCount/2]=b;
|
||
|
}
|
||
|
bytOut[3]=nByteOut[0];
|
||
|
bytOut[2]=nByteOut[1];
|
||
|
bytOut[1]=nByteOut[2];
|
||
|
bytOut[0]=nByteOut[3];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
private int ByteToInt(byte[] bytIn)
|
||
|
{
|
||
|
int nNumber=0;
|
||
|
nNumber=bytIn[3];
|
||
|
nNumber=(nNumber<<8) | bytIn[2];
|
||
|
nNumber=(nNumber<<8) | bytIn[1];
|
||
|
nNumber=(nNumber<<8) | bytIn[0];
|
||
|
return nNumber;
|
||
|
}
|
||
|
|
||
|
public byte[] StringToByte(string sText)
|
||
|
{
|
||
|
int nCount=0;
|
||
|
char[] cChars=new char[sText.Length];
|
||
|
byte[] nByteOut=new byte[2*cChars.Length];
|
||
|
cChars=sText.ToCharArray();
|
||
|
|
||
|
for(nCount=0; nCount<nByteOut.Length; nCount=nCount+2)
|
||
|
{
|
||
|
nByteOut[nCount]=(byte)cChars[nCount/2];
|
||
|
}
|
||
|
return nByteOut;
|
||
|
}
|
||
|
|
||
|
public string ByteToHexString(byte[] nBytes)
|
||
|
{
|
||
|
char[] HexDigits ={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||
|
char[] cChrs = new char[nBytes.Length * 2];
|
||
|
|
||
|
for(int i=0; i<nBytes.Length; i++)
|
||
|
{
|
||
|
int b=nBytes[i];
|
||
|
cChrs[i*2]=HexDigits[b >> 4];
|
||
|
cChrs[i*2+1]=HexDigits[b & 0xF];
|
||
|
}
|
||
|
return new string(cChrs);
|
||
|
}
|
||
|
|
||
|
public string ByteToString(byte[] nBytes)
|
||
|
{
|
||
|
char[] cChrs = new char[nBytes.Length/2];
|
||
|
|
||
|
for(int i=0; i<nBytes.Length; i=i+2)
|
||
|
{
|
||
|
cChrs[i/2]=(char)nBytes[i];
|
||
|
}
|
||
|
return new string(cChrs);
|
||
|
}
|
||
|
public byte[] HexToByte(string sHexData)
|
||
|
{
|
||
|
byte[] nByteOut=new byte[sHexData.Length/2];
|
||
|
char[] cChars=sHexData.ToCharArray();
|
||
|
for(int nCount=0; nCount<cChars.Length; nCount=nCount+2)
|
||
|
{
|
||
|
byte b=(byte)(Convert.ToByte(cChars[nCount].ToString(), 16)<<4);
|
||
|
b=(byte)(b | Convert.ToByte(cChars[nCount+1].ToString(), 16) & 0x0F);
|
||
|
nByteOut[nCount/2]=b;
|
||
|
}
|
||
|
return nByteOut;
|
||
|
}
|
||
|
}
|
||
|
}
|