commit 340fecc4071ae9a33eba89dd9c05a5ea2ef06e72 Author: emigrantMuse Date: Sun Apr 16 01:49:52 2017 +0800 4.16 diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fceb480 --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + 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..0465a71 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ThinORAM + + + + + + 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..3a21537 --- /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.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +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.8 diff --git a/src/nankai/oram/client/MCloudCommInfo.java b/src/nankai/oram/client/MCloudCommInfo.java new file mode 100644 index 0000000..e06a0ff --- /dev/null +++ b/src/nankai/oram/client/MCloudCommInfo.java @@ -0,0 +1,29 @@ +package nankai.oram.client; + +public interface MCloudCommInfo { + + +// public static int severBeginLevel = 3;//the default level of each partition in the server +// public static int clientEndLevel = 2;//the default level of each partition in the client cache +// public static int evictConditionSize = 8;//1+2+4+8+16=31 +// public static int cloudNumber = 2; //the cloud number + +// public static int severBeginLevel = 4;//the default level of each partition in the server +// public static int clientEndLevel =3;//the default level of each partition in the client cache +// public static int evictConditionSize = 16;//1+2+4=6 +// public static int cloudNumber = 2; //the cloud number + + public static int severBeginLevel = 2;//the default level of each partition in the server + public static int clientEndLevel =1;//the default level of each partition in the client cache + public static int evictConditionSize = 4;//1+2+4=6 + public static int cloudNumber = 2; //the cloud number + +// public static int severBeginLevel = 5;//the default level of each partition in the server +// public static int clientEndLevel = 4;//the default level of each partition in the client cache +// public static int evictConditionSize = 32;//1+2+4+8=15 +// public static int cloudNumber = 2; //the cloud number + + //public static String[] ip={ "114.215.26.85", "114.215.26.85"}; + public static String[] ip={ "localhost", "localhost"}; + public static int[] port={ 2121, 2122}; +} diff --git a/src/nankai/oram/client/PartitionClient.java b/src/nankai/oram/client/PartitionClient.java new file mode 100644 index 0000000..da7ee29 --- /dev/null +++ b/src/nankai/oram/client/PartitionClient.java @@ -0,0 +1,280 @@ +package nankai.oram.client; + + +import java.security.NoSuchAlgorithmException; +import java.util.Enumeration; +import java.util.Hashtable; +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.partition.Partition; +import nankai.oram.common.CommInfo; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.Util; +import nankai.oram.interfaces.ORAM; + + +public class PartitionClient implements ORAM{ + + boolean initFlag; + int N; + int n_partitions; + 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 counter=0;//for sequneceEvict + + byte s_buffer[][];//shuffule buffer - a large memory + Position pos_map[];//position map + + /*************************************************/ + Queue 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/SubCloudThinORAM.java b/src/nankai/oram/client/SubCloudThinORAM.java new file mode 100644 index 0000000..f2ff9c2 --- /dev/null +++ b/src/nankai/oram/client/SubCloudThinORAM.java @@ -0,0 +1,178 @@ +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.ThinORAMClient; +import nankai.oram.client.common.Position; +import nankai.oram.client.common.SlotObject; +import nankai.oram.client.partition.Partition; +import nankai.oram.common.CommInfo; +import nankai.oram.common.SocketClientUtil; +import nankai.oram.common.CommandType; +import nankai.oram.common.ResponseType; +import nankai.oram.common.SymmetricCypto; +import nankai.oram.common.Util; +import nankai.oram.interfaces.MultiCloudORAM; +import nankai.oram.interfaces.ORAM; + +public class SubCloudThinORAM implements MultiCloudORAM { + + int cloud; + int n_partitions; + int n_capacity;//the max capacity of a partition -- need the top level + int n_levels; + int n_realBlocks_p;//the real number of blocks in a partition + int counter=0;//for sequneceEvict + ThinORAMPartition[] partitions; + Position pos_map[];//position map + SocketClientUtil[] cli; + + private SecretKey userKey; //First onion encryption Layer + byte s_buffer[][]; + + public SubCloudThinORAM(int npartitions, int realBlocks_p, int levels, int capacity, int c, Position posMap[], SocketClientUtil[] cLi,byte sBuffer[][]) + { + n_partitions=npartitions; + n_realBlocks_p=realBlocks_p; + n_levels=levels; + n_capacity=capacity; + cloud=c; + pos_map=posMap; + cli=cLi; + partitions=new ThinORAMPartition[n_partitions]; + s_buffer=sBuffer; + for (int i=0;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); + } + + public boolean canWrite() + { + int realnumber = 0; + for (int i=0;i ( (this.n_realBlocks_p * this.n_partitions * 11)/10 ) ) + return false; + return true; + } + + + @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/Test/TestReadWrite/ThinInitOram.java b/src/nankai/oram/client/Test/TestReadWrite/ThinInitOram.java new file mode 100644 index 0000000..c0b4c76 --- /dev/null +++ b/src/nankai/oram/client/Test/TestReadWrite/ThinInitOram.java @@ -0,0 +1,37 @@ +package nankai.oram.client.Test.TestReadWrite; + +import nankai.oram.client.ThinORAMClient; +import nankai.oram.client.PartitionClient; + +/** + * This is the init oram program + * Each test should after the initilization of ORAM + * @author Dell + * + */ + +public class ThinInitOram { + + public static void main(String[] args) { + + + ThinORAMClient oram=new ThinORAMClient(); + + //initialize the client + oram.init(40000); + oram.openConnection(); + + long testTime = -1; + long testDoneTime = -1; + testTime = System.currentTimeMillis(); //ms + //initalize the server + oram.initORAM(); + + testDoneTime = System.currentTimeMillis(); + double totalElapsedTime = (testDoneTime - testTime);// / 1000.0; + System.out.println("totalElapsedTime:"+totalElapsedTime); + + oram.closeConnection(); + + } +} diff --git a/src/nankai/oram/client/Test/TestReadWrite/ThinReadAndWrite.java b/src/nankai/oram/client/Test/TestReadWrite/ThinReadAndWrite.java new file mode 100644 index 0000000..1b2655b --- /dev/null +++ b/src/nankai/oram/client/Test/TestReadWrite/ThinReadAndWrite.java @@ -0,0 +1,391 @@ +package nankai.oram.client.Test.TestReadWrite; + +import java.util.Random; + +import nankai.oram.client.ThinORAMClient; +import nankai.oram.client.PartitionClient; +import nankai.oram.client.MCloudCommInfo; +import nankai.oram.common.CommInfo; +import nankai.oram.common.Util; + +public class ThinReadAndWrite { + + public static int N = 40000; + + public static void main(String[] args) { + + + //testRead(); + + + //testMultiWrite(); + + //testSameAccess(); + testRandomAccess(); + } + + private static void testMultiWrite() { + //testWrite(5); + testWrite(10); + testWrite(50); + testWrite(100); + testWrite(1000); + } + + private static void testRead() { + ThinORAMClient oram=new ThinORAMClient(); + //initialize the client + oram.init(N); + oram.openConnection(); + //initalize the server + oram.openORAM(); + + writeTheBlocksToApartition(oram, 1000); + + + readABlock(oram, 10); + readABlock(oram, 50); + readABlock(oram, 100); + readABlock(oram, 150); +// readABlock(oram, 40); +// readABlock(oram, 50); +// readABlock(oram, 60); +// readABlock(oram, 70); +// readABlock(oram, 80); +// readABlock(oram, 90); + //readABlock(oram, 70); + //readABlock(oram, 100); + //readABlock(oram, 150); + readABlock(oram, 250); + readABlock(oram, 500); + + oram.closeConnection(); + } + + /************************ + * After the initOram + * This test can be performed + * + * This test is used to test the execution time of random access, the number of shuffle between clouds and the write operation + **********************/ + private static void testRandomAccess() { + ThinORAMClient oram=new ThinORAMClient(); + //initialize the client + oram.init(N); + oram.openConnection(); + //initalize the server + oram.openORAM(); + + Util.debug = false; + + writeTheBlocks(oram, N); + + accessWithRandomStatus(oram, 50); + accessWithRandomStatus(oram, 100); + accessWithRandomStatus(oram, 500); accessWithRandomStatus(oram, 1000); +// + + oram.closeConnection(); + } + private static void testSameAccess() { + ThinORAMClient oram=new ThinORAMClient(); + //initialize the client + oram.init(N); + oram.openConnection(); + //initalize the server + oram.openORAM(); + + Util.debug = false; + + writeTheBlocks(oram, 10000); + + +// //accessWithSameStatus(oram, 5); +// accessWithSameStatus(oram, 10); +// //accessWithSameStatus(oram, 25); +// accessWithSameStatus(oram, 50); +// //accessWithSameStatus(oram, 75); + accessWithSameStatus(oram, 100); +// //accessWithSameStatus(oram, 150); +// accessWithSameStatus(oram, 200); + + accessWithSameStatus(oram, 500); + //accessWithSameStatus(oram, 500); + accessWithSameStatus(oram, 1000); + //accessWithSameStatus(oram, 2500); + accessWithSameStatus(oram, 5000); +// accessWithSameStatus(oram, 7500); accessWithSameStatus(oram, 10000); + +// writeTheBlocks(oram, 10000); +// +// accessWithSameStatus(oram, 5000); +// + + oram.closeConnection(); + } + + private static void writeTheBlocks(ThinORAMClient oram, int number) { + //write some data + + byte[] bData = new byte[CommInfo.blockSize]; + for (int id = 0; id < number; id++) { + for (int i = 0; i < CommInfo.blockSize; i++) + bData[i] = (byte) (i % 100); + //Util.intToByte(bData, 0, id); + oram.write(id, bData); + } + + bData = oram.read( 2 ); + System.out.println(" read 2:"+bData[2]); + } + + + private static void accessWithRandomStatus(ThinORAMClient oram, int number) + { + + + oram.clearSlot(); + + + Util.writeNumber = 0; + Util.readbandwidth =0; + Util.cloudcloudbandwidth =0; + Util.readNumber =0; + Util.bandwidth =0; + Util.cloudtocloud=0; + + long testTime = -1; + long testDoneTime = -1; + testTime = System.currentTimeMillis(); //ms + byte[] bData = new byte[CommInfo.blockSize]; + Random rnd=new Random(); + for (int id = 0; id < number ; id++) { + //System.out.println("read "+id); + int _id= rnd.nextInt(N); + oram.read(_id); + _id= rnd.nextInt(N); + oram.read(_id); + _id= rnd.nextInt(N); + //write to the cloud + for (int i = 0; i < CommInfo.blockSize; i++) + bData[i] = (byte) ((_id) % 100); + //System.out.println("write "+ (id+1) ); + oram.write(_id, bData); + } + testDoneTime = System.currentTimeMillis(); + double totalElapsedTime = (testDoneTime - testTime);// / 1000.0; + System.out.println("number is:"+number); + System.out.println("totalElapsedTime:"+totalElapsedTime); +// System.out.println("-----Shuffle numeber-----!"+Util.writeNumber+" Util.cloudtocloud:"+ Util.cloudtocloud); +// System.out.println("-----ORAM CACHE-----!"+ oram.getCacheSlotSize()); + System.out.println("-----writeNumb r ---- "+Util.writeNumber ); + System.out.println("-----cloudtocloud ---- "+Util.cloudtocloud ); + System.out.println("-----readNumber ---- "+Util.readNumber ); + System.out.println("-----bandwidth ---- "+ Util.bandwidth ); + System.out.println("-----cloudcloudbandwidth ---- "+Util.cloudcloudbandwidth ); + System.out.println("-----readbandwidth ---- "+Util.readbandwidth ); + + + + + bData = oram.read( 2 ); + System.out.println(" read 2:"+bData[2]); + bData = oram.read( 8 ); + System.out.println(" read 8:"+bData[2]); + + } + + private static void accessWithSameStatus(ThinORAMClient oram, int number) + { + + + oram.clearSlot(); + + + Util.writeNumber = 0; + Util.readbandwidth =0; + Util.cloudcloudbandwidth =0; + Util.readNumber =0; + Util.bandwidth =0; + Util.cloudtocloud=0; + + long testTime = -1; + long testDoneTime = -1; + testTime = System.currentTimeMillis(); //ms + byte[] bData = new byte[CommInfo.blockSize]; + for (int id = 0; id < number -10 ; id++) { + //System.out.println("read "+id); + oram.read(id); + //write to the cloud + for (int i = 0; i < CommInfo.blockSize; i++) + bData[i] = (byte) ((id+1) % 100); + //System.out.println("write "+ (id+1) ); + oram.write(id+1, bData); + } + testDoneTime = System.currentTimeMillis(); + double totalElapsedTime = (testDoneTime - testTime);// / 1000.0; + System.out.println("number is:"+number); + System.out.println("totalElapsedTime:"+totalElapsedTime); +// System.out.println("-----Shuffle numeber-----!"+Util.writeNumber+" Util.cloudtocloud:"+ Util.cloudtocloud); +// System.out.println("-----ORAM CACHE-----!"+ oram.getCacheSlotSize()); + System.out.println("-----writeNumber ---- "+Util.writeNumber ); + System.out.println("-----cloudtocloud ---- "+Util.cloudtocloud ); + System.out.println("-----readNumber ---- "+Util.readNumber ); + System.out.println("-----bandwidth ---- "+ Util.bandwidth ); + System.out.println("-----cloudcloudbandwidth ---- "+Util.cloudcloudbandwidth ); + System.out.println("-----readbandwidth ---- "+Util.readbandwidth ); + + + + + bData = oram.read( 2 ); + System.out.println(" read 2:"+bData[2]); + bData = oram.read( 8 ); + System.out.println(" read 8:"+bData[2]); + + } + + private static void writeTheBlocksToApartition(ThinORAMClient oram, int number) { + + Util.debug = true; //debug is ture, to write into a fix partiton + + Util.writeNumber = 0; + + long testTime = -1; + long testDoneTime = -1; + + testTime = System.currentTimeMillis(); //ms + byte[] bData = new byte[CommInfo.blockSize]; + for (int id = 0; id < number; id++) { + for (int i = 0; i < CommInfo.blockSize; i++) + bData[i] = (byte) (i % 128); + Util.intToByte(bData, 0, id); + oram.write(id, bData); + } + testDoneTime = System.currentTimeMillis(); + double totalElapsedTime = (testDoneTime - testTime);// / 1000.0; + System.out.println("totalElapsedTime:"+totalElapsedTime); + System.out.println("-----Shuffle numeber---- -"+Util.writeNumber+" cache size:"+oram.getCacheSlotSize()); + + byte[] bdata = oram.read(2); + System.out.println(" data :"+bdata[8]); + } + private static void readABlock(ThinORAMClient oram, int number) { + + Util.debug = true; + + Util.writeNumber = 0; + + long testTime = -1; + long testDoneTime = -1; + + testTime = System.currentTimeMillis(); //ms + + for (int i=0; i slots[]; + + SocketClientUtil[] cli; + + byte s_buffer[][]; + public ThinORAMClient() + { + 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 SubCloudThinORAM(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) + { + if (subORAMs[c].canWrite()) + 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= 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); + } + + + //update all the real numbers + realDataNumber=0; + int levelBegin = (1 << (MCloudCommInfo.severBeginLevel + 1)) - 2; + for (int i=levelBegin; i0 && readFlag[i]==false) + realDataNumber++; + } + 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 && readFlag[i]==false) + realDataNumber++; + } + + + if (realDataNumber > this.n_realBlocks_p) + realDataNumber=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 && readFlag[i]==false) + 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=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;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) { + 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/ThinPartitionServerThread.java b/src/nankai/oram/server/ThinPartitionServerThread.java new file mode 100644 index 0000000..ec1b6e9 --- /dev/null +++ b/src/nankai/oram/server/ThinPartitionServerThread.java @@ -0,0 +1,640 @@ +package nankai.oram.server; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +import javax.crypto.SecretKey; + +import nankai.oram.client.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 ThinPartitionServerThread extends Thread { + + Socket socket = null; // 保存与本线程相关的Socket对象 + byte recvCmd[]; + byte recvMsg[]; + byte sendMsg[]; + ThinORAMserver oram; + + public ThinPartitionServerThread(Socket socket) { + this.socket = socket; + recvCmd = new byte[29]; + recvMsg = new byte[1024]; + sendMsg = new byte[1024]; + oram = ThinORAMserver.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/ThinServer.java b/src/nankai/oram/server/ThinServer.java new file mode 100644 index 0000000..b4c2e30 --- /dev/null +++ b/src/nankai/oram/server/ThinServer.java @@ -0,0 +1,59 @@ +package nankai.oram.server; + +import java.net.InetSocketAddress; +import java.net.ServerSocket; + +import nankai.oram.client.MCloudCommInfo; + + +public class ThinServer { + private int queueSize = 100; + private static int port = 2121; + public ThinServer() { + 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 ThinPartitionServerThread(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]); + ThinServer.port=MCloudCommInfo.port[cloud-1]; + System.out.println("cloud "+cloud+" port:"+ThinServer.port); + } + new ThinServer(); + } + + +}