class CloudComm {
- String baseurl;
- Cipher encryptCipher;
- Cipher decryptCipher;
- Mac mac;
- String password;
- SecureRandom random;
- static final int SALT_SIZE = 8;
- static final int TIMEOUT_MILLIS = 100;
- byte salt[];
- Table table;
+ private static final int SALT_SIZE = 8;
+ private static final int TIMEOUT_MILLIS = 100;
+
+ private String baseurl;
+ private Cipher encryptCipher;
+ private Cipher decryptCipher;
+ private Mac mac;
+ private String password;
+ private SecureRandom random;
+ private byte salt[];
+ private Table table;
+ private int listeningPort = -1;
+ private Thread localServerThread = null;
+ private boolean doEnd = false;
/**
* Empty Constructor needed for child class.
/**
* Constructor for actual use. Takes in the url and password.
*/
- CloudComm(Table _table, String _baseurl, String _password) {
+ CloudComm(Table _table, String _baseurl, String _password, int _listeningPort) {
this.table = _table;
this.baseurl = _baseurl;
this.password = _password;
this.random = new SecureRandom();
+ this.listeningPort = _listeningPort;
+
+ if (this.listeningPort > 0) {
+ localServerThread = new Thread(new Runnable() {
+ public void run() {
+ localServerWorkerFunction();
+ }
+ });
+ localServerThread.start();
+ }
}
/**
*/
private SecretKeySpec initKey() {
try {
- PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
+ PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray(),
+ salt,
+ 65536,
+ 128);
SecretKey tmpkey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(keyspec);
return new SecretKeySpec(tmpkey.getEncoded(), "AES");
} catch (Exception e) {
* Inits the HMAC generator.
*/
private void initCrypt() {
+
+ if (password == null) {
+ return;
+ }
+
try {
SecretKeySpec key = initKey();
password = null; // drop password
}
public void setSalt() throws ServerException {
+
+ if (salt != null) {
+ // Salt already sent to server so dont set it again
+ return;
+ }
+ byte[] saltTmp = new byte[SALT_SIZE];
+ random.nextBytes(saltTmp);
+
+ URL url = null;
+ URLConnection con = null;
+ HttpURLConnection http = null;
+
try {
- byte[] saltTmp = new byte[SALT_SIZE];
- random.nextBytes(saltTmp);
- URL url = new URL(baseurl + "?req=setsalt");
- URLConnection con = url.openConnection();
- HttpURLConnection http = (HttpURLConnection) con;
+ url = new URL(baseurl + "?req=setsalt");
+ con = url.openConnection();
+ http = (HttpURLConnection) con;
http.setRequestMethod("POST");
http.setFixedLengthStreamingMode(saltTmp.length);
http.setDoOutput(true);
int responsecode = http.getResponseCode();
if (responsecode != HttpURLConnection.HTTP_OK) {
// TODO: Remove this print
- // System.out.println(responsecode);
+ System.out.println(responsecode);
throw new Error("Invalid response");
}
- salt = saltTmp;
} catch (Exception e) {
throw new ServerException("Failed setting salt", ServerException.TypeConnectTimeout);
}
- initCrypt();
+
+
+ try {
+ InputStream is = http.getInputStream();
+ DataInputStream dis = new DataInputStream(is);
+ // byte [] tmp = new byte[1];
+ byte tmp = dis.readByte();
+
+ if (tmp == 0) {
+ salt = saltTmp;
+ initCrypt();
+ } else {
+ getSalt(); // there was already a salt so we need to get it
+ }
+
+ } catch (SocketTimeoutException e) {
+ throw new ServerException("setSalt failed", ServerException.TypeInputTimeout);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("setSlot failed");
+ }
}
private void getSalt() throws ServerException {
e.printStackTrace();
throw new Error("getSlot failed");
}
-
}
/*
OutputStream os = http.getOutputStream();
os.write(bytes);
os.flush();
+
+ // System.out.println("Bytes Sent: " + bytes.length);
} catch (SocketTimeoutException e) {
throw new ServerException("putSlot failed", ServerException.TypeConnectTimeout);
} catch (Exception e) {
}
}
-
/**
* Request the server to send all slots with the given
* sequencenumber or newer.
http.setRequestMethod("POST");
http.setConnectTimeout(TIMEOUT_MILLIS);
http.setReadTimeout(TIMEOUT_MILLIS);
-
-
http.connect();
- } catch (ServerException e) {
+ } catch (SocketTimeoutException e) {
throw new ServerException("getSlots failed", ServerException.TypeConnectTimeout);
+ } catch (ServerException e) {
+ throw e;
} catch (Exception e) {
e.printStackTrace();
throw new Error("getSlots failed");
throw new Error("Bad Response: " + new String(resptype));
else
return processSlots(dis);
- } catch (ServerException e) {
+ } catch (SocketTimeoutException e) {
throw new ServerException("getSlots failed", ServerException.TypeInputTimeout);
} catch (Exception e) {
e.printStackTrace();
private Slot[] processSlots(DataInputStream dis) throws Exception {
int numberofslots = dis.readInt();
int[] sizesofslots = new int[numberofslots];
+
+
+ // System.out.println("number of slots: " + numberofslots);
+
+
+
Slot[] slots = new Slot[numberofslots];
for (int i = 0; i < numberofslots; i++)
sizesofslots[i] = dis.readInt();
for (int i = 0; i < numberofslots; i++) {
+
+ // System.out.println("Size of slot: " + sizesofslots[i]);
+
byte[] data = new byte[sizesofslots[i]];
dis.readFully(data);
dis.close();
return slots;
}
+
+ public byte[] sendLocalData(byte[] sendData, String host, int port) {
+
+ if (salt == null) {
+ return null;
+ }
+ try {
+ // Encrypt the data for sending
+ byte[] encryptedData = encryptCipher.doFinal(sendData);
+
+ // Open a TCP socket connection to a local device
+ Socket socket = new Socket(host, port);
+ socket.setReuseAddress(true);
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+
+ // Send data to output (length of data, the data)
+ output.writeInt(encryptedData.length);
+ output.write(encryptedData, 0, encryptedData.length);
+ output.flush();
+
+ int lengthOfReturnData = input.readInt();
+ byte[] returnData = new byte[lengthOfReturnData];
+ input.readFully(returnData);
+ returnData = decryptCipher.doFinal(returnData);
+
+ // We are dont with this socket
+ socket.close();
+
+ return returnData;
+ } catch (SocketTimeoutException e) {
+
+ } catch (BadPaddingException e) {
+
+ } catch (IllegalBlockSizeException e) {
+
+ } catch (UnknownHostException e) {
+
+ } catch (IOException e) {
+
+ }
+
+ return null;
+ }
+
+ private void localServerWorkerFunction() {
+
+ ServerSocket inputSocket = null;
+
+ try {
+ // Local server socket
+ inputSocket = new ServerSocket(listeningPort);
+ inputSocket.setReuseAddress(true);
+ inputSocket.setSoTimeout(TIMEOUT_MILLIS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("Local server setup failure...");
+ }
+
+ while (!doEnd) {
+
+ try {
+ // Accept incoming socket
+ Socket socket = inputSocket.accept();
+
+ DataInputStream input = new DataInputStream(socket.getInputStream());
+ DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+
+ // Get the encrypted data from the server
+ int dataSize = input.readInt();
+ byte[] readData = new byte[dataSize];
+ input.readFully(readData);
+
+ // Decrypt the data
+ readData = decryptCipher.doFinal(readData);
+
+ // Process the data
+ byte[] sendData = table.acceptDataFromLocal(readData);
+
+ // Encrypt the data for sending
+ sendData = encryptCipher.doFinal(sendData);
+
+ // Send data to output (length of data, the data)
+ output.writeInt(sendData.length);
+ output.write(sendData, 0, sendData.length);
+ output.flush();
+
+ // close the socket
+ socket.close();
+ } catch (SocketTimeoutException e) {
+
+ } catch (BadPaddingException e) {
+
+ } catch (IllegalBlockSizeException e) {
+
+ } catch (UnknownHostException e) {
+
+ } catch (IOException e) {
+
+ }
+ }
+
+ if (inputSocket != null) {
+ try {
+ inputSocket.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("Local server close failure...");
+ }
+ }
+ }
+
+ public void close() {
+ doEnd = true;
+
+ try {
+ localServerThread.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Error("Local Server thread join issue...");
+ }
+
+ System.out.println("Done Closing");
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ close(); // close open files
+ } finally {
+ super.finalize();
+ }
+ }
+
}