package com.mtools.core.plugin.security; class CEA { long ExtendKey[][]; int CEA_ROTATE; int CEA_MPI_LONG; public CEA() { CEA_ROTATE = 6; CEA_MPI_LONG = 2; ExtendKey = new long[2 * CEA_ROTATE + 4][2]; } protected void Add(long s1[], long s2[], long res[], int length) { long c = 0L; for(int i = length - 1; i >= 0; i--) { res[i] = s1[i] + s2[i] + c; c = (res[i] & 0xff00000000L) >>> 32; res[i] = res[i] & 0xffffffffL; } } public void ByteToInt(byte source[], int result[], int length) { for(int i = 0; i < length; i++) if(source[i] >= 0) result[i] = source[i]; else result[i] = source[i] + 256; } public void CEADecrypt(byte cipher[], byte plain[]) { long A[] = new long[2]; long B[] = new long[2]; long Temp1[] = new long[2]; long Temp2[] = new long[2]; int Temp[] = new int[16]; ByteToInt(cipher, Temp, 16); A[0] = (long)Temp[0] << 24 | (long)Temp[1] << 16 | (long)Temp[2] << 8 | (long)Temp[3]; A[1] = (long)Temp[4] << 24 | (long)Temp[5] << 16 | (long)Temp[6] << 8 | (long)Temp[7]; B[0] = (long)Temp[8] << 24 | (long)Temp[9] << 16 | (long)Temp[10] << 8 | (long)Temp[11]; B[1] = (long)Temp[12] << 24 | (long)Temp[13] << 16 | (long)Temp[14] << 8 | (long)Temp[15]; Add(A, ExtendKey[0], A, CEA_MPI_LONG); Add(B, ExtendKey[1], B, CEA_MPI_LONG); for(int i = 1; i <= CEA_ROTATE; i++) { Xor(A, B, Temp1, CEA_MPI_LONG); int shift = (int)(B[1] & (long)63); LShift(Temp1, Temp2, shift, CEA_MPI_LONG); Add(Temp2, ExtendKey[2 * i], A, CEA_MPI_LONG); Xor(B, A, Temp1, CEA_MPI_LONG); shift = (int)(A[1] & (long)63); LShift(Temp1, Temp2, shift, CEA_MPI_LONG); Add(Temp2, ExtendKey[2 * i + 1], B, CEA_MPI_LONG); } Xor(A, ExtendKey[2 * CEA_ROTATE + 2], Temp1, CEA_MPI_LONG); Copy(Temp1, A, CEA_MPI_LONG); Xor(B, ExtendKey[2 * CEA_ROTATE + 3], Temp1, CEA_MPI_LONG); Copy(Temp1, B, CEA_MPI_LONG); LShift(A, Temp1, 1, CEA_MPI_LONG); LShift(B, Temp2, 1, CEA_MPI_LONG); long Bit1 = Temp1[1] & (long)1; long Bit2 = Temp2[1] & (long)1; Temp1[1] = Temp1[1] & 0xfffffffeL; Temp1[1] = Temp1[1] | Bit2; Temp2[1] = Temp2[1] & 0xfffffffeL; Temp2[1] = Temp2[1] | Bit1; Bit1 = Temp1[0] & 0x80000000L; Bit2 = (Temp1[0] & 0x40000000L) << 1; Bit1 ^= Bit2; Temp1[0] = Temp1[0] & 0x7fffffffL; Temp1[0] = Temp1[0] | Bit1; Copy(Temp1, A, CEA_MPI_LONG); Copy(Temp2, B, CEA_MPI_LONG); for(int i = CEA_ROTATE; i >= 1; i--) { Sub(B, ExtendKey[2 * i + 1], Temp1, CEA_MPI_LONG); int shift = (int)(A[1] & (long)63); RShift(Temp1, Temp2, shift, CEA_MPI_LONG); Xor(Temp2, A, B, CEA_MPI_LONG); Sub(A, ExtendKey[2 * i], Temp1, CEA_MPI_LONG); shift = (int)(B[1] & (long)63); RShift(Temp1, Temp2, shift, CEA_MPI_LONG); Xor(Temp2, B, A, CEA_MPI_LONG); } Sub(B, ExtendKey[1], Temp1, CEA_MPI_LONG); Temp[8] = (int)(Temp1[0] >>> 24 & (long)255); Temp[9] = (int)(Temp1[0] >>> 16 & (long)255); Temp[10] = (int)(Temp1[0] >>> 8 & (long)255); Temp[11] = (int)(Temp1[0] & (long)255); Temp[12] = (int)(Temp1[1] >>> 24 & (long)255); Temp[13] = (int)(Temp1[1] >>> 16 & (long)255); Temp[14] = (int)(Temp1[1] >>> 8 & (long)255); Temp[15] = (int)(Temp1[1] & (long)255); Sub(A, ExtendKey[0], Temp1, CEA_MPI_LONG); Temp[0] = (int)(Temp1[0] >>> 24 & (long)255); Temp[1] = (int)(Temp1[0] >>> 16 & (long)255); Temp[2] = (int)(Temp1[0] >>> 8 & (long)255); Temp[3] = (int)(Temp1[0] & (long)255); Temp[4] = (int)(Temp1[1] >>> 24 & (long)255); Temp[5] = (int)(Temp1[1] >>> 16 & (long)255); Temp[6] = (int)(Temp1[1] >>> 8 & (long)255); Temp[7] = (int)(Temp1[1] & (long)255); IntToByte(Temp, plain, 16); } public void CEAEncrypt(byte plain[], byte cipher[]) { long A[] = new long[2]; long B[] = new long[2]; long Temp1[] = new long[2]; long Temp2[] = new long[2]; int Temp[] = new int[16]; ByteToInt(plain, Temp, 16); A[0] = (long)Temp[0] << 24 | (long)Temp[1] << 16 | (long)Temp[2] << 8 | (long)Temp[3]; A[1] = (long)Temp[4] << 24 | (long)Temp[5] << 16 | (long)Temp[6] << 8 | (long)Temp[7]; B[0] = (long)Temp[8] << 24 | (long)Temp[9] << 16 | (long)Temp[10] << 8 | (long)Temp[11]; B[1] = (long)Temp[12] << 24 | (long)Temp[13] << 16 | (long)Temp[14] << 8 | (long)Temp[15]; Add(A, ExtendKey[0], A, CEA_MPI_LONG); Add(B, ExtendKey[1], B, CEA_MPI_LONG); for(int i = 1; i <= CEA_ROTATE; i++) { Xor(A, B, Temp1, CEA_MPI_LONG); int shift = (int)(B[1] & (long)63); LShift(Temp1, Temp2, shift, CEA_MPI_LONG); Add(Temp2, ExtendKey[2 * i], A, CEA_MPI_LONG); Xor(B, A, Temp1, CEA_MPI_LONG); shift = (int)(A[1] & (long)63); LShift(Temp1, Temp2, shift, CEA_MPI_LONG); Add(Temp2, ExtendKey[2 * i + 1], B, CEA_MPI_LONG); } LShift(A, Temp1, 63, CEA_MPI_LONG); LShift(B, Temp2, 63, CEA_MPI_LONG); long Bit1 = Temp1[0] & 0x80000000L; long Bit2 = Temp2[0] & 0x80000000L; Temp1[0] = Temp1[0] & 0x7fffffffL; Temp1[0] = Temp1[0] | Bit2; Temp2[0] = Temp2[0] & 0x7fffffffL; Temp2[0] = Temp2[0] | Bit1; Bit1 = Temp1[0] & 0x40000000L; Bit2 = (Temp1[0] & 0x20000000L) << 1; Bit1 ^= Bit2; Temp1[0] = Temp1[0] & 0xbfffffffL; Temp1[0] = Temp1[0] | Bit1; Xor(Temp1, ExtendKey[2 * CEA_ROTATE + 2], A, CEA_MPI_LONG); Xor(Temp2, ExtendKey[2 * CEA_ROTATE + 3], B, CEA_MPI_LONG); for(int i = CEA_ROTATE; i >= 1; i--) { Sub(B, ExtendKey[2 * i + 1], Temp1, CEA_MPI_LONG); int shift = (int)(A[1] & (long)63); RShift(Temp1, Temp2, shift, CEA_MPI_LONG); Xor(Temp2, A, B, CEA_MPI_LONG); Sub(A, ExtendKey[2 * i], Temp1, CEA_MPI_LONG); shift = (int)(B[1] & (long)63); RShift(Temp1, Temp2, shift, CEA_MPI_LONG); Xor(Temp2, B, A, CEA_MPI_LONG); } Sub(B, ExtendKey[1], Temp1, CEA_MPI_LONG); Temp[8] = (int)(Temp1[0] >>> 24 & (long)255); Temp[9] = (int)(Temp1[0] >>> 16 & (long)255); Temp[10] = (int)(Temp1[0] >>> 8 & (long)255); Temp[11] = (int)(Temp1[0] & (long)255); Temp[12] = (int)(Temp1[1] >>> 24 & (long)255); Temp[13] = (int)(Temp1[1] >>> 16 & (long)255); Temp[14] = (int)(Temp1[1] >>> 8 & (long)255); Temp[15] = (int)(Temp1[1] & (long)255); Sub(A, ExtendKey[0], Temp1, CEA_MPI_LONG); Temp[0] = (int)(Temp1[0] >>> 24 & (long)255); Temp[1] = (int)(Temp1[0] >>> 16 & (long)255); Temp[2] = (int)(Temp1[0] >>> 8 & (long)255); Temp[3] = (int)(Temp1[0] & (long)255); Temp[4] = (int)(Temp1[1] >>> 24 & (long)255); Temp[5] = (int)(Temp1[1] >>> 16 & (long)255); Temp[6] = (int)(Temp1[1] >>> 8 & (long)255); Temp[7] = (int)(Temp1[1] & (long)255); IntToByte(Temp, cipher, 16); } public void Copy(long source[], long result[], int length) { for(int i = 0; i < length; i++) result[i] = source[i]; } public int Decrypt(byte in_data[], byte out_data[], int in_len, byte key[], int key_len) { if(in_len < 16) return -1; byte in_temp[] = new byte[16]; byte out_temp[] = new byte[16]; init(key, key_len); int remainder = in_len % 16; int n = in_len / 16; if(remainder == 0) { for(int i = 0; i < n; i++) { int k = i * 16; for(int j = 0; j < 16; j++) { in_temp[j] = in_data[k]; k++; } CEADecrypt(in_temp, out_temp); k = i * 16; for(int j = 0; j < 16; j++) { out_data[k] = out_temp[j]; k++; } } } else { int k; for(int i = 0; i < n - 1; i++) { k = i * 16; for(int j = 0; j < 16; j++) { in_temp[j] = in_data[k]; k++; } CEADecrypt(in_temp, out_temp); k = i * 16; for(int j = 0; j < 16; j++) { out_data[k] = out_temp[j]; k++; } } k = (n - 1) * 16 + remainder; for(int j = 0; j < 16; j++) { in_temp[j] = in_data[k]; k++; } CEADecrypt(in_temp, out_temp); k = n * 16; for(int j = 0; j < remainder; j++) { out_data[k] = out_temp[j]; k++; } k = (n - 1) * 16; for(int j = 0; j < remainder; j++) { in_temp[j] = in_data[k]; k++; } for(int j = remainder; j < 16; j++) in_temp[j] = out_temp[j]; CEADecrypt(in_temp, out_temp); k = (n - 1) * 16; for(int j = 0; j < 16; j++) { out_data[k] = out_temp[j]; k++; } } return 0; } public int Encrypt(byte in_data[], byte out_data[], int in_len, byte key[], int key_len) { if(in_len < 16) return -1; byte in_temp[] = new byte[16]; byte out_temp[] = new byte[16]; init(key, key_len); int remainder = in_len % 16; int n = in_len / 16; for(int i = 0; i < n; i++) { int k = i * 16; for(int j = 0; j < 16; j++) { in_temp[j] = in_data[k]; k++; } CEAEncrypt(in_temp, out_temp); k = i * 16; for(int j = 0; j < 16; j++) { out_data[k] = out_temp[j]; k++; } } if(remainder != 0) { int k = n * 16; for(int j = 0; j < remainder; j++) { in_temp[j] = in_data[k]; k++; } k = (n - 1) * 16 + remainder; for(int j = remainder; j < 16; j++) { in_temp[j] = out_data[k]; k++; } CEAEncrypt(in_temp, out_temp); k = (n - 1) * 16 + remainder; for(int j = 0; j < 16; j++) { out_data[k] = out_temp[j]; k++; } } return 0; } public void init(byte key[], int keylength) { long SrcKey[][] = new long[2 * CEA_ROTATE + 4][CEA_MPI_LONG]; long A[] = new long[CEA_MPI_LONG]; long B[] = new long[CEA_MPI_LONG]; long Temp1[] = new long[CEA_MPI_LONG]; long Temp2[] = new long[CEA_MPI_LONG]; for(int i = 0; i < CEA_MPI_LONG; i++) { A[i] = 0L; B[i] = 0L; Temp1[i] = 0L; Temp2[i] = 0L; } int keycount = (keylength + (CEA_MPI_LONG * 4 - 1)) / (CEA_MPI_LONG * 4); int temp[] = new int[keycount * (CEA_MPI_LONG * 4)]; for(int i = 0; i < keycount * (CEA_MPI_LONG * 4); i++) temp[i] = 0; ByteToInt(key, temp, keylength); int n = 0; for(int i = 0; i < keycount; i++) { for(int j = 0; j < CEA_MPI_LONG; j++) { SrcKey[i][j] = 0L; for(int k = 0; k < 4; k++) { SrcKey[i][j] = SrcKey[i][j] << 8 | (long)(temp[n] & 0xff); n++; } } } ExtendKey[0][0] = 0xb7e15163L; ExtendKey[0][1] = 0x9e3779b9L; for(int i = 1; i < 2 * CEA_ROTATE + 4; i++) LShift(ExtendKey[i - 1], ExtendKey[i], i, CEA_MPI_LONG); for(int i = 0; i < 2 * CEA_ROTATE + 4; i++) { Add(A, B, Temp1, CEA_MPI_LONG); Add(ExtendKey[i], Temp1, Temp2, CEA_MPI_LONG); LShift(Temp2, ExtendKey[i], 5, CEA_MPI_LONG); Copy(ExtendKey[i], A, CEA_MPI_LONG); Add(A, B, Temp1, CEA_MPI_LONG); Add(Temp1, SrcKey[i % keycount], Temp2, CEA_MPI_LONG); long t = Temp1[1] % (long)64; LShift(Temp2, SrcKey[i % keycount], (int)t, CEA_MPI_LONG); Copy(SrcKey[i % keycount], B, CEA_MPI_LONG); } } public void IntToByte(int source[], byte result[], int length) { for(int i = 0; i < length; i++) if(source[i] < 128) result[i] = (byte)source[i]; else result[i] = (byte)(source[i] - 256); } public void LShift(long source[], long result[], int count, int length) { long mid[] = new long[length]; count %= length * 32; int shiftlong = count >>> 5; int shiftbit = count & 0x1f; int rshiftbit = 32 - shiftbit; for(int i = 0; i < length; i++) { mid[i] = source[shiftlong] << shiftbit & 0xffffffffL; if(++shiftlong >= length) shiftlong = 0; mid[i] = mid[i] | source[shiftlong] >>> rshiftbit & 0xffffffffL; } for(int i = 0; i < length; i++) result[i] = mid[i]; } public static void main(String args[]) { // CEA cea = new CEA(); // String text = "1234567890123456789012345678901234567890"; // String TransferKey = "11111111"; // byte cipher[] = new byte[41]; // byte plain1[] = new byte[41]; // int res = 0; // byte plain[] = text.getBytes(); // byte key[] = TransferKey.getBytes(); // res = cea.Encrypt(plain, cipher, 40, key, 8); // res = cea.Decrypt(cipher, plain1, 40, key, 8); // String str = new String(plain1); // System.out.println("str=".concat(String.valueOf(String.valueOf(str)))); } public void RShift(long source[], long result[], int count, int length) { count %= length * 32; count = length * 32 - count; count %= length * 32; LShift(source, result, count, length); } public void Sub(long s1[], long s2[], long result[], int length) { long b = 0L; for(int i = length - 1; i >= 0; i--) { result[i] = s1[i] - s2[i] - b; if(result[i] >= (long)0) { b = 0L; } else { result[i] = result[i] + 0x100000000L; b = 1L; } } } public void Xor(long s1[], long s2[], long result[], int length) { for(int i = 0; i < length; i++) result[i] = s1[i] ^ s2[i]; } }