using System; namespace HRM.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<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(j0); } //******************************************************************************* // 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 /// Decrypt Function /Oposite of Encrypt /// /// /// /// 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; lCountlEncodedLength-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> 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