safedispatch-mobile/libSafeMobile/src/main/java/com/safemobile/services/TEA.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;
}
}