commit 40f771b724947eb8fcbcbd310e4fa8252fb1a072 Author: emigranteMuse Date: Mon Mar 6 19:16:22 2017 +0800 3.6 diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..b54f5cb --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..b8be53e --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ORAM + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..838bd9d --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/src/nankai/oram/client/MCOSORAMClient.java b/src/nankai/oram/client/MCOSORAMClient.java new file mode 100644 index 0000000..3269f1c --- /dev/null +++ b/src/nankai/oram/client/MCOSORAMClient.java @@ -0,0 +1,344 @@ +package nankai.oram.client; + +import java.security.NoSuchAlgorithmException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Random; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import nankai.oram.client.common.Position; +import nankai.oram.client.common.SlotObject; +import nankai.oram.client.mCloud.MCOSPartition; +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.client.mCloud.SubCloudNewORAM; +import nankai.oram.common.CommInfo; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.Util; +import nankai.oram.interfaces.ORAM; + +public class MCOSORAMClient implements ORAM{ + + + boolean initFlag; + + int N; + int n_partitions; //All the partitions, for each cloud, it would be divided + //int n_partitions_cloud;//the number of partitions for a cloud + int n_capacity;//the max capacity of a partition -- need the top level + int n_levels; + int n_blocks; + int n_realBlocks_p;//the real number of blocks in a partition + int top_level_len;//the number of blocks in the top level + int counter=0;//for sequneceEvict + + Position pos_map[];//position map + + /*************************************************/ + Queue slots[]; + + SocketClientUtil[] cli; + + MCOSPartition[] partitions; + + + public MCOSORAMClient() + { + initFlag=false; + cli=new SocketClientUtil[MCloudCommInfo.cloudNumber]; + + } + + /** + * initialize the parameters, storage space and so on + * @param nN + */ + public boolean init(int nN) + { + if (initFlag==true) + { + System.out.println("have inited!"); + return false; + } + N=nN; + n_partitions = (int) Math.ceil(Math.sqrt(nN)); + //n_partitions_cloud = (int) Math.ceil(n_partitions/MCloudCommInfo.cloudNumber) ; + + n_realBlocks_p = (int) Math.ceil(((double) nN) / n_partitions); + n_blocks = n_realBlocks_p * n_partitions; + + n_levels = (int) (Math.log((double) n_realBlocks_p) / Math.log(2.0)) + 1; + n_capacity = (int) Math.ceil(CommInfo.capacity_parameter * n_realBlocks_p); + + pos_map=new Position[n_blocks]; + for (int i=0;i(); + partitions[i]=new MCOSPartition(n_realBlocks_p, n_levels, pos_map, cli, i); + } + + counter = 0; + + initFlag=true; + return true; + } + + public void openConnection() + { + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + cli[i].connect(); + } + } + public void closeConnection() + { + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + cli[i].disConnect(); + } + } + + public boolean initORAM() + { + boolean bRet = true; + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + byte cmd[]=new byte[14]; + cmd[0]=CommandType.initORAM; + Util.intToByte(cmd, 1, n_partitions); + Util.intToByte(cmd, 5, n_capacity); + Util.intToByte(cmd, 9, n_levels); + cmd[13] = (byte) i; + + cli[i].send( cmd, 14, null , 0, null); + if (cli[i].responseType!=ResponseType.wrong) + bRet = false; + } + + return bRet; + } + + + + /** + * Notice the ORAM server to open the database + * @return + */ + public boolean openORAM() + { + boolean bRet = true; + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) { + byte cmd[] = new byte[2]; + cmd[0] = CommandType.openDB; + cmd[1] = (byte)i; + + cli[i].send(cmd, 2, null, 0, null); + + if (cli[i].responseType != ResponseType.wrong) + bRet = false; + } + + return bRet; + } + + + + + byte[] access(char op, int block_id, byte[] value) + { +// try { +// Thread.sleep(10); +// } catch (InterruptedException e) { +// // TODO 自动生成的 catch 块 +// e.printStackTrace(); +// } + + byte data[] = new byte[CommInfo.blockSize]; + + + int r = Util.rand_int(this.n_partitions); + + //int c = pos_map[block_id].cloud; + + int p = pos_map[block_id].partition; + int level = pos_map[block_id].level; + /**************** + * Read data from slots or the server + * If it is in the slot + * readAndDel from the slot + * read a dummy block from server + * Else + * read the real block from the server + * ******************/ + if (p >= 0) { + boolean isInSlot = false; + Iterator itr = slots[p].iterator(); + SlotObject targetObj = null; + while (itr.hasNext()) + { + targetObj = (SlotObject)itr.next(); + if (targetObj.id==block_id) + { + isInSlot=true; + break; + } + } + + if ( isInSlot ) { + // in the slot + System.arraycopy(targetObj.value, 0, data, 0, CommInfo.blockSize); + slots[p].remove(targetObj); + //read a dummy block from clouds + readData(p, CommInfo.dummyID); + } else { + /************************** + * Here, should send a request to the cloud server to get the + * data + * **************************/ + byte[] ret = readData(p, block_id); + if (ret!=null) + System.arraycopy(ret, 0, data, 0, CommInfo.blockSize); + + } + + } + + pos_map[block_id].partition = r; + pos_map[block_id].level = -1; + pos_map[block_id].offset = -1; + + if (op == 'w') + { + System.arraycopy( value, 0, data, 0, CommInfo.blockSize); + } + writeCache(block_id, data, r); + + randomEvict(CommInfo.v); + return data; + } + + private byte[] readData(int p, int blockid) { + return partitions[p].readPartition(blockid); + } + + /**** + * Write to the cache. With the first layer onion-encryption + * @param block_id + * @param data + * @param r + */ + private void writeCache(int block_id, byte[] data, int p) { + //should be first onion - encryption + + SlotObject newObject = new SlotObject(block_id, data); + + slots[p].add(newObject); + } + + + void sequentialEvict(int vNumber) + { + for (int i = 0; i < vNumber; i++) { + counter = (counter + 1) % MCloudCommInfo.cloudNumber; + evict(counter); + } + } + void randomEvict(int vNumber) + { + Random rnd=new Random(); + for (int i = 0; i < vNumber; i++) { + int r = rnd.nextInt(this.n_partitions); + evict(r); + } + } + void evict(int p) { + + if (slots[p].size() >= 1) + { + //First to analysis which cloud to write + int cloud=1; + /*************************************** + * Judge which cloud should be written + ***************************************/ + + SlotObject targetObj = (SlotObject)slots[p].poll(); + partitions[p].writePartition(targetObj); + } + } + + + public int getCacheSlotSize() + { + int ret = 0; + for (int i=0; i0) + ;// subORAMs[i].writeCloud(slots[i]); + slots[i].clear(); + } + } + + public int getIDinDB() + { + for (int i=0;i slots[]; + + SocketClientUtil[] cli; + + byte s_buffer[][]; + public NewMCOSORAMClient() + { + initFlag=false; + cli=new SocketClientUtil[MCloudCommInfo.cloudNumber]; + + } + + /** + * initialize the parameters, storage space and so on + * @param nN + */ + public boolean init(int nN) + { + if (initFlag==true) + { + System.out.println("have inited!"); + return false; + } + N=nN; + n_partitions = (int) Math.ceil(Math.sqrt(nN)); + n_partitions_cloud = (int) Math.ceil(n_partitions/MCloudCommInfo.cloudNumber) ; + + n_realBlocks_p = (int) Math.ceil(((double) nN) / n_partitions); + n_blocks = n_realBlocks_p * n_partitions; + + n_levels = (int) (Math.log((double) n_realBlocks_p) / Math.log(2.0)) + 1; + n_capacity = (int) Math.ceil(CommInfo.capacity_parameter * n_realBlocks_p); + + pos_map=new Position[n_blocks]; + for (int i=0;i(); + cli[i]=new SocketClientUtil(MCloudCommInfo.ip[i], MCloudCommInfo.port[i]); + subORAMs[i]=new SubCloudNewORAM(n_partitions_cloud, n_realBlocks_p, n_levels, n_capacity, i, pos_map, cli, s_buffer); + } + + counter = 0; + + initFlag=true; + return true; + } + + public void openConnection() + { + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + cli[i].connect(); + } + } + public void closeConnection() + { + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + cli[i].disConnect(); + } + } + + public boolean initORAM() + { + boolean bRet = true; + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + if (subORAMs[i].initORAM()==false) + bRet = false; + } + + return bRet; + } + + /** + * Notice the ORAM server to open the database + * @return + */ + public boolean openORAM() + { + boolean bRet = true; + for (int i = 0; i < MCloudCommInfo.cloudNumber; i++) + { + if (subORAMs[i].openORAM()==false) + bRet = false; + } + + return bRet; + } + + + + byte[] access(char op, int block_id, byte[] value) + { + +// try { +// Thread.sleep(10); +// } catch (InterruptedException e) { +// // TODO 自动生成的 catch 块 +// e.printStackTrace(); +// } + try{ + +// System.out.println("access begin"); + + byte data[] = new byte[CommInfo.blockSize]; + + int r = Util.rand_int(MCloudCommInfo.cloudNumber); + + int c = pos_map[block_id].cloud; + int p = pos_map[block_id].partition; + /**************** + * Read data from slots or the server If it is in the slot + * readAndDel from the slot read a dummy block from server Else read + * the real block from the server + * ******************/ + if (c >= 0) { + boolean isInSlot = false; + Iterator itr = slots[c].iterator(); + SlotObject targetObj = null; + while (itr.hasNext()) { + targetObj = (SlotObject) itr.next(); + if (targetObj.id == block_id) { + isInSlot = true; + break; + } + } + + if (isInSlot) { + // in the slot + System.arraycopy(targetObj.value, 0, data, 0, + CommInfo.blockSize); + slots[c].remove(targetObj); +// System.out.println("readdummy block_id " + block_id + " c:" +// + c + " p:" + p); + subORAMs[c].readCloud(CommInfo.dummyID); +// System.out.println("readdummy end block_id " + block_id +// + " c:" + c + " p:" + p); + } else { + /************************** + * Here, should send a request to the cloud server to get + * the data + * **************************/ +// System.out.println("readCloud block_id " + block_id + " c:" +// + c + " p:" + p); + System.arraycopy(subORAMs[c].readCloud(block_id), 0, data, + 0, CommInfo.blockSize); +// System.out.println("read end"); + } + + } + + pos_map[block_id].cloud = r; + pos_map[block_id].partition = -1; + pos_map[block_id].level = -1; + pos_map[block_id].offset = -1; + + if (op == 'w') { + System.arraycopy(value, 0, data, 0, CommInfo.blockSize); + } + writeCache(block_id, data, r); + + //System.out.println("sequentialEvict begin"); + sequentialEvict(CommInfo.v); + //System.out.println("sequentialEvict end"); + +// System.out.println("access end"); + return data; + }catch(Exception ex) + { + ex.printStackTrace(); + } + return null; + } + + /**** + * Write to the cache. With the first layer onion-encryption + * @param block_id + * @param data + * @param r + */ + private void writeCache(int block_id, byte[] data, int c) { + //should be first onion - encryption + + SlotObject newObject = new SlotObject(block_id, data); + + slots[c].add(newObject); + } + + + void sequentialEvict(int vNumber) + { + for (int i = 0; i < vNumber; i++) { + counter = (counter + 1) % MCloudCommInfo.cloudNumber; + evict(counter); + } + } + void randomEvict(int vNumber) + { + Random rnd=new Random(); + for (int i = 0; i < vNumber; i++) { + int r = rnd.nextInt(MCloudCommInfo.cloudNumber); + evict(r); + } + } + void evict(int c) { + + if (slots[c].size() >= MCloudCommInfo.evictConditionSize) + { +// System.out.println("evict c:"+c+" slot size:"+slots[c].size()); + subORAMs[c].writeCloud(slots[c]); + } + } + + + public int getCacheSlotSize() + { + int ret = 0; + for (int i=0; i0) + subORAMs[i].writeCloud(slots[i]); + slots[i].clear(); + } + } + + public int getIDinDB() + { + for (int i=0;i slots[]; + Partition partions[]; + + + SocketClientUtil cli; + + + + public PartitionClient() + { + initFlag=false; + cli=new SocketClientUtil("localhost",2121); + } + + /** + * initialize the parameters, storage space and so on + * @param nN + */ + public boolean init(int nN) + { + if (initFlag==true) + { + System.out.println("have inited!"); + return false; + } + N=nN; + n_partitions = (int) Math.ceil(Math.sqrt(nN)); + + n_realBlocks_p = (int) Math.ceil(((double) nN) / n_partitions); + n_blocks = n_realBlocks_p * n_partitions; + + n_levels = (int) (Math.log((double) n_realBlocks_p) / Math.log(2.0)) + 1; + n_capacity = (int) Math.ceil(CommInfo.capacity_parameter * n_realBlocks_p); + + partions=new Partition[n_partitions]; + + s_buffer=new byte[n_capacity][CommInfo.blockSize]; + pos_map=new Position[n_blocks]; + for (int i=0;i(); + partions[i]=new Partition(N, n_partitions, pos_map, s_buffer, cli); + } + + counter = 0; + + initFlag=true; + return true; + } + + public void openConnection() + { + cli.connect(); + } + public void closeConnection() + { + cli.disConnect(); + } + + public boolean initORAM() + { + byte cmd[]=new byte[5]; + cmd[0]=CommandType.initORAM; + Util.intToByte(cmd, 1, N); + + cli.send( cmd, 5, null , 0, null); + + return cli.responseType!=ResponseType.wrong; + } + + /** + * Notice the ORAM server to open the database, will use the created database + * @return + */ + public boolean openORAM() + { + byte cmd[]=new byte[5]; + cmd[0]=CommandType.openDB; + + cli.send( cmd, 1, null , 0, null); + + return cli.responseType!=ResponseType.wrong; + } + + + byte[] access(char op, int block_id, byte[] value) + { + byte data[] = new byte[CommInfo.blockSize]; + + int r = 1; + if (Util.debug==false){ + r = Util.rand_int(n_partitions); + //not write to the partition with more than the pre-defined real blocks + while ( partions[r].realDataNumber >= this.n_realBlocks_p ) + r = Util.rand_int(n_partitions); + } + + int p = pos_map[block_id].partition; + /**************** + * Read data from slots or the server + * If it is in the slot + * readAndDel from the slot + * read a dummy block from server + * Else + * read the real block from the server + * ******************/ + if (p >= 0) { + boolean isInSlot = false; + Iterator itr = slots[p].iterator(); + SlotObject targetObj = null; + while (itr.hasNext()) + { + targetObj = (SlotObject)itr.next(); + if (targetObj.id==block_id) + { + isInSlot=true; + break; + } + } + + if ( isInSlot ) { + // in the slot + System.arraycopy(targetObj.value, 0, data, 0, CommInfo.blockSize); + slots[p].remove(targetObj); + partions[p].readPartition(CommInfo.dummyID); + } else { + /************************** + * Here, should send a request to the cloud server to get the + * data + * **************************/ + byte[] bReadData=partions[p].readPartition(block_id); + System.arraycopy(bReadData, 0, data, 0, CommInfo.blockSize); + } + } + + pos_map[block_id].partition = r; + pos_map[block_id].level = -1; + pos_map[block_id].offset = -1; + + if (op == 'w') + { + data=value; + } + SlotObject newObject = new SlotObject(block_id, data); + slots[r].add(newObject); + +// if (p>=0) +// evict(p); + + randomEvict(CommInfo.v); + return data; + } + + void sequentialEvict(int vNumber) + { + for (int i = 0; i < vNumber; i++) { + counter = (counter + 1) % n_partitions; + evict(counter); + } + } + void randomEvict(int vNumber) + { + Random rnd=new Random(); + for (int i = 0; i < vNumber; i++) { + int r = rnd.nextInt(n_partitions); + evict(r); + } + } + void evict(int p) { + + if (slots[p].isEmpty()) { + partions[p].writePartition(CommInfo.dummyID, null); + } else { + //pop a data in slots + SlotObject obj=slots[p].poll(); + partions[p].writePartition( obj.id, obj.value); + } + } + + public int getCacheSlotSize() + { + int ret = 0; + for (int i=0; i0){ + SlotObject obj=slots[i].poll(); + partions[i].writePartition(obj.id, obj.value); + } + slots[i].clear(); + } + } + + @Override + public void write(String idStr, byte[] value) { + access('w', Integer.parseInt(idStr), value); + } + + @Override + public byte[] read(String idStr) { + return access('r', Integer.parseInt(idStr), null); + } + + @Override + public void write(int id, byte[] value) { + access('w', id, value); + } + + @Override + public byte[] read(int id) { + return access('r', id, null); + } + + +} diff --git a/src/nankai/oram/client/Test/PartitionClientJUnitTest.java b/src/nankai/oram/client/Test/PartitionClientJUnitTest.java new file mode 100644 index 0000000..25fe6ed --- /dev/null +++ b/src/nankai/oram/client/Test/PartitionClientJUnitTest.java @@ -0,0 +1,33 @@ +package nankai.oram.client.Test; + +import static org.junit.Assert.*; +import nankai.oram.client.PartitionClient; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class PartitionClientJUnitTest { + + PartitionClient cliORAM=new PartitionClient(); + @Before + public void setUp() throws Exception { + System.out.println("setUp"); + cliORAM.init(10240); + cliORAM.openConnection(); + + } + + @After + public void tearDown() throws Exception { + System.out.println("tearDown"); + cliORAM.closeConnection(); + } + + @Test + public void testInitORAM() { + if (!cliORAM.initORAM()) + fail("尚未实现"); + } + +} diff --git a/src/nankai/oram/client/Test/TestENC.java b/src/nankai/oram/client/Test/TestENC.java new file mode 100644 index 0000000..ee99e05 --- /dev/null +++ b/src/nankai/oram/client/Test/TestENC.java @@ -0,0 +1,62 @@ +package nankai.oram.client.Test; + +import java.security.NoSuchAlgorithmException; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.common.CommInfo; +import nankai.oram.common.SymmetricCypto; +import nankai.oram.common.Util; + +public class TestENC { + + + + public static void main(String[] args) { + KeyGenerator kg; + SecretKey userKey = null; + try { + kg = KeyGenerator.getInstance("AES"); + kg.init(128); + userKey = kg.generateKey(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + byte[] data=new byte[CommInfo.blockSize]; + for (int i=0;i0) realPos--; + int targetPos = realPos; + //psuedo_random_permute( levelnumbers1 + levelnumbers2, sfk, realPos); + //Util.fpeForPermution(realPos, sfk, levelnumbers1 + levelnumbers2); + + //System.out.println(" realPos: "+realPos+" targetPos: "+targetPos); + /********************************************************************************** + * read for shuffle + *******************************************************************************/ + /******************************* + * Generate the OFFSETs in shuffle cloud + * And the ids read in other cloud + * *****************************/ + byte[] ids = new byte[ n_levels * 4 ]; + byte[] idsOther = new byte[ n_levels * 4 ]; + int length = 0; + int lengthOther = 0; + for (int i=0;i 0) + { + cli[shuffleCloud].send( ids, length*4 ); + } + + byte[] cmd1=new byte[2]; + cmd1[0]=0; + cmd1[1]=0; + cli[shuffleCloud].sendAndReceive(cmd1, 2); + + /********************************************************************************** + * read for cloud + *******************************************************************************/ + cmd[0]=CommandType.readCloud; + System.arraycopy(bSessionID, 0, cmd, 1, 8); + Util.intToByte(cmd, 9, partition); + Util.intToByte(cmd, 13, targetPos); + Util.intToByte(cmd, 17, lengthOther); + Util.intToByte(cmd, 21, shuffleCloud); + + byte[] bData=new byte[CommInfo.blockSize]; + if (lengthOther==0) + { + cli[otherCloud].send(cmd, 25, null, 0, bData); + }else{ + // get the data + + cli[otherCloud].send(cmd, 25, idsOther, lengthOther*4, bData); + } + + + //generate the information for analysis + Util.readNumber ++; + Util.readbandwidth += 37 + 25+ (length+lengthOther)*4 + CommInfo.blockSize; + Util.cloudtocloud++; + + Util.cloudcloudbandwidth += (lengthOther + length + lengthOther) * CommInfo.blockSize ; + + + return bData; + } + + + public int psuedo_random_permute(int filledLevelLength, SecretKey sfk, int realPos) { + int[] shffule = new int[filledLevelLength]; + + for (int i = 0; i 0) + otherCloud =(cloud==0)?1:0; + /*************************************************** + * COMPUTE the range of the levels + * ********************************************/ + int begin = 0; + int end = (1 << (unfilledLevel + 1)) - 2; + boolean bSpecialCase = false; + if (unfilledLevel == -1){ + bSpecialCase = true; + //All Filled levels, special treatment + unfilledLevel = n_levels - 1; + end = this.n_capacity; + } + + for (int i=begin; i filledLevelLength-2) + { + unreadDataNumber=filledLevelLength-2; + //read the real block and then the dummy blocks + int pos = 0; + //first , real block + for (int level = 0; level < this.n_levels; level++) { + if (filled[level]) { + + begin = (1 << (level + 1)) - 2; + int datalen = 0; + if (level != n_levels - 1) { + datalen = 2 * (1 << level); + } else + datalen = top_level_len; + + for (int _id = begin; _id < begin + datalen; _id++) { + if (this.readFlag[_id] == false && this.blockIDs[_id]>=0) { + Util.intToByte(ids, pos * 4, _id); + pos++; + } + } + } else { + break; + } + } + //second , dummy block + for (int level = 0; level < this.n_levels; level++) { + if (filled[level]) { + + begin = (1 << (level + 1)) - 2; + int datalen = 0; + if (level != n_levels - 1) { + datalen = 2 * (1 << level); + } else + datalen = top_level_len; + + for (int _id = begin; _id < begin + datalen; _id++) { + if (pos>unreadDataNumber) + break; + if (this.readFlag[_id] == false && this.blockIDs[_id]<0) { + Util.intToByte(ids, pos * 4, _id); + pos++; + } + } + } else { + break; + } + } + + }else{ + int pos = 0; + for (int level = 0; level < this.n_levels; level++) { + if (filled[level]) { + + begin = (1 << (level + 1)) - 2; + int datalen = 0; + if (level != n_levels - 1) { + datalen = 2 * (1 << level); + } else + datalen = top_level_len; + + for (int _id = begin; _id < begin + datalen; _id++) { + if (this.readFlag[_id] == false) { + Util.intToByte(ids, pos * 4, _id); + pos++; + } + } + } else { + break; + } + } + } + + /********************************************** + * Send to server + * *****************************************/ + byte[] cmd1=new byte[25]; + cmd1[0]=CommandType.noticeWriteCloud; + Util.intToByte(cmd1, 1, partition); + Util.intToByte(cmd1, 5, cloud); + Util.intToByte(cmd1, 9, unfilledLevel); + Util.intToByte(cmd1, 13, filledLevelLength); + Util.intToByte(cmd1, 17, unreadDataNumber); + Util.intToByte(cmd1, 21, otherCloud); + + + + cli[cloud].send(cmd1, 25); + + cli[cloud].send(targetObj.value, CommInfo.blockSize ); + + + if (unreadDataNumber>0) + cli[cloud].send(ids, unreadDataNumber*4 ); + + //key? shuffle ?- for later + keys[unfilledLevel]=kg.generateKey(); + filled[unfilledLevel]=false; + + byte[] shufflekey = getKey(unfilledLevel);//Util.generateDummyData(MCloudCommInfo.keySize); + cli[cloud].send(shufflekey, 16); + + + + + //generate the information for analysis + Util.writeNumber ++; + Util.bandwidth += CommInfo.blockSize + 25 + unreadDataNumber*4 + CommInfo.keySize + 4*(filledLevelLength-unreadDataNumber-1); + if (otherCloud != cloud) { + Util.cloudtocloud++; + Util.cloudcloudbandwidth += (filledLevelLength) * CommInfo.blockSize ; + } + + + int[] bIDS = new int[filledLevelLength]; + bIDS[0]=targetObj.id; + for (int i=0;i=0) + { + blockIDs[_id] = bID; + //update the position map + pos_map[bID].cloud = otherCloud; //store other cloud + pos_map[bID].partition = this.partition; + pos_map[bID].level = unfilledLevel; + pos_map[bID].offset = i; + } + } + } + + + /*** + * Permute the blockIDs in the client based on the key + * @param shufflekey + */ + private void psuedo_random_permute(byte[] shufflekey, int filledLevelLength, int[] bIDS) { + Util.writeNumber = Util.writeNumber+1; + + +// for (int i = 0; i < filledLevelLength; i++) { +// System.out.println("i: "+i+" "+blockIDs[i]); +// } + + SecretKey sfk = new SecretKeySpec(shufflekey, "AES"); + + for (int i = 0; i < filledLevelLength; i++) { + int j = Util.fpeForPermution(i, sfk, filledLevelLength); + int t = bIDS[i]; + bIDS[i] = bIDS[j]; + bIDS[j] = t; + +// System.out.println("permute: "+i+" "+j); + } + } + + + public int nextDummy(int type, int level) + { + int begin = (1 << (level + 1)) - 2; + int end=0; + if (level != n_levels - 1) { + end = 2 *(1 << level); + } else end = top_level_len; + //compute the position in the position map + for (int i=nextDummy[level];i= 0) + continue; + byte[] iv = Util.generateIV(_id); + for (int j = 0; j < CommInfo.blockSize; j++) + xorZero[j] = 0; + +// // first onion encrypt userkey +// scp.initEnc(userKey, iv); +// scp.enc_decData(xorZero, CommInfo.blockSize); +// // second onion encrypt level key +// scp.initEnc(keys[levels[i]], null); +// scp.enc_decData(xorZero, CommInfo.blockSize); + + // XOR + for (int j = 0; j < CommInfo.blockSize; j++) + data[j] ^= xorZero[j]; + + } + +// // First onion decrypt by level key +// scp.initDec(keys[level], null); +// scp.enc_decData(data, CommInfo.blockSize); + + // Second, onion decrypt by the user key + subOram.decryptData(data); + } + return data ; + } + + public byte[] generateXORBlock(int p, int _id, SecretKey userKey) + { + //Encrypt the 0x00 default value by the userkey + byte[] data=new byte[CommInfo.blockSize]; + for (int i=0;i=0) + unreadRealDataNumber++; + } + + /********************************************** + * GEI the maxinum number of blocks in this level + * *****************************************/ + int filledLevelLength = 0; + if (unfilledLevel != n_levels - 1) { + filledLevelLength = 2 *(1 << unfilledLevel); + } else filledLevelLength = top_level_len; + + int dataNumber=unreadRealDataNumber; + + byte[] ids=new byte[dataNumber*4];//id in partition , for reading + int[] intIDs=new int[dataNumber];//id + byte[] levels=new byte[dataNumber];//store each id's level, for onion decryption + + int pos = 0; + for (int level = MCloudCommInfo.severBeginLevel; level < this.n_levels; level++) { + if (filled[level]) { + + begin = (1 << (level + 1)) - 2; + int datalen = 0; + if (level != n_levels - 1) { + datalen = 2 * (1 << level); + } else + datalen = top_level_len; + + for (int _id = begin; _id < begin + datalen; _id++) { + if (this.readFlag[_id] == false && blockIDs[_id]>=0 ) { + Util.intToByte(ids, pos * 4, _id); + levels[pos] = (byte) level; + intIDs[pos++] = blockIDs[_id]; + } + } + } else { + break; + } + } + + if (pos!=unreadRealDataNumber) + System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + + /**************************************** + * (1)Notice Shuffle , Send All the data, onionkeys in slots to the otherCloud + * + * CommandType: noticeShuffle + * Content: session ID | unfilled levels number | + * onion keys and slots data + * + * (2)Notice this cloud to send the data to the otherCloud for shuffling + * CommandType: writeCloud + * content: session ID | unfilled - partition | other cloud for shuffling | length of ids + * + * + * (3)Send back the shuffled Data -- cloud to cloud, but not the client + * CommandType: backData + * ************************************/ + + //System.out.println("write partition filledLevelLength:"+filledLevelLength+" dataNumber:"+dataNumber+" unreadRealDataNumber:"+unreadRealDataNumber+" bSessionID:"+bSessionID[0]); + + + int rndLength = filledLevelLength - dataNumber - 2*evictSize; + if (rndLength<0){ + System.out.println(" rndLength "+ rndLength +" filledLevelLength "+filledLevelLength+" dataNumber "+dataNumber+" evictSize "+evictSize ); + return; + } + + + /*********************** First command: noticeShuffle ***************************/ + byte[] cmd=new byte[29]; + cmd[0]=CommandType.noticeShuffle; + System.arraycopy(bSessionID, 0, cmd, 1, 8); + Util.intToByte(cmd, 9, partition); + Util.intToByte(cmd, 13, unfilledLevel); + Util.intToByte(cmd, 17, filledLevelLength); + Util.intToByte(cmd, 21, dataNumber); + Util.intToByte(cmd, 25, evictSize); + + + + cliOtherCloud.send(cmd, 29); + + + //send the ids to notice how to onion decryption and encryption + cliOtherCloud.send( levels, dataNumber ); + +// if (dataNumber*4>512) +// System.out.println("----512-----"); + /**************************************************** + * Send the data blocks to the shuffled cloud + * We sends them directly here, in fact, we can permute them before sending them + *********************************************/ + //send the slots data, the number is filled + for (int _id=0;_id=0) + { + //update the position map + pos_map[bID].cloud = cloud; + pos_map[bID].partition = this.partition; + pos_map[bID].level = unfilledLevel; + pos_map[bID].offset = i; + } + } + /*for (int i=filledLevelLength-1;i>=0;i--) + { + int bID=blockIDs[i]; + int _id = i+levelBegin; + if (bID>=0) + { + //update the position map + pos_map[bID].cloud = cloud; + pos_map[bID].partition = this.partition; + pos_map[bID].level = unfilledLevel; + pos_map[bID].offset = i; + } + blockIDs[_id] = bID; + readFlag[_id]=false; + }*/ + //update the status of consecutive levels + for (int i=0; i0) + realDataNumber++; + } + } + + + private void writeCase1(Queue slot, SecretKey userKey, int cloud, + int evictSize, int unfilledLevel) { + + + int filledLevelLength = 2 * (1 << unfilledLevel); + + // System.out.println(" writeCase1 "); + if (evictSize > filledLevelLength ) + System.out.println(" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "); + // shuffle in client and then write to cloud rightly + for (int _id = 0; _id < evictSize; _id++) { + SlotObject targetObj = (SlotObject) slot.poll(); + blockIDs[_id] = targetObj.id; + subOram.encryptData(targetObj.value); + System.arraycopy(targetObj.value, 0, s_buffer[_id], 0, + CommInfo.blockSize); + // System.out.println(" _id:"+_id+" value:"+targetObj.value[0]); + } + for (int _id = evictSize; _id < filledLevelLength; _id++) { + byte[] bDummyData = generateXORBlock(partition, _id, userKey); + System.arraycopy(bDummyData, 0, s_buffer[_id], 0, + CommInfo.blockSize); + // System.out.println(" _id:"+_id+" value:"+bDummyData[0]); + } + // shuffle first and then send them to the clouds + psuedo_random_permute(s_buffer, filledLevelLength); + + keys[unfilledLevel] = kg.generateKey(); + nextDummy[unfilledLevel] = 0; + filled[unfilledLevel] = true; + + // onion encrypt them using the level key + + int[] bIDS = new int[filledLevelLength]; + for (int i=0; i= 0) { + // update the position map + pos_map[bID].cloud = cloud; + pos_map[bID].partition = this.partition; + pos_map[bID].level = unfilledLevel; + pos_map[bID].offset = i; + } + blockIDs[_id] = bID; + readFlag[_id] = false; + } + + // update the status of consecutive levels + for (int i = 0; i < levelBegin; i++) { + blockIDs[i] = CommInfo.dummyID; + readFlag[i] = true; + } + + Util.writeNumber ++; + Util.bandwidth += filledLevelLength*CommInfo.blockSize ; + + //write to cloud + byte[] cmd1=new byte[13]; + cmd1[0]=CommandType.directWriteCloud; + Util.intToByte(cmd1, 1, partition); + Util.intToByte(cmd1, 5, unfilledLevel); + Util.intToByte(cmd1, 9, filledLevelLength); + + cli.send(cmd1, 13); + + + for (int _id = 0; _id < filledLevelLength; _id++) { + cli.send( s_buffer[_id], CommInfo.blockSize ); + } + //send over and receive + cmd1[0]=0; + cmd1[1]=0; + cli.sendAndReceive(cmd1, 2); + + //update all the real numbers + realDataNumber=0; + for (int i=levelBegin; i0) + realDataNumber++; + } + } + + + + private void psuedo_random_permute(byte[][] sBuffer, int len) { + Random rnd=new Random(); + int id =0; + byte[] bData=new byte[CommInfo.blockSize]; + for (int i = len- 1; i > 0; --i) { + int j = rnd.nextInt(i); + + System.arraycopy(sBuffer[i], 0, bData, 0, CommInfo.blockSize); + id=blockIDs[i]; + System.arraycopy(sBuffer[j], 0, sBuffer[i], 0, CommInfo.blockSize); + blockIDs[i] =blockIDs[j]; + System.arraycopy(bData, 0, sBuffer[j], 0, CommInfo.blockSize); + blockIDs[j]=id; + } + } + + /*** + * Permute the blockIDs in the client based on the key + * @param shufflekey + */ + private void psuedo_random_permute(byte[] shufflekey, int filledLevelLength) { + Util.writeNumber = Util.writeNumber+1; + + +// for (int i = 0; i < filledLevelLength; i++) { +// System.out.println("i: "+i+" "+blockIDs[i]); +// } + + SecretKey sfk = new SecretKeySpec(shufflekey, "AES"); + + for (int i = 0; i < filledLevelLength; i++) { + int j = Util.fpeForPermution(i, sfk, filledLevelLength); + int t = blockIDs[i]; + blockIDs[i] = blockIDs[j]; + blockIDs[j] = t; + +// System.out.println("permute: "+i+" "+j); + } + } + + + public int nextDummy(int type, int level) + { + int begin = (1 << (level + 1)) - 2; + int end=0; + if (level != n_levels - 1) { + end = 2 *(1 << level); + } else end = top_level_len; + //compute the position in the position map + for (int i=nextDummy[level];i= (partitions[p].top_level_len - 2*MCloudCommInfo.evictConditionSize) ) + p = rnd.nextInt(n_partitions); + } + + //generate a random cloud to do the shuffle operation + int otherCloud = rnd.nextInt(MCloudCommInfo.cloudNumber); + if (MCloudCommInfo.cloudNumber > 1){ + while (otherCloud == this.cloud) + otherCloud = rnd.nextInt(MCloudCommInfo.cloudNumber); + } + + + partitions[p].writePartition(slot, cli[cloud], otherCloud, cli[otherCloud], userKey, cloud); + } + + + + @Override + public byte[] readCloud(String key) { + return readCloud(Integer.parseInt(key)); + } + + + @Override + public byte[] readCloud(int id) { + /***************** + * If it is a dummy Block, random select a partition to read + * **********************/ + byte[] data = null; + int p = 0; + if (id<=CommInfo.dummyID) + { + Random rnd=new Random(); + p = rnd.nextInt(n_partitions); + }else{ + p = pos_map[id].partition; + } + if (p>=0){ + data = partitions[p].readPartition(id, userKey); + return data; + }else{ + return new byte[CommInfo.blockSize]; + } + } + + + + +} \ No newline at end of file diff --git a/src/nankai/oram/client/partition/Partition.java b/src/nankai/oram/client/partition/Partition.java new file mode 100644 index 0000000..c528b9c --- /dev/null +++ b/src/nankai/oram/client/partition/Partition.java @@ -0,0 +1,349 @@ +package nankai.oram.client.partition; + +/************* + * The data in a level of a partition is encrypted by the key for level + * + * Each data is included by BID+DATA + * BID = REALBLOCK? BLOCKID : - OFFSET + */ + +import java.security.NoSuchAlgorithmException; +import java.util.Random; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import nankai.oram.client.common.Position; +import nankai.oram.common.CommInfo; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.CommandType; +import nankai.oram.common.SymmetricCypto; +import nankai.oram.common.Util; + +public class Partition{ + public static int part=0; + int n_levels; + + int n_blocks; + int n_realBlocks_p;//the real number of blocks in a partition + int n_capacity;//the max capacity of a partition -- need the top level + int top_level_len;//the number of blocks in the top level + + int p = 0; + int blockIDs[];//all the blockIDs. When re-shuffle, the dummyIDs will be re-filled + int dummyNumbers[];//the dummy block numbers; When re-shuffle, the dummyIDs will be filled + int nextDummy[];//the dummy block counter; + boolean filled[];//filled level flag + boolean flag[];//read flag + SecretKey keys[];//level key for each partition + + + byte s_buffer[][];//shuffule buffer - a large memory + Position pos_map[];//position map + SocketClientUtil cli; + + byte cmdData[] = new byte[13]; + + public int realDataNumber = 0; + KeyGenerator kg; + public Partition(int nN, int n_partitions, Position posMap[], byte sBuffer[][], SocketClientUtil cLi) + { + s_buffer=sBuffer; + pos_map=posMap; + cli=cLi; + + n_realBlocks_p = (int) Math.ceil(((double) nN) / n_partitions); + n_blocks = n_realBlocks_p * n_partitions; + + n_levels = (int) (Math.log((double) n_realBlocks_p) / Math.log(2.0)) + 1; + n_capacity = (int) Math.ceil(CommInfo.capacity_parameter * n_realBlocks_p); + top_level_len = n_capacity - (1 << n_levels) + 2; + + p = part++; + flag=new boolean[n_capacity]; + keys=new SecretKey[n_levels]; + blockIDs=new int[n_capacity]; + nextDummy=new int[n_levels]; + dummyNumbers=new int[n_levels]; + filled=new boolean[n_levels]; + + for (int i=0;i=0) + realDataNumber++; + } + + Util.cloudcloudbandwidth += sbuffer_len*CommInfo.blockSize; + + Util.writeNumber ++; + Util.bandwidth += CommInfo.blockSize + sbuffer_len*4; + Util.cloudtocloud ++; + } + + private void psuedo_random_permute(byte[][] sBuffer, int len) { + Util.writeNumber = Util.writeNumber+1; + + Random rnd=new Random(); + byte[] bData=new byte[CommInfo.blockSize]; + for (int i = len- 1; i > 0; --i) { + int j = rnd.nextInt(i); +/* bData=sBuffer[i].clone(); + sBuffer[i] = sBuffer[j].clone(); + sBuffer[j] = bData.clone();*/ + System.arraycopy(sBuffer[i], 0, bData, 0, CommInfo.blockSize); + System.arraycopy(sBuffer[j], 0, sBuffer[i], 0, CommInfo.blockSize); + System.arraycopy(bData, 0, sBuffer[j], 0, CommInfo.blockSize); + } + } + + private int fetchLevel(int level, int length) { + /****************************** + * Compute the position of begin and end + * **********************************/ + SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize); + scp.initDec(keys[level], null); + + int begin = (1 << (level + 1)) - 2; + int level_len=0; + if (level != n_levels - 1) { + level_len = 2 *(1 << level); + } else level_len = top_level_len; + + int _id=0; + + for (int j=0; j=0) + { + readBlock(p, level, j, s_buffer[length]); + /************************** + * Decrypt it and judge whether it is a dummy block + * *************************/ + scp.enc_decData(s_buffer[length], CommInfo.blockSize); + length++; + } + + //reset the flag + flag[_id]=true; + } + return length; + } + + private void readBlock(int p, int level, int offset, byte[] recData) { + int begin = (1 << (level + 1)) - 2; + int _id = begin+offset; + cmdData[0]=CommandType.readBlock; + Util.intToByte(cmdData, 1, p); + + //reset the read flag as true + flag[_id]=true; + Util.intToByte(cmdData, 5, _id); + + cli.send(cmdData, 9, null, 0, recData); + + } + + public int nextDummy(int level) + { + int begin = (1 << (level + 1)) - 2; + int end=0; + if (level != n_levels - 1) { + end = 2 *(1 << level); + } else end = top_level_len; + //compute the position in the position map + for (int i=nextDummy[level];i 0) { +// out.write(sendData, 0, dataLen); +// out.flush(); + + if (dataLen<512) + { + out.write(sendData, 0, dataLen); + out.flush(); + }else{ + int num = dataLen / 512 ; + int leftLen = dataLen % 512; + int hasSend = 0; + for (int i=0;i0){ + out.write(sendData, hasSend, leftLen); + out.flush(); + } + } + /********************* + * Send them with different block + * *********************/ + } + + /************************* + * Receive the response + * ResponseType | len | data + * *********************/ + while (in.read(recvMsg, 0, 1024) > 0) { + break; + } + responseType=recvMsg[0]; + //System.out.println("server return:" + responseType); + if (responseType==ResponseType.wrong){ + System.out.println(cmdInfo[0]+" "+cmdLen+" "+dataLen+"........"); + + for (int i=0;i 0) { + break; + } + + if (retLen != CommInfo.blockSize) + System.out.println("Wrong length" ); + + if (receiveData!=null && retLen == CommInfo.blockSize) + System.arraycopy(recvMsg, 0, receiveData, 0, retLen); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public void send(byte[] sendData, int dataLen) { + try { +// out.write(sendData, 0, dataLen); +// out.flush(); + if (dataLen<512) + { + out.write(sendData, 0, dataLen); + out.flush(); + }else{ + int length = dataLen / 512; + int leftLen = dataLen % 512; + int pos = 0; + + for (int i = 0; i < length; i++) { + out.write(sendData, pos, 512); + out.flush(); + pos += 512; + } + if (leftLen > 0) { + out.write(sendData, pos, leftLen); + out.flush(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public int receiving(byte[] recvData, int len) { + int retLen = -1; + try { + retLen = in.read(recvData, 0, len) ; + } catch (IOException e) { + e.printStackTrace(); + } + return retLen; + } + + + public void sendAndReceive(byte[] cmdInfo, int cmdLen) { + try { + + out.write(cmdInfo, 0, cmdLen); + out.flush(); + + /************************* + * Receive the response + * ResponseType | len | data + * *********************/ + while (in.read(recvMsg, 0, 1024) > 0) { + break; + } + responseType=recvMsg[0]; + //System.out.println("server return:" + responseType); + if (responseType==ResponseType.wrong){ + System.out.println(cmdInfo[0]+" "+cmdLen+"........"); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/nankai/oram/common/SymmetricCypto.java b/src/nankai/oram/common/SymmetricCypto.java new file mode 100644 index 0000000..daa1d8b --- /dev/null +++ b/src/nankai/oram/common/SymmetricCypto.java @@ -0,0 +1,65 @@ +package nankai.oram.common; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; + +public class SymmetricCypto { + Cipher cp; + int keySize; + static final String CIPHER_ALGORITHM_CBC_NoPadding = "AES/CBC/NoPadding"; + + byte[] iv; + public SymmetricCypto(int keysize) + { + try { + cp=Cipher.getInstance(CIPHER_ALGORITHM_CBC_NoPadding); + keySize=keysize; + iv=new byte[16]; + for (int i=0;i<16;i++) + iv[i]=0; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } + } + + + public void initEnc(SecretKey sk, byte[] IV) { + try { + cp.init(Cipher.ENCRYPT_MODE, sk, new IvParameterSpec( (IV==null)?iv:IV )); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void initDec(SecretKey sk, byte[] IV) + { + try { + cp.init(Cipher.DECRYPT_MODE, sk, new IvParameterSpec( (IV==null)?iv:IV )); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void enc_decData(byte[] bData, int len) + { + int blockNumber = len/keySize; + for (int i=0;i> 8 & 0xff); + dest[pos+1] = (byte) (value >> 16 & 0xff); + dest[pos+0] = (byte) (value >> 24 & 0xff); + } + + public static int rand_int(int maxNum) + { + Random rnd=new Random(); + if (maxNum<=0) maxNum=1; + return Math.abs(rnd.nextInt(maxNum)); + } + + public static byte[] generateDummyData( int len) + { + byte[] bData=new byte[len]; +// Random rnd=new Random(); +// rnd.nextBytes(bData); + for (int i=0;i0){ + //the pos is cloud - 1 + int cloud = Integer.parseInt(args[0]); + MCloudServer.port=MCloudCommInfo.port[cloud-1]; + System.out.println("cloud "+cloud+" port:"+MCloudServer.port); + } + new MCloudServer(); + } + + +} + diff --git a/src/nankai/oram/server/NewMCloudServer.java b/src/nankai/oram/server/NewMCloudServer.java new file mode 100644 index 0000000..f4d751c --- /dev/null +++ b/src/nankai/oram/server/NewMCloudServer.java @@ -0,0 +1,60 @@ +package nankai.oram.server; + +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.server.mcloud.NewMCloudPartitionServerThread; +import nankai.oram.server.partition.PartitionServerThread; + +public class NewMCloudServer { + private int queueSize = 100; + private static int port = 2121; + public NewMCloudServer() { + try { + boolean listening = true; // 是否对客户端进行监听 + ServerSocket serverSocket = null; // 服务器端Socket对象 + try { + // 创建一个ServerSocket在端口2121监听客户请求 + serverSocket = new ServerSocket(); + + //关闭serverSocket时,立即释放serverSocket绑定端口以便端口重用,默认为false + serverSocket.setReuseAddress(true); + //accept等待连接超时时间为1000毫秒,默认为0,永不超时 + //serverSocket.setSoTimeout(10000); + //为所有accept方法返回的socket对象设置接收缓存区大小,单位为字节,默认值和操作系统有关 + serverSocket.setReceiveBufferSize(128*1024); + //设置性能参数,可设置任意整数,数值越大,相应的参数重要性越高(连接时间,延迟,带宽) + serverSocket.setPerformancePreferences(3, 2, 1); + //服务端绑定至端口,10为服务端连接请求队列长度 + serverSocket.bind(new InetSocketAddress(port), queueSize); + System.out.println("Server starts..." + port); + } catch (Exception e) { + System.out.println("Can not listen to. " + e); + } + + while (listening) { + // 监听到客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动之 + //new ServerThread(server.accept()).start(); + new NewMCloudPartitionServerThread(serverSocket.accept()).start(); + } + } catch (Exception e) { + System.out.println("Error.... " + e); + } + } + + public static void main(String[] args) { + /** + * To run in a computer to simulate the multiple servers, we use the parameters of main to tell the socket bind port + */ + if (args.length>0){ + //the pos is cloud - 1 + int cloud = Integer.parseInt(args[0]); + NewMCloudServer.port=MCloudCommInfo.port[cloud-1]; + System.out.println("cloud "+cloud+" port:"+NewMCloudServer.port); + } + new NewMCloudServer(); + } + + +} diff --git a/src/nankai/oram/server/ORAMServer.java b/src/nankai/oram/server/ORAMServer.java new file mode 100644 index 0000000..bfb3808 --- /dev/null +++ b/src/nankai/oram/server/ORAMServer.java @@ -0,0 +1,50 @@ +package nankai.oram.server; + +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +import nankai.oram.server.partition.PartitionServerThread; + +public class ORAMServer { + + private int queueSize = 10; + private int port = 2121; + public ORAMServer() { + try { + boolean listening = true; // 是否对客户端进行监听 + ServerSocket serverSocket = null; // 服务器端Socket对象 + try { + // 创建一个ServerSocket在端口2121监听客户请求 + serverSocket = new ServerSocket(); + + //关闭serverSocket时,立即释放serverSocket绑定端口以便端口重用,默认为false + serverSocket.setReuseAddress(true); + //accept等待连接超时时间为1000毫秒,默认为0,永不超时 + //serverSocket.setSoTimeout(10000); + //为所有accept方法返回的socket对象设置接收缓存区大小,单位为字节,默认值和操作系统有关 + serverSocket.setReceiveBufferSize(128*1024); + //设置性能参数,可设置任意整数,数值越大,相应的参数重要性越高(连接时间,延迟,带宽) + serverSocket.setPerformancePreferences(3, 2, 1); + //服务端绑定至端口,10为服务端连接请求队列长度 + serverSocket.bind(new InetSocketAddress(port), queueSize); + System.out.println("Server starts..."); + } catch (Exception e) { + System.out.println("Can not listen to. " + e); + } + + while (listening) { + // 监听到客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动之 + //new ServerThread(server.accept()).start(); + new PartitionServerThread(serverSocket.accept()).start(); + } + } catch (Exception e) { + System.out.println("Error.... " + e); + } + } + + public static void main(String[] args) { + // TODO 自动生成的方法存根 + new ORAMServer(); + } + +} diff --git a/src/nankai/oram/server/ServerThread.java b/src/nankai/oram/server/ServerThread.java new file mode 100644 index 0000000..17f2230 --- /dev/null +++ b/src/nankai/oram/server/ServerThread.java @@ -0,0 +1,75 @@ +package nankai.oram.server; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.common.CommInfo; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.SymmetricCypto; +import nankai.oram.server.partition.PartitionORAMServer; + +public class ServerThread extends Thread { + + Socket socket = null; // 保存与本线程相关的Socket对象 + byte recvCmd[]; + + public ServerThread(Socket socket) { + this.socket = socket; + recvCmd=new byte[1024]; + } + + public void run() { + DataInputStream in=null; + DataOutputStream out=null; + try { + + in=new DataInputStream(socket.getInputStream()); + out=new DataOutputStream(socket.getOutputStream()); + + // 由Socket对象得到输出流,并构造PrintWriter对象 + byte type=0; + int len=0; + + while (true) { + + for (int i = 0; i < 1024; i++) { + if ( (len = in.read(recvCmd, 0, 1024))>0) + ;//System.out.println("received"+len); + } + //System.out.println("over"+len); + break; +// type = 0; +// len = 0; +// while ((len = in.read(recvCmd, 0, 13)) > 0) { +// type = recvCmd[0]; +// break; +// } +// +// if (type == CommandType.testTime) { +// System.out.println("return - "); +// out.writeByte(ResponseType.normal); +// out.flush(); +// } + + } + + + } catch (Exception e) { + System.out.println("Error.?>>>>> " + e); + e.printStackTrace(); + }finally{ + try { + out.close(); // 关闭Socket输出流 + in.close();// 关闭Socket输入流 + socket.close(); // 关闭Socket + } catch (IOException e1) { + e1.printStackTrace(); + } + System.out.println("closing........ "); + } + } +} diff --git a/src/nankai/oram/server/SocketServer.java b/src/nankai/oram/server/SocketServer.java new file mode 100644 index 0000000..0519446 --- /dev/null +++ b/src/nankai/oram/server/SocketServer.java @@ -0,0 +1,50 @@ +package nankai.oram.server; + +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +import nankai.oram.server.partition.PartitionServerThread; + +public class SocketServer { + + private int queueSize = 10; + private int port = 2121; + public SocketServer() { + try { + boolean listening = true; // 是否对客户端进行监听 + ServerSocket serverSocket = null; // 服务器端Socket对象 + try { + // 创建一个ServerSocket在端口2121监听客户请求 + serverSocket = new ServerSocket(); + + //关闭serverSocket时,立即释放serverSocket绑定端口以便端口重用,默认为false + serverSocket.setReuseAddress(true); + //accept等待连接超时时间为1000毫秒,默认为0,永不超时 + //serverSocket.setSoTimeout(10000); + //为所有accept方法返回的socket对象设置接收缓存区大小,单位为字节,默认值和操作系统有关 + serverSocket.setReceiveBufferSize(128*1024); + //设置性能参数,可设置任意整数,数值越大,相应的参数重要性越高(连接时间,延迟,带宽) + serverSocket.setPerformancePreferences(3, 2, 1); + //服务端绑定至端口,10为服务端连接请求队列长度 + serverSocket.bind(new InetSocketAddress(port), queueSize); + System.out.println("Server starts..."+serverSocket.getInetAddress()); + + } catch (Exception e) { + System.out.println("Can not listen to. " + e); + } + + while (listening) { + // 监听到客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动之 + //new ServerThread(server.accept()).start(); + new ServerThread(serverSocket.accept()).start(); + } + } catch (Exception e) { + System.out.println("Error.... " + e); + } + } + + public static void main(String[] args) { + // TODO 自动生成的方法存根 + new SocketServer(); + } +} diff --git a/src/nankai/oram/server/mcloud/MCloudORAMserver.java b/src/nankai/oram/server/mcloud/MCloudORAMserver.java new file mode 100644 index 0000000..b3f2cd3 --- /dev/null +++ b/src/nankai/oram/server/mcloud/MCloudORAMserver.java @@ -0,0 +1,152 @@ +package nankai.oram.server.mcloud; + +import java.io.UnsupportedEncodingException; + +import nankai.oram.common.CommInfo; +import nankai.oram.common.MongDBUtil; +import nankai.oram.server.partition.PartitionORAMServer; + +import org.bson.Document; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; + +public class MCloudORAMserver { + public static MCloudORAMserver instance; + byte cloud; + boolean initFlag; + int N; + int n_levels; + int n_partitions; + int n_blocks; + int n_realBlocks_p;//the real number of blocks in a partition + int n_capacity;//the max capacity of a partition -- need the top level + public MongDBUtil dbUtil; + byte[] bBlockData; + + + byte s_buffer[][];//shuffule buffer - a large memory + + private MCloudORAMserver() + { + bBlockData=new byte[CommInfo.blockSize]; + initFlag=false; + dbUtil=new MongDBUtil(); + dbUtil.connect("localhost", 27017); + cloud = 0; + } + public static MCloudORAMserver getInstance() + { + if (instance==null) + instance=new MCloudORAMserver(); + return instance; + } + /** + * This function will create the database for the ORAM + */ + public boolean init(int paritions, int capacity, int levels, byte cloud) + { + if (initFlag) + return false; + n_partitions = paritions; + n_capacity = capacity; + n_levels = levels; + this.cloud = cloud; + + //Create DB and open DB + if (!dbUtil.createDB("MCloudPartitionORAM"+cloud)) + return false; + //init partitions: create the table/collection for the partitions + try { + initPartitions(); + } catch (UnsupportedEncodingException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + return false; + } + + initFlag=true; + return true; + } + + + public boolean openDB(byte cloud) + { + this.cloud=cloud; + if (!dbUtil.openDB("MCloudPartitionORAM"+cloud)) + return false; + return true; + } + + public boolean writeBlock(int p, int _id, byte[] blockData, int pos) throws UnsupportedEncodingException + { + System.arraycopy(blockData, pos, bBlockData, 0, CommInfo.blockSize); + + MongoCollection collection = dbUtil.getCollection("part_"+p); + + String str=new String(bBlockData, "ISO-8859-1"); + + collection.findOneAndReplace(new Document("_id", _id), new Document("_id", _id).append("data", str)); + + return true; + } + + + public boolean readBlock(int p, int _id, byte[] receiveData) { + boolean bError = false; + try{ + MongoCollection collection = dbUtil + .getCollection("part_" + p); + // Find the data and return them + + FindIterable findIterable = collection.find(new Document( + "_id", _id)); + MongoCursor mongoCursor = findIterable.iterator(); + if (mongoCursor.hasNext()) { + Document doc1 = mongoCursor.next(); + + String bData = (String) doc1.get("data"); + + byte[] bs = bData.getBytes("ISO-8859-1"); + + System.arraycopy(bs, 0, receiveData, 0, CommInfo.blockSize); + return true; + } + }catch(Exception ex) + { + bError=true; + ex.printStackTrace(); + }finally{ + if (bError) + System.out.println("!!!!!!!!!!!!!!!!!readBlock mongdbError,p:"+p+" _id:"+_id); + } + + return false; + } + + private void initPartitions() throws UnsupportedEncodingException + { + int i=0; + for (i=0;i collection = dbUtil.getCollection("part_"+i); + //Each level, there are max 2^i real blocks, but more than 2^i dummy blocks + for (int j = 0; j < n_capacity; j++) { + /*collection.insertOne(new Document("_id", j).append("data", + new String(bBlockData, "ISO-8859-1")));*/ + collection.insertOne(new Document("_id", j).append("data", + bBlockData )); + } + /*************************************** + * Each level, there are 2^(i+1) blocks + * ***********************************/ + + } + + } +} diff --git a/src/nankai/oram/server/mcloud/MCloudPartitionServerThread.java b/src/nankai/oram/server/mcloud/MCloudPartitionServerThread.java new file mode 100644 index 0000000..23dc22e --- /dev/null +++ b/src/nankai/oram/server/mcloud/MCloudPartitionServerThread.java @@ -0,0 +1,606 @@ +package nankai.oram.server.mcloud; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.common.CommInfo; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.Util; + +public class MCloudPartitionServerThread extends Thread { + + Socket socket = null; // 保存与本线程相关的Socket对象 + byte recvCmd[]; + byte recvMsg[]; + byte sendMsg[]; + MCloudORAMserver oram; + + public MCloudPartitionServerThread(Socket socket) { + this.socket = socket; + recvCmd = new byte[37]; + recvMsg = new byte[1024]; + sendMsg = new byte[1024]; + oram = MCloudORAMserver.getInstance(); + //System.out.println(" new connection ......... "); + } + + public void run() { + DataInputStream in = null; + DataOutputStream out = null; + try { + + in = new DataInputStream(socket.getInputStream()); + out = new DataOutputStream(socket.getOutputStream()); + + byte type = 0; + int len = 0; + + while (true) { + type = 0; + len = 0; + while ((len = in.read(recvCmd, 0, 1)) > 0) { + type = recvCmd[0]; +// System.out +// .println("-----------------------------------------------------------"); +// System.out.println("receive a command type:" + type + " len " +// + len); + break; + } + + //close the thread + if (type == CommandType.closeThread) + break; + + switch (type) { + case CommandType.openDB: + { + in.read(recvCmd, 1, 1); + oram.openDB(recvCmd[1]); + out.writeByte(ResponseType.normal); + out.flush(); + + break; + } + case CommandType.initORAM: { + len = in.read(recvCmd, 1, 13); + if (len != 13) { + System.out.println("initORAM error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else + initORAM(out); + break; + } + case CommandType.readCloud: { + len = in.read(recvCmd, 1, 24); + if (len != 24) { + System.out.println("readCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + readCloud(out, in); + } + break; + } + case CommandType.noticeWriteCloud: { + len = in.read(recvCmd, 1, 24); + // content: session ID | unfilled - partition | other cloud for shuffling | length of ids + if (len != 24) { + System.out.println("noticeWriteCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + noticeWriteCloud(out, in); + } + + break; + } + case CommandType.noticeShuffle: { + len = in.read(recvCmd, 1, 36); + // content: session ID | unfilled - partition | other cloud for shuffling | length of ids + if (len != 36) { + System.out.println("noticeWriteCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + noticeShuffle(out, in); + } + + break; + } + case CommandType.directWriteCloud:{ + len = in.read(recvCmd, 1, 12); + if (len != 12) { + System.out.println("directWriteCloud error data! " + len); + for (int i=0;i>>>> " + e); + e.printStackTrace(); + } finally { + try { + out.close(); // 关闭Socket输出流 + in.close();// 关闭Socket输入流 + socket.close(); // 关闭Socket + } catch (IOException e1) { + e1.printStackTrace(); + } + } + //System.out.println("closing............................ "); + } + + private void initORAM(DataOutputStream out) throws IOException { + /********* + * CMD 9, CMDTYPE | PARTITIONS | CAPACITY + * *********/ + //System.out.println("init oram"); + + int paritions = Util.byteToInt(recvCmd, 1, 4); + int capacity = Util.byteToInt(recvCmd, 5, 4); + int levels = Util.byteToInt(recvCmd, 9, 4); + byte cloud = recvCmd[13]; +// System.out.println("init paritions capacity:" + paritions + " " +// + capacity); + oram.init(paritions, capacity, levels, cloud); + +// System.out.println("init OK."); + out.writeByte(ResponseType.normal); + out.flush(); + } + + + private synchronized void shuffleData(DataOutputStream out, DataInputStream in ) + throws IOException { + + byte[] sessionID = new byte[8]; + + System.arraycopy(recvCmd, 1, sessionID, 0, 8); + int idsLen = Util.byteToInt(recvCmd, 9, 4); + + /************************************************************** + * Get the session Object, must be received, because client first send noticeShuffle, + * and then the target cloud sends the shuffled data + *************************************************************/ + SessionManager manager=SessionManager.getInstance(); + //System.out.print("3. ->shuffleData "); + SessionObject session = manager.getObject(sessionID); + if (session==null) + { + //create it + System.out.println("Cannot find the session OBJECT!!!!!!!!!!!!!!!!!!!!!!!"); + return; + //session=new SessionObject(sessionID); + } + + + int filledLevelLength = session.filledLevelLength; + /*********************************************** + * Receive the block data from other cloud + * + * Firstly, onion decrypt them + *******************************************/ + byte[] recBlcokData = new byte[CommInfo.blockSize]; + for (int i=0;i 0) { + if (in.read(ids, 0, length * 4) != length * 4) { + System.out.println("error 1"); + } + } + + + //System.out.println("readcloud - shuffleCloud:"+shuffleCloud+" session "+recvCmd[1]); + + SocketClientUtil SCU=new SocketClientUtil(MCloudCommInfo.ip[shuffleCloud], MCloudCommInfo.port[shuffleCloud]); + SCU.connect(); + byte[] cmd=new byte[13]; + cmd[0]=CommandType.shuffleData; + System.arraycopy(recvCmd, 1, cmd, 1, 8); + Util.intToByte(cmd, 9, length);// + + SCU.send(cmd, 13); + + byte[] bData = new byte[CommInfo.blockSize]; + + if (length > 0) { + for (int i = 0; i < length; i++) { + int _id = Util.byteToInt(ids, i * 4, 4); + + oram.readBlock(partition, _id, bData); + //System.out.println("_id: "+_id+" i: "+i+" "+bData[8]); + SCU.send(bData, CommInfo.blockSize); + } + } + + //Then, waiting for the response + byte[] backCmd=new byte[5]; + if (SCU.receiving(backCmd, 5)!=5 || backCmd[0]!=CommandType.backData) + System.out.println("wrong back command!"); + int len=Util.byteToInt(backCmd, 1, 4); + for (int i=0; inoticeShuffle "); + SessionObject session = new SessionObject(sessionID); + session.setSFKey(sfk); + + //receive the IDs + byte[] ids = new byte[idsLen*4]; + if (idsLen>0){ + // read all the ids + if (in.read(ids, 0, idsLen*4) <= 0) + System.out.println("ERROR read IDs data!!!!!!!!!!!!!!!!!!!!!!!!"); + }else{ + ;//System.out.println("ids Len is 0!!"); + } + + //read the block and set to buffer + session.createShuffle(levels); + byte[] bData = new byte[CommInfo.blockSize]; + for (int i=0;i 0) { +// if (in.read(ids, 0, unreadDataNumber * 4) != unreadDataNumber * 4) { +// System.out.println("error 4"); +// } + + int dataLen = unreadDataNumber*4; + if (dataLen<512){ + if (in.read(ids, 0, dataLen)!=dataLen) + System.out.println("ids Error!!!"); + }else{ + int num = dataLen / 512 ; + int leftLen = dataLen % 512; + int hasRead = 0; + for (int i=0;i0){ + if (in.read(ids, hasRead, leftLen)!=leftLen) + System.out.println("noticeShuffle leftLen Error!!!"); + } + } + + + + for (int i = 0; i < unreadDataNumber; i++) { + int _id = Util.byteToInt(ids, i * 4, 4); + + oram.readBlock(partition, _id, bData); + System.arraycopy(bData, 0, s_buffer[nowPos++], 0, + CommInfo.blockSize); + } + } + + + //generate dummy block + for (int i=nowPos; i collection = dbUtil.getCollection("part_"+p); + + String str=new String(bBlockData, "ISO-8859-1"); + + collection.findOneAndReplace(new Document("_id", _id), new Document("_id", _id).append("data", str)); + + return true; + } + + + public boolean readBlock(int p, int _id, byte[] receiveData) { + boolean bError = false; + try{ + MongoCollection collection = dbUtil + .getCollection("part_" + p); + // Find the data and return them + + FindIterable findIterable = collection.find(new Document( + "_id", _id)); + MongoCursor mongoCursor = findIterable.iterator(); + if (mongoCursor.hasNext()) { + Document doc1 = mongoCursor.next(); + + String bData = (String) doc1.get("data"); + + byte[] bs = bData.getBytes("ISO-8859-1"); + + System.arraycopy(bs, 0, receiveData, 0, CommInfo.blockSize); + return true; + } + }catch(Exception ex) + { + bError=true; + ex.printStackTrace(); + }finally{ + if (bError) + System.out.println("!!!!!!!!!!!!!!!!!readBlock mongdbError,p:"+p+" _id:"+_id); + } + + return false; + } + + private void initPartitions() throws UnsupportedEncodingException + { + int i=0; + for (i=0;i collection = dbUtil.getCollection("part_"+i); + //Each level, there are max 2^i real blocks, but more than 2^i dummy blocks + for (int j = 0; j < n_capacity; j++) { + /*collection.insertOne(new Document("_id", j).append("data", + new String(bBlockData, "ISO-8859-1")));*/ + collection.insertOne(new Document("_id", j).append("data", + bBlockData )); + } + /*************************************** + * Each level, there are 2^(i+1) blocks + * ***********************************/ + + } + + } + } diff --git a/src/nankai/oram/server/mcloud/NewMCloudPartitionServerThread.java b/src/nankai/oram/server/mcloud/NewMCloudPartitionServerThread.java new file mode 100644 index 0000000..d0c97e8 --- /dev/null +++ b/src/nankai/oram/server/mcloud/NewMCloudPartitionServerThread.java @@ -0,0 +1,640 @@ +package nankai.oram.server.mcloud; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +import javax.crypto.SecretKey; + +import nankai.oram.client.mCloud.MCloudCommInfo; +import nankai.oram.common.CommInfo; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.Util; + +public class NewMCloudPartitionServerThread extends Thread { + + Socket socket = null; // 保存与本线程相关的Socket对象 + byte recvCmd[]; + byte recvMsg[]; + byte sendMsg[]; + NewMCloudORAMserver oram; + + public NewMCloudPartitionServerThread(Socket socket) { + this.socket = socket; + recvCmd = new byte[29]; + recvMsg = new byte[1024]; + sendMsg = new byte[1024]; + oram = NewMCloudORAMserver.getInstance(); + //System.out.println(" new connection ......... "); + } + + public void run() { + DataInputStream in = null; + DataOutputStream out = null; + try { + + in = new DataInputStream(socket.getInputStream()); + out = new DataOutputStream(socket.getOutputStream()); + + byte type = 0; + int len = 0; + + while (true) { + type = 0; + len = 0; + while ((len = in.read(recvCmd, 0, 1)) > 0) { + type = recvCmd[0]; +// System.out +// .println("-----------------------------------------------------------"); +// System.out.println("receive a command type:" + type + " len " +// + len); + break; + } + + //close the thread + if (type == CommandType.closeThread) + break; + + switch (type) { + case CommandType.openDB: + { + in.read(recvCmd, 1, 1); + oram.openDB(recvCmd[1]); + out.writeByte(ResponseType.normal); + out.flush(); + + break; + } + case CommandType.initORAM: { + len = in.read(recvCmd, 1, 13); + if (len != 13) { + System.out.println("initORAM error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else + initORAM(out); + break; + } + case CommandType.readCloud: { + len = in.read(recvCmd, 1, 8); + if (len != 8) { + System.out.println("readCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + readCloud(out, in); + } + break; + } + case CommandType.noticeWriteCloud: { + len = in.read(recvCmd, 1, 21); + // content: session ID | unfilled - partition | other cloud for shuffling | length of ids + if (len != 21) { + System.out.println("noticeWriteCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + noticeWriteCloud(out, in); + } + + break; + } + case CommandType.directWriteCloud: + { + len = in.read(recvCmd, 1, 12); + // content: session ID | unfilled - partition | other cloud for shuffling | length of ids + if (len != 12) { + System.out.println("directWriteCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + directWriteCloud(out, in); + } + break; + } + case CommandType.noticeShuffle: { + len = in.read(recvCmd, 1, 28); + // content: session ID | unfilled - partition | other cloud for shuffling | length of ids + if (len != 28) { + System.out.println("noticeWriteCloud error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + noticeShuffle(out, in); + } + + break; + } + case CommandType.shuffleData:{ + len = in.read(recvCmd, 1, 12); + if (len != 12) { + System.out.println("shuffleData error data! " + len); + for (int i=0;i>>>> " + e); + e.printStackTrace(); + } finally { + try { + out.close(); // 关闭Socket输出流 + in.close();// 关闭Socket输入流 + socket.close(); // 关闭Socket + } catch (IOException e1) { + e1.printStackTrace(); + } + } + //System.out.println("closing............................ "); + } + + private void initORAM(DataOutputStream out) throws IOException { + /********* + * CMD 9, CMDTYPE | PARTITIONS | CAPACITY + * *********/ +// System.out.println("init oram"); + + int paritions = Util.byteToInt(recvCmd, 1, 4); + int capacity = Util.byteToInt(recvCmd, 5, 4); + int levels = Util.byteToInt(recvCmd, 9, 4); + byte cloud = recvCmd[13]; +// System.out.println("init paritions capacity:" + paritions + " " +// + capacity); + oram.init(paritions, capacity, levels, cloud); + +// System.out.println("init OK."); + out.writeByte(ResponseType.normal); + out.flush(); + } + + /** + * When receive this data, the cloud would read data and send them to the other cloud + * @param out + * @param in + * @throws IOException + */ + private void shuffleData(DataOutputStream out, DataInputStream in) + throws IOException { + /**************************************** + * (2)Send All the data, onionkeys in slots to the otherCloud + * + * CommandType: shuffleData + * Content: session ID | unfilled levels number | + * onion keys and slots data + * ************************************/ + + byte[] sessionID = new byte[8]; + + System.arraycopy(recvCmd, 1, sessionID, 0, 8); + int idsLen = Util.byteToInt(recvCmd, 9, 4); + + //System.out.println("4. shuffleData " + sessionID[0]); + /************************************************************** + * Get the session Object, must be received, because client first send noticeShuffle, + * and then the target cloud sends the shuffled data + *************************************************************/ + SessionManager manager=SessionManager.getInstance(); + SessionObject session = manager.getObject(sessionID); + if (session==null) + { + //create it + System.out.println("Cannot find the session OBJECT!!!!!!!!!!!!!!!!!!!!!!!"+sessionID[0]+" "+sessionID[5]); + return; + //session=new SessionObject(sessionID); + } + //verify the length + if (idsLen != session.idsLen) + System.out.println("wrong ID number!!!!!!!!!!!!!!!!!!!!!!! idsLen:"+idsLen+" "+session.idsLen); + + //System.out.println("shuffleData: idsLen "+idsLen); + + int filledLevelLength = session.filledLevelLength; + /*********************************************** + * Receive the block data from other cloud + * + * Firstly, onion decrypt them + *******************************************/ + byte[] recBlcokData = new byte[CommInfo.blockSize]; + for (int i=0;i0){ + // read all the ids +// if (in.read(levels, 0, idsLen) <= 0) +// System.out.println("ERROR read IDs data!!!!!!!!!!!!!!!!!!!!!!!!"); + + readSocketLongData(in, idsLen, levels); + + + }else{ + ;//System.out.println("ids Len is 0!!"); + } + session.setLevels(levels, idsLen); + + + //receive each data and buffer them + session.createShuffle(filledLevelLength); + byte[] recBlcokData = new byte[CommInfo.blockSize]; + for (int i=0;i< 2*evictSize ;i++) + { + if (in.read(recBlcokData, 0, CommInfo.blockSize) <= 0) { + System.out.println("ERROR read data!!!!!!!!!!!!!!!!!!!!!!!!"); + } + //System.out.println("i: "+i+ " "+recBlcokData[0]); + session.setBlockData(i, recBlcokData); + } + + /******************************************************* + * read the random value and generate the dummy data + ******************************************************/ + byte[] rnds=new byte[rndLength*4]; + { + + + readSocketLongData(in, rndLength*4, rnds); + + for (int i=0;i 0) { + + ids = new byte[idsLen*4]; + +// if (in.read(ids, 0, idsLen*4)!=idsLen*4) +// System.out.println("ids Error!!!"); + + readSocketLongData(in, idsLen*4, ids); + + + + }else{ + ;//System.out.println("data length is 0!"); + } + + + /************************ + * SEND COMMAND TO OTHER CLOUD + * ***************************/ + byte[] cmd=new byte[13]; + cmd[0]=CommandType.shuffleData; + System.arraycopy(sessionID, 0, cmd, 1, 8);//session ID + Util.intToByte(cmd, 9, idsLen);//idsLen + + SocketClientUtil SCU=new SocketClientUtil(MCloudCommInfo.ip[cloud], MCloudCommInfo.port[cloud]); + SCU.connect(); + +// System.out.println("Ready for shuffle data command sending!"); +// for (int i=0;i<13;i++) +// System.out.print(cmd[i]+" "); + SCU.send(cmd, 13); + byte[] bData = new byte[CommInfo.blockSize]; + for (int i = 0; i < idsLen; i++) { + int _id = Util.byteToInt(ids, i * 4, 4); +// System.out.println("read _id: "+_id+" partition: "+partition); + //IDS 4 id | 1 level + +// if (_id == 0) { +// System.out +// .println("noticeWriteCloud :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!idsLen!!!!!!" +// + idsLen); +// for (int z = 0; z < idsLen * 4; z++) +// System.out.print(ids[z] + " "); +// +// for (int z = 0; z < idsLen ; z++) +// { +// int _did = Util.byteToInt(ids, z * 4, 4); +// System.out.print(_did + " "); +// } +// } + + oram.readBlock(partition, _id, bData); + SCU.send(bData, CommInfo.blockSize); + } + + //Then, waiting for the response + byte[] backCmd=new byte[5]; + if (SCU.receiving(backCmd, 5)!=5 || backCmd[0]!=CommandType.backData) + System.out.println("wrong back command!"); + int length=Util.byteToInt(backCmd, 1, 4); + int beginID=(1 << (unfilledLevel + 1)) - 2; + for (int i=0;i0){ + if (in.read(ids, hasRead, leftLen)!=leftLen) + System.out.println("noticeWriteCloud leftLen Error!!!"); + } + } + } + + + private void readCloud(DataOutputStream out, DataInputStream in) + throws IOException { + /********* + * P + ID + * *********/ +// System.out.println("readCloud"); + + int p = Util.byteToInt(recvCmd, 1, 4); + int len = Util.byteToInt(recvCmd, 5, 4); // the next length of all the + // IDs + //System.out.println("readCloud p _id :" + p + " len: " + len); + + byte[] bData = new byte[CommInfo.blockSize]; + + if (len>0){ + byte[] ids = new byte[len * 4]; + + // read all the ids + while (in.read(ids, 0, len * 4) > 0) { + break; + } + + for (int i = 0; i < CommInfo.blockSize; i++) + bData[i] = 0; + + byte[] bRnd = new byte[CommInfo.blockSize]; + for (int i = 0; i < len; i++) { + int _id = Util.byteToInt(ids, i * 4, 4); + if (_id == 0) + System.out + .println("readCloud :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + oram.readBlock(p, _id, bRnd); + for (int j = 0; j < CommInfo.blockSize; j++) + bData[j] ^= bRnd[j]; + } + } + + out.writeByte(ResponseType.normalWithValue); + out.flush(); + out.write(bData, 0, CommInfo.blockSize); + out.flush(); + } + + +} diff --git a/src/nankai/oram/server/mcloud/SessionManager.java b/src/nankai/oram/server/mcloud/SessionManager.java new file mode 100644 index 0000000..fff2ebf --- /dev/null +++ b/src/nankai/oram/server/mcloud/SessionManager.java @@ -0,0 +1,45 @@ +package nankai.oram.server.mcloud; + +import java.util.Vector; + +public class SessionManager { + public static SessionManager instance; + + public Vector objects ; + public synchronized static SessionManager getInstance() + { + if (instance==null) + instance=new SessionManager(); + return instance; + } + + private SessionManager() + { + objects = new Vector(); + } + + public synchronized SessionObject getObject(byte[] sessionID) + { + SessionObject obj = null; + int size = objects.size(); + for (int i=0; i level:"+level+" pos:"+pos); +// scp.initDec(key[level], null); +// scp.enc_decData(bdata, CommInfo.blockSize); + + System.arraycopy(bdata, 0, shffule[pos], 0, CommInfo.blockSize); + } + + public void psuedo_random_permute() { + byte[] bData = new byte[CommInfo.blockSize]; + + +// for (int i = 0; i < filledLevelLength; i++) { +// System.out.println("i: "+i+" "+shffule[i][0]); +// } + + for (int i = 0; i collection = dbUtil.getCollection("part_"+p); + + String str=new String(bBlockData, "ISO-8859-1"); + + collection.findOneAndReplace(new Document("_id", _id), new Document("_id", _id).append("data", str)); + + return true; + } + + + public boolean readBlock(int p, int _id, byte[] receiveData) throws UnsupportedEncodingException { + MongoCollection collection = dbUtil + .getCollection("part_" + p); + // Find the data and return them + + FindIterable findIterable = collection.find(new Document( + "_id", _id)); + MongoCursor mongoCursor = findIterable.iterator(); + if (mongoCursor.hasNext()) { + Document doc1 = mongoCursor.next(); + + String bData = (String) doc1.get("data"); + + byte[] bs = bData.getBytes("ISO-8859-1"); + + System.arraycopy(bs, 0, receiveData, 0, CommInfo.blockSize); + return true; + } + + return false; + } + + private void initPartitions() throws UnsupportedEncodingException + { + int i=0; + for (i=0;i collection = dbUtil.getCollection("part_"+i); + //Each level, there are max 2^i real blocks, but more than 2^i dummy blocks + for (int j = 0; j < n_capacity; j++) { + /*collection.insertOne(new Document("_id", j).append("data", + new String(bBlockData, "ISO-8859-1")));*/ + collection.insertOne(new Document("_id", j).append("data", + bBlockData )); + } + /*************************************** + * Each level, there are 2^(i+1) blocks + * ***********************************/ + + } + } + + +} diff --git a/src/nankai/oram/server/partition/PartitionServerThread.java b/src/nankai/oram/server/partition/PartitionServerThread.java new file mode 100644 index 0000000..9268d21 --- /dev/null +++ b/src/nankai/oram/server/partition/PartitionServerThread.java @@ -0,0 +1,204 @@ +package nankai.oram.server.partition; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +import nankai.oram.common.CommInfo; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.Util; + +public class PartitionServerThread extends Thread { + + + Socket socket = null; // 保存与本线程相关的Socket对象 + byte recvCmd[]; + byte recvMsg[]; + byte sendMsg[]; + PartitionORAMServer oram; + + public PartitionServerThread(Socket socket) { + this.socket = socket; + recvCmd=new byte[13]; + recvMsg=new byte[10240]; + sendMsg=new byte[10240]; + oram=PartitionORAMServer.getInstance(); + } + + public void run() { + DataInputStream in=null; + DataOutputStream out=null; + try { + + in=new DataInputStream(socket.getInputStream()); + out=new DataOutputStream(socket.getOutputStream()); + + // 由Socket对象得到输出流,并构造PrintWriter对象 + byte type=0; + int len=0; + + while (true) + { + type=0; + len=0; + while ( (len = in.read(recvCmd, 0, 13)) >0) { + type = recvCmd[0]; +// System.out.println("-----------------------------------------------------------"); +// System.out.println("receive a command type:"+ type+" "+ recvCmd[1]); + break; + } + + if (type == CommandType.closeThread) + break; + + switch (type) + { + case CommandType.openDB: + { + System.out.println("open DB"); + if (oram.openDB()==false) + System.out.println("open DB ERROR"); + out.writeByte(ResponseType.normal); + out.flush(); + + break; + } + case CommandType.testTime: + { + out.writeByte(ResponseType.normal); + out.flush(); + break; + } + case CommandType.initORAM: + { + if (len!=5){ +// System.out.println("initORAM error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + }else + initORAM(out); + break; + } + case CommandType.readBlock: + { + if (len != 9) { + System.out.println("readBlock error data! " + len); + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + /************************************** + * partition+_id + * **********************************/ + readBlock(out); + } + break; + } + case CommandType.writeBlock: + { + if (len != 13) { + System.out.println("writeBlock error data! " + len); + + for (int i=0;i 0) { + break; + } + + for (int i=0;i<3;i++) + System.out.print(recvMsg[i]+" "); + System.out.println(); + + out.writeByte(ResponseType.wrong); + out.flush(); + } else { + while (in.read(recvMsg, 0, 10240) > 0) { + break; + } + /************************************** + * partition+_id+length+block + * **********************************/ + writeBlock(out); + } + break; + } + + } + + } + + + } catch (Exception e) { + System.out.println("Error.?>>>>> " + e); + e.printStackTrace(); + }finally{ + try { + out.close(); // 关闭Socket输出流 + in.close();// 关闭Socket输入流 + socket.close(); // 关闭Socket + } catch (IOException e1) { + e1.printStackTrace(); + } + System.out.println("closing........ "); + } + } + + private void initORAM(DataOutputStream out) throws IOException { + /********* + * LEN = 4, N value + * *********/ +// System.out.println("init oram"); + + int N = Util.byteToInt(recvCmd, 1, 4); +// System.out.println("init N blocks:" + N); + oram.init(N); + +// System.out.println("init OK."); + out.writeByte(ResponseType.normal); + out.flush(); + } + + private void readBlock(DataOutputStream out ) throws IOException { + /********* + * P + ID + * *********/ + //System.out.println("readBlock"); + + int p = Util.byteToInt(recvCmd, 1, 4); + int _id = Util.byteToInt(recvCmd, 5, 4); + //System.out.println("p _id :" + p + " " + _id ); + + oram.readBlock(p, _id, sendMsg); + + out.writeByte(ResponseType.normalWithValue); + out.flush(); + out.write(sendMsg, 0, CommInfo.blockSize); + //System.out.println("return back data:" + sendMsg[0]+" " +sendMsg[5]); + out.flush(); + } + + private void writeBlock(DataOutputStream out ) throws IOException { + + //System.out.println("writeBlock"); + + int p = Util.byteToInt(recvCmd, 1, 4); + int _id = Util.byteToInt(recvCmd, 5, 4); + int len = Util.byteToInt(recvCmd, 9, 4); + //System.out.println("p _id len:" + p + " " + _id + " " + // + len); + //System.out.println(recvMsg[0]+" "+recvMsg[1]+"........"); + if (len!=CommInfo.blockSize) + System.out.println("Error Length"); + + oram.writeBlock(p, _id, recvMsg, 0); + + //System.out.println("write OK."); + out.writeByte(ResponseType.normal); + out.flush(); + } +}