281 lines
7.8 KiB
Java
281 lines
7.8 KiB
Java
package com.safemobile.services;
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
public class TEA {
|
|
|
|
private final static long DELTA = 0x9E3779B9L;
|
|
private final static long STEPS = 32;
|
|
private final static long UNDELTA = 0xC6EF3720L;
|
|
private static final String password = "SafeMobileBridge";
|
|
private static String encoding = "UTF-8";
|
|
private static long[] encrypted;
|
|
private static long[] decrypted;
|
|
private static long[] key;
|
|
|
|
public TEA(String password, String encoding) throws UnsupportedEncodingException {
|
|
// convert key to long
|
|
key = convertByteArrayToLongArray(password.getBytes(encoding));
|
|
TEA.encoding = encoding;
|
|
}
|
|
|
|
public TEA(String password) throws UnsupportedEncodingException {
|
|
// convert key to long
|
|
key = convertByteArrayToLongArray(password.getBytes(encoding));
|
|
}
|
|
|
|
|
|
public static byte[] encrypt(String toEncrypt) throws UnsupportedEncodingException {
|
|
encrypted = new long[200];
|
|
|
|
key = convertByteArrayToLongArray(password.getBytes(encoding));
|
|
|
|
// convert String to long array
|
|
long[] values = convertByteArrayToLongArray(toEncrypt.getBytes(encoding));
|
|
|
|
encrypted = new long[values.length];
|
|
|
|
// encipher the long array
|
|
for(int i=0; i<values.length; i=i+2) {
|
|
//System.out.println("v[" + i + "]=" + values[i]);
|
|
//System.out.println("v[" + (i+1) + "]=" + values[i+1]);
|
|
|
|
// get the long values that will be enciphered
|
|
long[] v = new long[2];
|
|
long[] w = new long[2];
|
|
v[0] = values[i];
|
|
v[1] = values[i+1];
|
|
|
|
// ENCRYPT
|
|
encipher(v, w, key);
|
|
|
|
// save the encrypted values in the big string
|
|
encrypted[i] = w[0];
|
|
encrypted[i+1] = w[1];
|
|
//System.out.println("\nEncrypted: " + w[0] + " | " + w[1]);
|
|
}
|
|
return convertLongArrayToByteArray(encrypted, false);
|
|
}
|
|
|
|
/*
|
|
public static byte[] decrypt(long[] toDecrypt) {
|
|
// convert String to long array
|
|
long[] values = toDecrypt;
|
|
|
|
decrypted = new long[values.length];
|
|
|
|
for(int i=0; i<values.length; i=i+2) {
|
|
//System.out.println("v[" + i + "]=" + values[i]);
|
|
//System.out.println("v[" + (i+1) + "]=" + values[i+1]);
|
|
|
|
long[] v = new long[2];
|
|
long[] w = new long[2];
|
|
v[0] = values[i];
|
|
v[1] = values[i+1];
|
|
|
|
|
|
// ENCRYPT
|
|
decipher(v, w, key);
|
|
|
|
// save the encrypted values in the big string
|
|
decrypted[i] = w[0];
|
|
decrypted[i+1] = w[1];
|
|
//System.out.println("\nEncrypted: " + w[0] + " | " + w[1]);
|
|
}
|
|
|
|
return convertLongArrayToByteArray(decrypted);
|
|
|
|
}
|
|
*/
|
|
|
|
public static byte[] decrypt(byte[] toDecrypt) throws UnsupportedEncodingException {
|
|
// convert String containing encrypted data to long array
|
|
long[] values = convertByteArrayToLongArray(toDecrypt);
|
|
|
|
decrypted = new long[values.length];
|
|
|
|
key = convertByteArrayToLongArray(password.getBytes(encoding));
|
|
|
|
for(int i=0; i<values.length; i=i+2) {
|
|
//System.out.println("v[" + i + "]=" + values[i]);
|
|
//System.out.println("v[" + (i+1) + "]=" + values[i+1]);
|
|
|
|
long[] v = new long[2];
|
|
long[] w = new long[2];
|
|
v[0] = values[i];
|
|
v[1] = values[i+1];
|
|
|
|
// DECRYPT
|
|
decipher(v, w, key);
|
|
|
|
// save the encrypted values in the big string
|
|
decrypted[i] = w[0];
|
|
decrypted[i+1] = w[1];
|
|
//System.out.println("\nEncrypted: " + w[0] + " | " + w[1]);
|
|
}
|
|
|
|
return convertLongArrayToByteArray(decrypted, true);
|
|
|
|
}
|
|
|
|
|
|
private static void encipher(long v[], long w[], long k[])
|
|
{
|
|
long y=v[0],z=v[1],sum=0, a=k[0],b=k[1],c=k[2],d=k[3],n=STEPS;
|
|
|
|
//System.out.printf("\nv[0] = %d | v[1] = %d\n", y, z);
|
|
//System.out.printf("a=%d | b=%d | c=%d | d=%d\n", a,b,c,d);
|
|
|
|
while(n-- > 0)
|
|
{
|
|
/*
|
|
sum += DELTA;
|
|
y += ((z << 4)+a) ^ (z+sum) ^ ((z >> 5)+b);
|
|
z += ((y << 4)+c) ^ (y+sum) ^ ((y >> 5)+d);
|
|
*/
|
|
sum = (long)((int)(sum + DELTA) & 0xFFFFFFFFL);
|
|
|
|
/*
|
|
System.out.println("left: " + (ctu(z<<4) + a));
|
|
System.out.println("center: " + ctu(z + sum));
|
|
System.out.println("right: " + (ctu(z>>>5) + b));
|
|
*/
|
|
y = ctu(y + ((ctu(z<<4) + a) ^ (z + sum) ^ (ctu(z>>>5) + b)));
|
|
z = ctu(z + ((ctu(y<<4) + c) ^ (y + sum) ^ (ctu(y>>>5) + d)));
|
|
|
|
//System.out.println("Y = " + y + " | " + "Z = " + z) ;
|
|
}
|
|
w[0]=y; w[1]=z;
|
|
|
|
//System.out.println("Encrypted: " + y + " | " + z);
|
|
}
|
|
|
|
private static void decipher(long v[], long w[], long k[])
|
|
{
|
|
long y=v[0],z=v[1],sum=UNDELTA, a=k[0],b=k[1], c=k[2],d=k[3],n=STEPS;
|
|
/* sum = delta<<5, in general sum = delta * n */
|
|
while(n-->0)
|
|
{
|
|
z = ctu(z - ((ctu(y << 4)+c) ^ (y+sum) ^ (ctu(y >>> 5)+d)));
|
|
y = ctu(y - ((ctu(z << 4)+a) ^ (z+sum) ^ (ctu(z >>> 5)+b)));
|
|
|
|
//System.out.println("Y = " + y + " | " + "Z = " + z) ;
|
|
|
|
sum -= DELTA;
|
|
}
|
|
w[0]=y; w[1]=z;
|
|
//System.out.println("Y = " + y + " | " + "Z = " + z) ;
|
|
}
|
|
|
|
/*
|
|
private long convertToUnsigned(long value) {
|
|
return (((int) value) & 0xFFFFFFFFL);
|
|
}
|
|
*/
|
|
|
|
private static long ctu (long value) {
|
|
return (((int) value) & 0xFFFFFFFFL);
|
|
}
|
|
|
|
|
|
private static long[] convertByteArrayToLongArray(byte[] toConvert) {
|
|
// convert string in an array of bytes
|
|
byte[] by = toConvert;
|
|
|
|
|
|
// get the size of long array considering that a long has 4bytes
|
|
int size = (int) Math.ceil(by.length / 4);
|
|
|
|
// if the size of the array is an odd number I should increase it because
|
|
// encryption needs an array of two long values
|
|
if(size % 2 != 0)
|
|
size++;
|
|
|
|
long[] values = new long[size];
|
|
|
|
// convert every string value to a long one by shifting 4 chars
|
|
// a long is 4 bytes
|
|
for(int i=0; i<by.length; i=i+4) {
|
|
|
|
//
|
|
byte c4 = ((i+3 >= by.length ) ? 0 : (byte) by[i+3]);
|
|
byte c3 = ((i+2 >= by.length ) ? 0 : (byte) by[i+2] );
|
|
byte c2 = ((i+1 >= by.length ) ? 0 : (byte) by[i+1] );
|
|
byte c1 = ((i >= by.length ) ? 0 : (byte) by[i] );
|
|
|
|
//System.out.println("###" + c4 + " | " + c3 + " | " + c2 + " | " + c1);
|
|
|
|
values[i/4] = ctu(((c4 & 0x00FFL) << 24) + ((c3 & 0x00FFL) << 16) + ((c2 & 0x00FFL) << 8) + ((c1 & 0x00FFL)));
|
|
//System.out.println("##### " + (encrypted == null ? 0 : encrypted[i/4]) + " | " + values[i/4]);
|
|
}
|
|
return values;
|
|
}
|
|
|
|
|
|
private static byte[] convertLongArrayToByteArray(long[] array, boolean isDecrypt) {
|
|
//String myString = "";
|
|
byte[] byteArray = new byte[array.length * 4];
|
|
byte[] byteArrayReduced;
|
|
int sizeToReduce = 0;
|
|
|
|
// convert every bytes from a long into a char using masks
|
|
for(int i=0; i<array.length; i++) {
|
|
byte c1 = (byte) (array[i] & 0xFF);
|
|
byte c2 = (byte) ((array[i] & 0x0000FF00) >> 8);
|
|
byte c3 = (byte) ((array[i] & 0x00FF0000) >> 16);
|
|
byte c4 = (byte) ((array[i] & 0xFF000000) >> 24);
|
|
|
|
//System.out.println("###" + array[i] + " | c4: " + c4 + " | " + c3 + " | " + c2 + " | " + c1);
|
|
//*
|
|
// remove last bytes containing 0 because they are unwanted information
|
|
if(array.length > 1 && i==(array.length-1) && isDecrypt)
|
|
{
|
|
System.out.println("LAST Chunck of four");
|
|
if (c4 != 0)
|
|
byteArray[i*4+3] = c4;
|
|
else
|
|
sizeToReduce++;
|
|
if (c3 != 0)
|
|
byteArray[i*4+2] = c3;
|
|
else
|
|
sizeToReduce++;
|
|
if (c2 != 0)
|
|
byteArray[i*4+1] = c2;
|
|
else
|
|
sizeToReduce++;
|
|
if (c1 != 0)
|
|
byteArray[i*4] = c1;
|
|
else
|
|
sizeToReduce++;
|
|
}
|
|
// add value because it's not the last long value
|
|
|
|
else //*/
|
|
{
|
|
byteArray[i*4] = c1;
|
|
byteArray[i*4+1] = c2;
|
|
byteArray[i*4+2] = c3;
|
|
byteArray[i*4+3] = c4;
|
|
}
|
|
|
|
}
|
|
|
|
// remove the 0's from the string, they were added when converting long
|
|
//System.out.println("#### Syze to reduce : " + sizeToReduce);
|
|
byteArrayReduced = new byte[byteArray.length - sizeToReduce];
|
|
for(int i=0; i<(byteArray.length - sizeToReduce); i++)
|
|
byteArrayReduced[i] = byteArray[i];
|
|
|
|
/*
|
|
try {
|
|
myString = new String ( byteArray, encoding);
|
|
} catch (UnsupportedEncodingException e) {
|
|
e.printStackTrace();
|
|
}*/
|
|
|
|
//myString = new String(byteArray);
|
|
|
|
return byteArrayReduced;
|
|
}
|
|
|
|
}
|