From da3251e24dcc3c3503834cd70bc5b23a97b3eee0 Mon Sep 17 00:00:00 2001 From: Brian Demsky Date: Tue, 26 Jul 2016 18:37:50 -0700 Subject: [PATCH] Add support for salts and crypto --- src/java/iotcloud/CloudComm.java | 99 +++++++++++++++++++++----------- src/java/iotcloud/Table.java | 1 + src/java/iotcloud/issues.txt | 3 +- src/server/iotquery.cpp | 78 +++++++++++++++++++++++-- src/server/iotquery.h | 7 +++ 5 files changed, 145 insertions(+), 43 deletions(-) diff --git a/src/java/iotcloud/CloudComm.java b/src/java/iotcloud/CloudComm.java index 49217ec..964b7c0 100644 --- a/src/java/iotcloud/CloudComm.java +++ b/src/java/iotcloud/CloudComm.java @@ -22,8 +22,8 @@ class CloudComm { String password; SecureRandom random; static final int SALT_SIZE = 8; - static final int IV_SIZE = 16; - + byte salt[]; + /** * Empty Constructor needed for child class. */ @@ -45,7 +45,7 @@ class CloudComm { * Generates Key from password. */ - private SecretKeySpec initKey(byte[] salt) { + private SecretKeySpec initKey() { try { PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128); SecretKey tmpkey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(keyspec); @@ -60,27 +60,16 @@ class CloudComm { * Inits the HMAC generator. */ - private byte[] initCrypt(byte[] salt) { + private void initCrypt() { try { - SecretKeySpec key=initKey(salt); + SecretKeySpec key=initKey(); + password = null; // drop password mac = Mac.getInstance("HmacSHA256"); mac.init(key); - encryptCipher =Cipher.getInstance("AES/CBC/PKCS5Padding"); + encryptCipher =Cipher.getInstance("AES/ECB/PKCS5Padding"); encryptCipher.init(Cipher.ENCRYPT_MODE, key); - return encryptCipher.getIV(); - } catch (Exception e) { - e.printStackTrace(); - throw new Error("Failed To Initialize Ciphers"); - } - } - - private void initDeCrypt(byte[] salt, byte[] iv) { - try { - SecretKeySpec key=initKey(salt); - mac = Mac.getInstance("HmacSHA256"); - mac.init(key); - Cipher decryptCipher =Cipher.getInstance("AES/CBC/PKCS5Padding"); - decryptCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + decryptCipher =Cipher.getInstance("AES/ECB/PKCS5Padding"); + decryptCipher.init(Cipher.DECRYPT_MODE, key); } catch (Exception e) { e.printStackTrace(); throw new Error("Failed To Initialize Ciphers"); @@ -98,33 +87,72 @@ class CloudComm { urlstr += "&max="+maxentries; return new URL(urlstr); } + + public void setSalt() { + try { + salt = new byte[SALT_SIZE]; + random.nextBytes(salt); + URL url=new URL(baseurl+"?req=setsalt"); + URLConnection con=url.openConnection(); + HttpURLConnection http = (HttpURLConnection) con; + http.setRequestMethod("POST"); + http.setFixedLengthStreamingMode(salt.length); + http.setDoOutput(true); + http.connect(); + OutputStream os=http.getOutputStream(); + os.write(salt); + int responsecode=http.getResponseCode(); + if (responsecode != HttpURLConnection.HTTP_OK) + throw new Error("Invalid response"); + } catch (Exception e) { + e.printStackTrace(); + throw new Error("Failed setting salt"); + } + initCrypt(); + } + private void getSalt() throws Exception { + URL url=new URL(baseurl+"?req=getsalt"); + URLConnection con=url.openConnection(); + HttpURLConnection http = (HttpURLConnection) con; + http.setRequestMethod("POST"); + http.connect(); + + InputStream is=http.getInputStream(); + DataInputStream dis=new DataInputStream(is); + int salt_length=dis.readInt(); + byte [] tmp=new byte[salt_length]; + dis.readFully(tmp); + salt=tmp; + } + /* * API for putting a slot into the queue. Returns null on success. * On failure, the server will send slots with newer sequence * numbers. */ - public Slot[] putSlot(Slot slot, int max) { + Slot[] putSlot(Slot slot, int max) { try { - long sequencenumber=slot.getSequenceNumber(); - byte[] salt=new byte[SALT_SIZE]; - random.nextBytes(salt); - byte[] iv=initCrypt(salt); + if (salt == null) { + getSalt(); + initCrypt(); + } + long sequencenumber=slot.getSequenceNumber(); byte[] bytes=slot.encode(mac); + bytes = encryptCipher.doFinal(bytes); + URL url=buildRequest(true, sequencenumber, max); URLConnection con=url.openConnection(); HttpURLConnection http = (HttpURLConnection) con; + http.setRequestMethod("POST"); http.setFixedLengthStreamingMode(bytes.length); http.setDoOutput(true); http.connect(); OutputStream os=http.getOutputStream(); - os.write(salt); - os.write(iv); - bytes = encryptCipher.doFinal(bytes); os.write(bytes); InputStream is=http.getInputStream(); @@ -138,6 +166,7 @@ class CloudComm { else throw new Error("Bad response to putslot"); } catch (Exception e) { + e.printStackTrace(); throw new Error("putSlot failed"); } } @@ -147,8 +176,13 @@ class CloudComm { * sequencenumber or newer. */ - public Slot[] getSlots(long sequencenumber) { + Slot[] getSlots(long sequencenumber) { try { + if (salt == null) { + getSalt(); + initCrypt(); + } + URL url=buildRequest(false, sequencenumber, 0); URLConnection con=url.openConnection(); HttpURLConnection http = (HttpURLConnection) con; @@ -165,6 +199,7 @@ class CloudComm { else return processSlots(dis); } catch (Exception e) { + e.printStackTrace(); throw new Error("getSlots failed"); } } @@ -182,12 +217,6 @@ class CloudComm { sizesofslots[i]=dis.readInt(); for(int i=0; i