4.16
This commit is contained in:
commit
340fecc407
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1 @@
|
||||||
|
/bin/
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>ThinORAM</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -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
|
|
@ -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};
|
||||||
|
}
|
|
@ -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<SlotObject> 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<n_blocks; i++)
|
||||||
|
{
|
||||||
|
pos_map[i]=new Position();
|
||||||
|
}
|
||||||
|
slots=new Queue[n_partitions];
|
||||||
|
|
||||||
|
//randomly generate the keys for each level of each partition
|
||||||
|
for (int i = 0; i < n_partitions; i++)
|
||||||
|
{
|
||||||
|
slots[i]=new LinkedList<SlotObject>();
|
||||||
|
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; i<slots.length; i++)
|
||||||
|
{
|
||||||
|
ret += slots[i].size();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suggest the client to call this, when it will be closed
|
||||||
|
*/
|
||||||
|
public void clearSlot()
|
||||||
|
{
|
||||||
|
for (int i=0; i<slots.length; i++)
|
||||||
|
{
|
||||||
|
/**************
|
||||||
|
* Here, do not clear directly
|
||||||
|
* Just remove from the slot, but the data should always stored in the database
|
||||||
|
* So, we should update the position map
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (slots[i].size()>0){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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<n_partitions;i++)
|
||||||
|
{
|
||||||
|
partitions[i]=new ThinORAMPartition(realBlocks_p, levels, posMap, cLi[cloud], this,s_buffer);
|
||||||
|
partitions[i].partition=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyGenerator kg;
|
||||||
|
try {
|
||||||
|
kg = KeyGenerator.getInstance("AES");
|
||||||
|
kg.init(128);
|
||||||
|
userKey = kg.generateKey();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void encryptData(byte[] data) {
|
||||||
|
// SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
// scp.initEnc(this.userKey, null);
|
||||||
|
// scp.enc_decData(data, CommInfo.blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decryptData(byte[] data) {
|
||||||
|
// SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
// scp.initDec(this.userKey, null);
|
||||||
|
// scp.enc_decData(data, CommInfo.blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean initORAM()
|
||||||
|
{
|
||||||
|
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) this.cloud;
|
||||||
|
|
||||||
|
cli[cloud].send( cmd, 14, null , 0, null);
|
||||||
|
|
||||||
|
return cli[cloud].responseType!=ResponseType.wrong;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean openORAM()
|
||||||
|
{
|
||||||
|
byte cmd[]=new byte[2];
|
||||||
|
cmd[0]=CommandType.openDB;
|
||||||
|
cmd[1]=(byte) this.cloud;
|
||||||
|
|
||||||
|
cli[cloud].send( cmd, 2, null , 0, null);
|
||||||
|
|
||||||
|
return cli[cloud].responseType!=ResponseType.wrong;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeCloud(Queue slot) {
|
||||||
|
/*****************
|
||||||
|
* Random select a partition
|
||||||
|
*
|
||||||
|
* Select another cloud to do the shuffle operation
|
||||||
|
* *********************/
|
||||||
|
|
||||||
|
//System.out.println("writeCloud begin");
|
||||||
|
Random rnd=new Random();
|
||||||
|
int p = 1;//rnd.nextInt(n_partitions);
|
||||||
|
if (Util.debug == false){
|
||||||
|
p = rnd.nextInt(n_partitions);
|
||||||
|
//not write to the partition with more than the pre-defined real blocks
|
||||||
|
while ( partitions[p].realDataNumber >= (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_partitions; i++)
|
||||||
|
{
|
||||||
|
realnumber += this.partitions[i].realDataNumber;
|
||||||
|
}
|
||||||
|
if (realnumber> ( (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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<number;i++)
|
||||||
|
{
|
||||||
|
oram.read(oram.getIDinDB() );
|
||||||
|
}
|
||||||
|
|
||||||
|
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+" cache size:"+oram.getCacheSlotSize());
|
||||||
|
|
||||||
|
byte[] bdata = oram.read(2);
|
||||||
|
System.out.println(" data :"+bdata[8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void access(int number)
|
||||||
|
{
|
||||||
|
ThinORAMClient oram=new ThinORAMClient();
|
||||||
|
//initialize the client
|
||||||
|
oram.init(N);
|
||||||
|
oram.openConnection();
|
||||||
|
//initalize the server
|
||||||
|
oram.openORAM();
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
oram.read(id);
|
||||||
|
oram.write(id+1, 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());
|
||||||
|
|
||||||
|
oram.closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the special write to a fix partition
|
||||||
|
*
|
||||||
|
* if Util.debug set true, fix partition
|
||||||
|
* For a fix partition, test the number less than 1100
|
||||||
|
* but if false, random partition
|
||||||
|
*/
|
||||||
|
private static void testWrite(int number) {
|
||||||
|
ThinORAMClient oram=new ThinORAMClient();
|
||||||
|
//initialize the client
|
||||||
|
oram.init(N);
|
||||||
|
oram.openConnection();
|
||||||
|
//initalize the server
|
||||||
|
oram.openORAM();
|
||||||
|
//write some data
|
||||||
|
|
||||||
|
Util.debug = true;
|
||||||
|
Util.writeNumber = 0;
|
||||||
|
Util.readbandwidth =0;
|
||||||
|
Util.cloudcloudbandwidth =0;
|
||||||
|
Util.readNumber =0;
|
||||||
|
Util.bandwidth =0;
|
||||||
|
Util.cloudtocloud=0;
|
||||||
|
|
||||||
|
byte[] bData = new byte[CommInfo.blockSize];
|
||||||
|
|
||||||
|
System.out.println("number is:"+number);
|
||||||
|
long testTime = -1;
|
||||||
|
long testTime1 = -1;
|
||||||
|
long testDoneTime = -1;
|
||||||
|
long testDoneTime1 = -1;
|
||||||
|
testTime = System.currentTimeMillis(); //ms
|
||||||
|
testTime1 = System.nanoTime();//ns
|
||||||
|
|
||||||
|
for (int id = 0; id < number; id++) {
|
||||||
|
for (int i = 0; i < CommInfo.blockSize; i++)
|
||||||
|
bData[i] = (byte) (id % 100);
|
||||||
|
oram.write(id, bData);
|
||||||
|
}
|
||||||
|
|
||||||
|
testDoneTime = System.currentTimeMillis();
|
||||||
|
testDoneTime1 = System.nanoTime();
|
||||||
|
double totalElapsedTime = (testDoneTime - testTime);// / 1000.0;
|
||||||
|
|
||||||
|
double totalElapsedTime1 = (testDoneTime1 - testTime1);// / 1000.0;
|
||||||
|
System.out.println("totalElapsedTime:"+totalElapsedTime);
|
||||||
|
// System.out.println("totalElapsedTime222:"+totalElapsedTime1);
|
||||||
|
|
||||||
|
System.out.println("-----cloudtocloud ---- "+Util.cloudtocloud );
|
||||||
|
System.out.println("-----writeNumber ---- "+Util.writeNumber );
|
||||||
|
System.out.println("-----bandwidth ---- "+Util.bandwidth );
|
||||||
|
System.out.println("-----cloudcloudbandwidth ---- "+Util.cloudcloudbandwidth );
|
||||||
|
System.out.println("-----readNumber ---- "+Util.readNumber );
|
||||||
|
System.out.println("-----readbandwidth ---- "+Util.readbandwidth );
|
||||||
|
|
||||||
|
byte[] data = oram.read(8);
|
||||||
|
System.out.println("-----read 8--------- : " + data[8]);
|
||||||
|
data = oram.read(9);
|
||||||
|
System.out.println("-----read 9--------- : " + data[8]);
|
||||||
|
|
||||||
|
oram.closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,324 @@
|
||||||
|
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.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 ThinORAMClient implements ORAM{
|
||||||
|
|
||||||
|
|
||||||
|
boolean initFlag;
|
||||||
|
SubCloudThinORAM[] subORAMs;
|
||||||
|
|
||||||
|
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<SlotObject> 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<n_blocks; i++)
|
||||||
|
{
|
||||||
|
pos_map[i]=new Position();
|
||||||
|
}
|
||||||
|
slots=new Queue[MCloudCommInfo.cloudNumber];
|
||||||
|
subORAMs=new SubCloudThinORAM[MCloudCommInfo.cloudNumber];
|
||||||
|
s_buffer=new byte[MCloudCommInfo.evictConditionSize*3][CommInfo.blockSize];//the real value is evicCondition*2
|
||||||
|
|
||||||
|
//randomly generate the keys for each level of each partition
|
||||||
|
for (int i = 0; i < MCloudCommInfo.cloudNumber; i++)
|
||||||
|
{
|
||||||
|
slots[i]=new LinkedList<SlotObject>();
|
||||||
|
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; i<slots.length; i++)
|
||||||
|
{
|
||||||
|
ret += slots[i].size();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSlot()
|
||||||
|
{
|
||||||
|
for (int i=0; i<slots.length; i++)
|
||||||
|
{
|
||||||
|
/**************
|
||||||
|
* Here, do not clear directly
|
||||||
|
* Just remove from the slot, but the data should always stored in the database
|
||||||
|
* So, we should update the position map
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (slots[i].size()>0)
|
||||||
|
subORAMs[i].writeCloud(slots[i]);
|
||||||
|
slots[i].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIDinDB()
|
||||||
|
{
|
||||||
|
for (int i=0;i<n_blocks; i++)
|
||||||
|
{
|
||||||
|
if (pos_map[i].partition != -1 )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,716 @@
|
||||||
|
package nankai.oram.client;
|
||||||
|
|
||||||
|
/*************
|
||||||
|
* 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.Queue;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import nankai.oram.client.common.Position;
|
||||||
|
import nankai.oram.client.common.SlotObject;
|
||||||
|
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 ThinORAMPartition{
|
||||||
|
public static int part=0;
|
||||||
|
int n_levels;
|
||||||
|
|
||||||
|
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 partition = 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 readFlag[];//read flag
|
||||||
|
SecretKey keys[];//level key for each partition
|
||||||
|
|
||||||
|
byte s_buffer[][];
|
||||||
|
|
||||||
|
Position pos_map[];//position map
|
||||||
|
SocketClientUtil cli;
|
||||||
|
|
||||||
|
SubCloudThinORAM subOram;
|
||||||
|
|
||||||
|
KeyGenerator kg;
|
||||||
|
|
||||||
|
public int realDataNumber = 0;
|
||||||
|
|
||||||
|
public ThinORAMPartition(int realBlocks_p, int levels, Position posMap[], SocketClientUtil cLi, SubCloudThinORAM soram,byte sBuffer[][])
|
||||||
|
{
|
||||||
|
subOram=soram;
|
||||||
|
pos_map=posMap;
|
||||||
|
cli=cLi;
|
||||||
|
s_buffer = sBuffer;
|
||||||
|
n_realBlocks_p = realBlocks_p;
|
||||||
|
|
||||||
|
n_levels = levels;
|
||||||
|
n_capacity = (int) Math.ceil(CommInfo.capacity_parameter * n_realBlocks_p);
|
||||||
|
top_level_len = n_capacity - (1 << n_levels) + 2;
|
||||||
|
|
||||||
|
readFlag=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<n_levels;i++)
|
||||||
|
{
|
||||||
|
dummyNumbers[i]=0;
|
||||||
|
nextDummy[i]=0;
|
||||||
|
filled[i]=false;
|
||||||
|
}
|
||||||
|
for (int i=0;i<n_capacity;i++)
|
||||||
|
{
|
||||||
|
readFlag[i]=true;
|
||||||
|
blockIDs[i]=CommInfo.dummyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
initKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initKeys()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
kg = KeyGenerator.getInstance("AES");
|
||||||
|
kg.init(128);
|
||||||
|
for (int j = 0; j < n_levels; j++)
|
||||||
|
keys[j] = kg.generateKey();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getKey(int pos)
|
||||||
|
{
|
||||||
|
return keys[pos].getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] readPartition(int block_id, SecretKey userKey) {
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* Gnerate the OFFSETs
|
||||||
|
*
|
||||||
|
* Length + ID1 ...... + ID2......
|
||||||
|
* *****************************/
|
||||||
|
byte[] data = new byte[CommInfo.blockSize];
|
||||||
|
byte[] xorZero = new byte[CommInfo.blockSize];
|
||||||
|
byte[] ids = new byte[ n_levels * 4 ];
|
||||||
|
int[] levels = new int[n_levels];
|
||||||
|
int level = -1;
|
||||||
|
if (block_id!=CommInfo.dummyID)
|
||||||
|
level = pos_map[block_id].level;
|
||||||
|
int length = 0;
|
||||||
|
int realDataID = -1;
|
||||||
|
for (int i=MCloudCommInfo.severBeginLevel;i<n_levels;i++)
|
||||||
|
{
|
||||||
|
if (filled[i])
|
||||||
|
{
|
||||||
|
int _id = (1 << (i + 1)) - 2;
|
||||||
|
|
||||||
|
if (level==i && block_id!=CommInfo.dummyID)
|
||||||
|
{
|
||||||
|
_id += pos_map[block_id].offset;
|
||||||
|
realDataID = _id;
|
||||||
|
}else{
|
||||||
|
// not in this level, to read a dummy block, get the dummy offset
|
||||||
|
int dID=nextDummy(0, i);
|
||||||
|
if (dID == -1) // There is no dummy block can be read
|
||||||
|
continue;
|
||||||
|
_id += dID;//nextDummy(i);
|
||||||
|
}
|
||||||
|
readFlag[_id]=true;
|
||||||
|
Util.intToByte(ids, length*4, _id);
|
||||||
|
levels[length] = i;
|
||||||
|
length ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (length==0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
* Send to the cloud
|
||||||
|
*
|
||||||
|
* Command: readCloud
|
||||||
|
* content: partition + length
|
||||||
|
* offsets
|
||||||
|
* **************************/
|
||||||
|
//System.out.println("read partition length:"+length);
|
||||||
|
byte[] cmd=new byte[9];
|
||||||
|
cmd[0]=CommandType.readCloud;
|
||||||
|
Util.intToByte(cmd, 1, partition);
|
||||||
|
Util.intToByte(cmd, 5, length);
|
||||||
|
|
||||||
|
cli.send(cmd, 9, ids, length*4, data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Util.readbandwidth += 9+length*4+CommInfo.blockSize; //
|
||||||
|
Util.readNumber ++ ; //
|
||||||
|
/*************************************
|
||||||
|
* Decrypt Data based on XOR technique
|
||||||
|
*
|
||||||
|
* Enc-level-key and Enc-enc-key
|
||||||
|
* **********************************/
|
||||||
|
if (block_id != CommInfo.dummyID) {
|
||||||
|
SymmetricCypto scp = new SymmetricCypto(CommInfo.keySize);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
// XOR the data 000000
|
||||||
|
int _id = Util.byteToInt(ids, i * 4, 4);
|
||||||
|
if (_id >= 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; i<this.n_capacity; i++)
|
||||||
|
{
|
||||||
|
if (blockIDs[i]>0 && 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<CommInfo.blockSize;i++)
|
||||||
|
{
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
/****************************
|
||||||
|
* The first 4 bytes is the dummmyID and the random value, to make sure it is less than 0
|
||||||
|
*
|
||||||
|
* But now, to simplify the implementation, we ignore the random value for the same 0000000
|
||||||
|
* ******************************/
|
||||||
|
int dummyID = CommInfo.dummyID - Util.rand_int(n_capacity);
|
||||||
|
blockIDs[_id]=dummyID;
|
||||||
|
|
||||||
|
// byte[] iv = Util.generateIV(dummyID);
|
||||||
|
|
||||||
|
//encrypt
|
||||||
|
// SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
// scp.initEnc(userKey, iv);
|
||||||
|
// scp.enc_decData(data, CommInfo.blockSize);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePartition(Queue slot, SocketClientUtil cli, int otherCloud, SocketClientUtil cliOtherCloud, SecretKey userKey, int cloud)
|
||||||
|
{
|
||||||
|
//System.out.println("write begin!!");
|
||||||
|
int evictSize = MCloudCommInfo.evictConditionSize;
|
||||||
|
if (slot.size()<evictSize) {
|
||||||
|
evictSize = slot.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int unfilledLevel = -1;
|
||||||
|
for (int i = MCloudCommInfo.severBeginLevel; i < this.n_levels; i++) {
|
||||||
|
if (!filled[i]) {
|
||||||
|
unfilledLevel = i ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (unfilledLevel == MCloudCommInfo.severBeginLevel){
|
||||||
|
//CASE 2
|
||||||
|
writeCase1(slot, userKey, cloud, evictSize, unfilledLevel);
|
||||||
|
}else{
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
writeCase2(slot, cli, otherCloud, cliOtherCloud, userKey,
|
||||||
|
cloud, evictSize, unfilledLevel);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("error!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.out.println("write ok!!");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void writeCase2(Queue slot, SocketClientUtil cli, int otherCloud,
|
||||||
|
SocketClientUtil cliOtherCloud, SecretKey userKey, int cloud,
|
||||||
|
int evictSize, int unfilledLevel) {
|
||||||
|
// System.out.println(" writeCase2 ");
|
||||||
|
|
||||||
|
byte[] bSessionID = Util.generateSessionData(8);
|
||||||
|
int unreadRealDataNumber = 0;
|
||||||
|
/***************************************************
|
||||||
|
* COMPUTE the range of the levels
|
||||||
|
* ********************************************/
|
||||||
|
int begin = (1 << (MCloudCommInfo.severBeginLevel + 1)) - 2;
|
||||||
|
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<end; i++)
|
||||||
|
if (readFlag[i] == false)
|
||||||
|
{
|
||||||
|
if (blockIDs[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<evictSize;_id++)
|
||||||
|
{
|
||||||
|
SlotObject targetObj = (SlotObject)slot.poll();
|
||||||
|
blockIDs[_id]=targetObj.id;
|
||||||
|
subOram.encryptData(targetObj.value);
|
||||||
|
cliOtherCloud.send( targetObj.value, CommInfo.blockSize );
|
||||||
|
//System.out.println(" _id:"+_id+" value:"+targetObj.value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int _id = evictSize; _id < 2*evictSize; _id++) {
|
||||||
|
byte[] bDummyData = generateXORBlock(partition, _id, userKey);
|
||||||
|
cliOtherCloud.send( bDummyData, CommInfo.blockSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
* generate random value for dummy blocks
|
||||||
|
* **************************************/
|
||||||
|
//generate random value
|
||||||
|
Random rnd=new Random();
|
||||||
|
|
||||||
|
int[] rnds=new int[rndLength];
|
||||||
|
byte[] rndBytes=new byte[rndLength*4];
|
||||||
|
for (int i=0; i<rndLength; i++)
|
||||||
|
{
|
||||||
|
rnds[i]= - rnd.nextInt( this.n_capacity ); //
|
||||||
|
blockIDs[ i+2*evictSize ] = rnds[i];
|
||||||
|
Util.intToByte(rndBytes, i*4, rnds[i]);
|
||||||
|
}
|
||||||
|
for (int _id=0;_id<dataNumber;_id++)
|
||||||
|
{
|
||||||
|
blockIDs[_id+2*evictSize+rndLength]=intIDs[_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cliOtherCloud.send(rndBytes, rndLength*4);
|
||||||
|
|
||||||
|
//send the onion keys
|
||||||
|
/********************************************************************
|
||||||
|
* Notice that: must send the unfilledlevel key to the server,
|
||||||
|
* because the special case, the unfilled level is the top level, the onion decryption will be used
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
Util.bandwidth += rndLength*4 + MCloudCommInfo.evictConditionSize*CommInfo.blockSize + (unfilledLevel-MCloudCommInfo.severBeginLevel+1)*CommInfo.keySize;
|
||||||
|
|
||||||
|
Util.writeNumber ++;
|
||||||
|
|
||||||
|
Util.cloudtocloud++;
|
||||||
|
Util.cloudcloudbandwidth += (filledLevelLength) * CommInfo.blockSize + dataNumber*CommInfo.blockSize;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=MCloudCommInfo.severBeginLevel; i<=unfilledLevel; i++)
|
||||||
|
{
|
||||||
|
byte[] bkeyData = getKey(i);
|
||||||
|
cliOtherCloud.send( bkeyData, CommInfo.keySize );
|
||||||
|
}
|
||||||
|
|
||||||
|
//send the shuffle key and wait for the response
|
||||||
|
/******************************
|
||||||
|
* Here, the client can receive the shffule key
|
||||||
|
* But, in our implmenetation, we generate the key in the client
|
||||||
|
* it is also OK
|
||||||
|
* ************************************
|
||||||
|
*
|
||||||
|
* The client must wait for the response of the cloud
|
||||||
|
* and cloud should finish the shuffle operation
|
||||||
|
*
|
||||||
|
* Notice, we use the onion key as the shuffle key, it is also OK
|
||||||
|
* *********************************/
|
||||||
|
|
||||||
|
//reset some status in the unfilled level
|
||||||
|
keys[unfilledLevel]=kg.generateKey();
|
||||||
|
nextDummy[unfilledLevel]=0;
|
||||||
|
filled[unfilledLevel]=true;
|
||||||
|
|
||||||
|
byte[] shufflekey = getKey(unfilledLevel);//Util.generateDummyData(MCloudCommInfo.keySize);
|
||||||
|
cliOtherCloud.sendAndReceive(shufflekey, 16);
|
||||||
|
|
||||||
|
//System.out.println("noticeshufule ok cloud: "+cloud+" session "+ bSessionID[0]+" dataNumber "+dataNumber+" filledLevelLength:"+filledLevelLength);
|
||||||
|
|
||||||
|
|
||||||
|
/*********************** Second command: noticeWriteCloud ***************************/
|
||||||
|
/////////////////////////First, command and keys
|
||||||
|
byte[] cmd1=new byte[22];
|
||||||
|
cmd1[0]=CommandType.noticeWriteCloud;
|
||||||
|
System.arraycopy(bSessionID, 0, cmd1, 1, 8);
|
||||||
|
Util.intToByte(cmd1, 9, partition);
|
||||||
|
Util.intToByte(cmd1, 13, unfilledLevel);
|
||||||
|
cmd1[17] = (byte) otherCloud;
|
||||||
|
Util.intToByte(cmd1, 18, dataNumber);
|
||||||
|
|
||||||
|
cli.send(cmd1, 22, ids, dataNumber*4, null);
|
||||||
|
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Final, reset the status in the client
|
||||||
|
* (1) shuffle the blockIDs
|
||||||
|
* (2) reset the filled and read flag
|
||||||
|
* *******************************/
|
||||||
|
psuedo_random_permute( shufflekey, filledLevelLength);
|
||||||
|
|
||||||
|
for (int i=MCloudCommInfo.severBeginLevel;i<unfilledLevel; i++)
|
||||||
|
{
|
||||||
|
nextDummy[i]=0;
|
||||||
|
filled[i]=false;
|
||||||
|
}
|
||||||
|
//update the status in the un-filled level
|
||||||
|
/******************
|
||||||
|
* Save to a temp int array
|
||||||
|
* For the worst case
|
||||||
|
* ******************/
|
||||||
|
int[] bIDS = new int[filledLevelLength];
|
||||||
|
for (int i=0; i<filledLevelLength; i++)
|
||||||
|
{
|
||||||
|
bIDS[i]=blockIDs[i];
|
||||||
|
}
|
||||||
|
int levelBegin = (1 << (unfilledLevel + 1)) - 2;
|
||||||
|
for (int i=0;i<filledLevelLength;i++)
|
||||||
|
{
|
||||||
|
int bID=bIDS[i];
|
||||||
|
int _id = i+levelBegin;
|
||||||
|
blockIDs[_id] = bID;
|
||||||
|
readFlag[_id]=false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*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; i<levelBegin; i++)
|
||||||
|
{
|
||||||
|
blockIDs[i] = CommInfo.dummyID;
|
||||||
|
readFlag[i]=true;
|
||||||
|
}
|
||||||
|
//update all the real numbers
|
||||||
|
realDataNumber=0;
|
||||||
|
for (int i=levelBegin; i<this.n_capacity; i++)
|
||||||
|
{
|
||||||
|
if (blockIDs[i]>0 && 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<filledLevelLength; i++)
|
||||||
|
{
|
||||||
|
bIDS[i]=blockIDs[i];
|
||||||
|
}
|
||||||
|
// reset the status
|
||||||
|
int levelBegin = (1 << (unfilledLevel + 1)) - 2;
|
||||||
|
for (int i = 0; i< filledLevelLength; i++ ) {
|
||||||
|
int bID = bIDS[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; 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; i<this.n_capacity; i++)
|
||||||
|
{
|
||||||
|
if (blockIDs[i]>0 && 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<end;i++)
|
||||||
|
if (blockIDs[begin+i]<= CommInfo.dummyID)
|
||||||
|
{
|
||||||
|
nextDummy[level]=i+1;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Notice that, there is no dummy blocks
|
||||||
|
// System.out.println("No dummy !!!!!! return 0!!!!!p:"+this.partition+" !!!type:"+type+" level:"+level+" nextDummy[level]"+nextDummy[level]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package nankai.oram.client.common;
|
||||||
|
|
||||||
|
public class Position{
|
||||||
|
/**********************
|
||||||
|
* BLockID is maintained by the client
|
||||||
|
* But id is stored in the server, the record ID of the data u with ID of BLockID
|
||||||
|
*
|
||||||
|
* The same sequence in the client is denoted as the BLockIDs
|
||||||
|
* but the real sequence in the server will be the different ids
|
||||||
|
* ********************/
|
||||||
|
public int partition;
|
||||||
|
public int level;
|
||||||
|
public int offset;
|
||||||
|
public int rndNumber;//random value
|
||||||
|
public int cloud;//random value
|
||||||
|
public Position()
|
||||||
|
{
|
||||||
|
partition=-1;
|
||||||
|
level=-1;
|
||||||
|
offset=-1;
|
||||||
|
rndNumber=0;
|
||||||
|
cloud=-1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package nankai.oram.client.common;
|
||||||
|
|
||||||
|
import nankai.oram.common.CommInfo;
|
||||||
|
|
||||||
|
public class SlotObject{
|
||||||
|
public int id;
|
||||||
|
public byte[] value;
|
||||||
|
public SlotObject()
|
||||||
|
{
|
||||||
|
id=0;
|
||||||
|
value=new byte[CommInfo.blockSize];
|
||||||
|
}
|
||||||
|
public SlotObject(int _id, byte[] _value)
|
||||||
|
{
|
||||||
|
id=_id;
|
||||||
|
value=new byte[CommInfo.blockSize];
|
||||||
|
System.arraycopy(_value, 0, value, 0, CommInfo.blockSize);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<n_levels;i++)
|
||||||
|
{
|
||||||
|
dummyNumbers[i]=0;
|
||||||
|
nextDummy[i]=0;
|
||||||
|
filled[i]=false;
|
||||||
|
}
|
||||||
|
for (int i=0;i<n_capacity;i++)
|
||||||
|
{
|
||||||
|
flag[i]=true;
|
||||||
|
blockIDs[i]=CommInfo.dummyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
initKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initKeys()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
kg = KeyGenerator.getInstance("AES");
|
||||||
|
kg.init(128);
|
||||||
|
for (int j = 0; j < n_levels; j++)
|
||||||
|
keys[j] = kg.generateKey();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] readPartition(int block_id) {
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* From Each filled level, to read a block
|
||||||
|
* if it is in this level, read the only one real block
|
||||||
|
* else, read a dummy block *
|
||||||
|
* *****************************/
|
||||||
|
int readNumber = 0;
|
||||||
|
byte[] data = new byte[CommInfo.blockSize];
|
||||||
|
int level=-1;
|
||||||
|
if (block_id!=CommInfo.dummyID)
|
||||||
|
level = pos_map[block_id].level;
|
||||||
|
for (int i=0;i<n_levels;i++)
|
||||||
|
{
|
||||||
|
if (filled[i])
|
||||||
|
{
|
||||||
|
if (level==i && block_id!=CommInfo.dummyID)
|
||||||
|
{
|
||||||
|
readNumber++;
|
||||||
|
// in this level, to read a real block. get the offset
|
||||||
|
readBlock(p, i, pos_map[block_id].offset, data);
|
||||||
|
/*****************************
|
||||||
|
* Decrypt the data
|
||||||
|
* *************************/
|
||||||
|
SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
scp.initDec(keys[i], null);
|
||||||
|
scp.enc_decData(data, CommInfo.blockSize);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
readNumber++;
|
||||||
|
// not in this level, to read a dummy block, get the dummy offset
|
||||||
|
|
||||||
|
int dID=nextDummy(i);
|
||||||
|
if (dID == -1) // There is no dummy block can be read
|
||||||
|
continue;
|
||||||
|
|
||||||
|
readBlock(p, i, dID, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Util.readNumber ++;
|
||||||
|
Util.readbandwidth += CommInfo.blockSize + readNumber*4;
|
||||||
|
Util.cloudcloudbandwidth += readNumber * CommInfo.blockSize *1.2 + readNumber*4;
|
||||||
|
Util.cloudtocloud ++;
|
||||||
|
|
||||||
|
return data ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePartition(int block_id, byte[] bData)
|
||||||
|
{
|
||||||
|
|
||||||
|
int level=-1;
|
||||||
|
for (int i=0;i<this.n_levels;i++)
|
||||||
|
{
|
||||||
|
if (!filled[i])
|
||||||
|
{
|
||||||
|
level=i-1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* fetch all the unread blocks from the server
|
||||||
|
* ***************************************/
|
||||||
|
int realNumber=0;
|
||||||
|
if (level != -1) {
|
||||||
|
for (int i = 0; i <= level; i++) {
|
||||||
|
realNumber = fetchLevel(i, realNumber);
|
||||||
|
filled[i]=false;
|
||||||
|
}
|
||||||
|
Util.cloudtocloud = Util.cloudtocloud+1;
|
||||||
|
}
|
||||||
|
/******************************************
|
||||||
|
* If block_id is dummy block
|
||||||
|
* It will not be add into the shffule buffer
|
||||||
|
* ***************************************/
|
||||||
|
if (block_id!=CommInfo.dummyID)
|
||||||
|
System.arraycopy(bData, 0, s_buffer[realNumber++], 0, CommInfo.blockSize);
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* Treate the special level, i.e., the top level
|
||||||
|
* ************************/
|
||||||
|
if (level != n_levels - 1) ++level;
|
||||||
|
else{
|
||||||
|
System.out.println(" Filled!!!¡¡¡¡¡¡¡¡");
|
||||||
|
}
|
||||||
|
/******************************************
|
||||||
|
* Generate the dummy blocks and add them into the buffer
|
||||||
|
* ***************************************/
|
||||||
|
int begin = (1 << (level + 1)) - 2;
|
||||||
|
int sbuffer_len=0;
|
||||||
|
if (level != n_levels - 1) {
|
||||||
|
sbuffer_len = 2 *(1 << level);
|
||||||
|
} else sbuffer_len = top_level_len;
|
||||||
|
|
||||||
|
for (int i=realNumber;i<sbuffer_len;i++)
|
||||||
|
{
|
||||||
|
//generate the data
|
||||||
|
Util.intToByte(s_buffer[i], 0, CommInfo.dummyID);
|
||||||
|
byte[] bDummy=Util.generateDummyData(CommInfo.blockSize-4);
|
||||||
|
System.arraycopy(bDummy, 0, s_buffer[i], 4, CommInfo.blockSize-4);
|
||||||
|
}
|
||||||
|
/******************************************
|
||||||
|
* Shuffle the plian data in the shufflebuffer
|
||||||
|
* Then encrypt Them using the level key
|
||||||
|
* ***************************************/
|
||||||
|
psuedo_random_permute(s_buffer, sbuffer_len);
|
||||||
|
//Reset the key and dummyID
|
||||||
|
keys[level]=kg.generateKey();
|
||||||
|
nextDummy[level]=0;
|
||||||
|
/******************************************
|
||||||
|
* re-encrypt all the data
|
||||||
|
* ***************************************/
|
||||||
|
int bID=0;
|
||||||
|
|
||||||
|
SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
scp.initEnc(keys[level], null);
|
||||||
|
filled[level]=true;
|
||||||
|
|
||||||
|
for (int i=0;i<sbuffer_len;i++)
|
||||||
|
{
|
||||||
|
//set the flag and blockIDs
|
||||||
|
bID=Util.byteToInt(s_buffer[i], 0, 4);
|
||||||
|
int _id = begin+i;
|
||||||
|
if (bID==CommInfo.dummyID)
|
||||||
|
bID=CommInfo.dummyID-i;
|
||||||
|
else{
|
||||||
|
//update position map
|
||||||
|
pos_map[bID].partition=p;
|
||||||
|
pos_map[bID].level=level;
|
||||||
|
pos_map[bID].offset=i;
|
||||||
|
}
|
||||||
|
blockIDs[_id]=bID;
|
||||||
|
Util.intToByte(s_buffer[i], 0, bID);
|
||||||
|
flag[_id]=false;
|
||||||
|
|
||||||
|
//encrypt
|
||||||
|
scp.enc_decData(s_buffer[i], CommInfo.blockSize);
|
||||||
|
//partition + ID (_id)
|
||||||
|
cmdData[0]=CommandType.writeBlock;
|
||||||
|
Util.intToByte(cmdData, 1, p);
|
||||||
|
Util.intToByte(cmdData, 5, _id);
|
||||||
|
Util.intToByte(cmdData, 9, CommInfo.blockSize);
|
||||||
|
//store into the database
|
||||||
|
cli.send(cmdData, 13, s_buffer[i], CommInfo.blockSize, null);
|
||||||
|
}
|
||||||
|
for (int i=0;i<begin;i++)
|
||||||
|
{
|
||||||
|
blockIDs[i]=CommInfo.dummyID;
|
||||||
|
flag[i]=true;
|
||||||
|
}
|
||||||
|
realDataNumber=0;
|
||||||
|
for (int i=begin;i<this.n_capacity;i++)
|
||||||
|
{
|
||||||
|
if (blockIDs[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<level_len; j++)
|
||||||
|
{
|
||||||
|
_id=begin+j;
|
||||||
|
if (!flag[_id] && blockIDs[_id]>=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<end;i++)
|
||||||
|
if (blockIDs[begin+i] <= CommInfo.dummyID)
|
||||||
|
{
|
||||||
|
nextDummy[level]=i+1;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Notice that, there is no dummy blocks
|
||||||
|
//System.out.println("No dummy !!!!!! return 0!!!!!!!!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
public interface CommInfo {
|
||||||
|
|
||||||
|
public static int dummyID=-1;
|
||||||
|
public static int keySize=16;//the length of a key byte
|
||||||
|
public static int v=2;//the rate of evict operation
|
||||||
|
public static int blockSize=128;//the length of a block byte
|
||||||
|
public static double capacity_parameter=4.6;//4.6*N, the parameter of max capacity of partition
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
public interface CommandType {
|
||||||
|
|
||||||
|
public static byte initORAM=1;
|
||||||
|
public static byte readBlock=2;
|
||||||
|
public static byte writeBlock=3;
|
||||||
|
public static byte readCloud=4;
|
||||||
|
public static byte noticeWriteCloud=5; //client notices the cloud to be ready for the write operation
|
||||||
|
public static byte noticeShuffle=6; //client notices the cloud to be read for the shuffle operation
|
||||||
|
public static byte shuffleData=7; //cloud sends the shuffle data to the other cloud
|
||||||
|
public static byte backData=8;//the other cloud sends back the shuffled data
|
||||||
|
public static byte directWriteCloud=9; //client write to cloud the unfilled level directly
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static byte testTime=112;//the other cloud sends back the shuffled data
|
||||||
|
public static byte closeThread=111;
|
||||||
|
|
||||||
|
|
||||||
|
public static byte openDB=113;//the other cloud sends back the shuffled data
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
import com.mongodb.*;
|
||||||
|
import com.mongodb.client.*;
|
||||||
|
|
||||||
|
public class MongDBUtil {
|
||||||
|
MongoClient conn;
|
||||||
|
MongoDatabase db;
|
||||||
|
|
||||||
|
public void connect(String ip, int port, String dbName)
|
||||||
|
{
|
||||||
|
conn = new MongoClient(ip, port);
|
||||||
|
db = conn.getDatabase(dbName);
|
||||||
|
}
|
||||||
|
public void connect(String ip, int port )
|
||||||
|
{
|
||||||
|
conn = new MongoClient(ip, port);
|
||||||
|
}
|
||||||
|
public boolean createDB(String dbName)
|
||||||
|
{
|
||||||
|
if (conn==null)
|
||||||
|
{
|
||||||
|
System.out.println("no connection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
System.out.println("createDB "+dbName);
|
||||||
|
//first, drop it if exists
|
||||||
|
conn.dropDatabase(dbName);
|
||||||
|
//then, create
|
||||||
|
db = conn.getDatabase(dbName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public boolean openDB(String dbName)
|
||||||
|
{
|
||||||
|
if (conn==null)
|
||||||
|
{
|
||||||
|
System.out.println("no connection");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
System.out.println("openDB "+dbName);
|
||||||
|
db = conn.getDatabase(dbName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* create table / collection
|
||||||
|
* use the default index '__id' as the unique index
|
||||||
|
* @param collectioName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean createCollection(String collectioName)
|
||||||
|
{
|
||||||
|
if (db==null)
|
||||||
|
{
|
||||||
|
System.out.println("no db");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
db.createCollection(collectioName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MongoCollection getCollection(String collectioName)
|
||||||
|
{
|
||||||
|
return db.getCollection(collectioName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
public interface ResponseType {
|
||||||
|
|
||||||
|
public static int wrong=0;
|
||||||
|
public static int normal=1; //without value
|
||||||
|
public static int normalWithValue=2; //right run and some returned value + LEN +DATA
|
||||||
|
}
|
|
@ -0,0 +1,224 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class SocketClientUtil {
|
||||||
|
String ip;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
Socket socket;
|
||||||
|
DataInputStream in;
|
||||||
|
DataOutputStream out;
|
||||||
|
|
||||||
|
byte recvMsg[];
|
||||||
|
byte sendMsg[];
|
||||||
|
|
||||||
|
public static int responseType;//the returned value from the cloud server
|
||||||
|
|
||||||
|
public SocketClientUtil(String ip, int port) {
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
recvMsg=new byte[1024];//1k
|
||||||
|
sendMsg=new byte[4];//100k
|
||||||
|
responseType=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean connect() {
|
||||||
|
try {
|
||||||
|
// 向本机的2121端口发出客户请求
|
||||||
|
socket = new Socket(ip, port);
|
||||||
|
// System.out.println("Established a connection...");
|
||||||
|
|
||||||
|
socket.setKeepAlive(true);
|
||||||
|
out = new DataOutputStream(socket.getOutputStream());
|
||||||
|
in = new DataInputStream(socket.getInputStream());
|
||||||
|
// 由Socket对象得到输出流,并构造PrintWriter对象
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Error connect. " + e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// System.out.println("success for connection. " );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disConnect() {
|
||||||
|
try {
|
||||||
|
out.write(CommandType.closeThread);
|
||||||
|
out.flush();
|
||||||
|
out.close(); // 关闭Socket输出流
|
||||||
|
in.close(); // 关闭Socket输入流
|
||||||
|
socket.close(); // 关闭Socket
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Error. " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type request command type
|
||||||
|
* @param cmdInfo some information for specific command
|
||||||
|
* @param cmdLen the length of the cmdInfo
|
||||||
|
* @param sendData the data which contains the concrete command information
|
||||||
|
* @param dataLen the data length
|
||||||
|
* @param receiveData TODO
|
||||||
|
* @param retValue the returned data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void send(byte[] cmdInfo, int cmdLen, byte[] sendData, int dataLen, byte[] receiveData) {
|
||||||
|
try {
|
||||||
|
/************************
|
||||||
|
* Send
|
||||||
|
* (1) the request - command
|
||||||
|
* CommandType | len | data
|
||||||
|
* And (2) the message content
|
||||||
|
* *************************/
|
||||||
|
|
||||||
|
out.write(cmdInfo, 0, cmdLen);
|
||||||
|
out.flush();
|
||||||
|
if (dataLen > 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;i<num;i++)
|
||||||
|
{
|
||||||
|
out.write(sendData, hasSend, 512);
|
||||||
|
out.flush();
|
||||||
|
hasSend += 512;
|
||||||
|
}
|
||||||
|
if (leftLen>0){
|
||||||
|
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<cmdLen;i++)
|
||||||
|
System.out.print(cmdInfo[i]+" ");
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
for (int i=0;i<3;i++)
|
||||||
|
System.out.print(sendData[i]+" ");
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("Return error value!");
|
||||||
|
}else{
|
||||||
|
//System.out.println("server return success:" + responseType);
|
||||||
|
if (responseType == ResponseType.normalWithValue)
|
||||||
|
{
|
||||||
|
int retLen=0;
|
||||||
|
while ( (retLen = in.read(recvMsg, 0, 1024)) > 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<blockNumber;i++)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
cp.doFinal(bData, i*keySize, keySize, bData, i*keySize);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package nankai.oram.common;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
import nankai.oram.client.MCloudCommInfo;
|
||||||
|
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
public static boolean debug = false;
|
||||||
|
public static int writeNumber = 0; //
|
||||||
|
public static int cloudtocloud = 0; //
|
||||||
|
public static long bandwidth = 0; //
|
||||||
|
public static long cloudcloudbandwidth = 0; //
|
||||||
|
public static long readbandwidth = 0; //
|
||||||
|
public static int readNumber = 0; //
|
||||||
|
|
||||||
|
public static int byteToInt(byte[] src, int pos, int len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
for(int i =0; i< len; i++){
|
||||||
|
ret += (src[pos+i]&0xff) << (24-8*i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void intToByte(byte[] dest, int pos, int value) {
|
||||||
|
dest[pos+3] = (byte) (value & 0xff);
|
||||||
|
dest[pos+2] = (byte) (value >> 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<len;i++)
|
||||||
|
bData[i]=-1;
|
||||||
|
return bData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] generateSessionData( int len)
|
||||||
|
{
|
||||||
|
byte[] bData=new byte[len];
|
||||||
|
Random rnd=new Random();
|
||||||
|
rnd.nextBytes(bData);
|
||||||
|
return bData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] generateIV(int dummyID) {
|
||||||
|
byte[] iv=new byte[16];
|
||||||
|
Util.intToByte(iv, 0, dummyID);
|
||||||
|
for (int i=4;i<16;i++)
|
||||||
|
{
|
||||||
|
iv[i] = 0;
|
||||||
|
}
|
||||||
|
return iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int fpeForPermution(int inData, SecretKey sfk, int modular)
|
||||||
|
{
|
||||||
|
SymmetricCypto scp =new SymmetricCypto(CommInfo.keySize);
|
||||||
|
scp.initEnc(sfk, null);
|
||||||
|
byte[] bData = new byte[CommInfo.keySize];
|
||||||
|
for (int j=0; j<CommInfo.keySize; j++)
|
||||||
|
bData[j]=(byte) inData;
|
||||||
|
scp.enc_decData(bData, CommInfo.keySize);
|
||||||
|
int ret = Math.abs( Util.byteToInt(bData, 0, 4) );
|
||||||
|
return ret % modular;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static byte[] hexStringToByte(String hex) {
|
||||||
|
// int len = (hex.length() / 2);
|
||||||
|
// byte[] result = new byte[len];
|
||||||
|
// char[] achar = hex.toCharArray();
|
||||||
|
// for (int i = 0; i < len; i++) {
|
||||||
|
// int pos = i * 2;
|
||||||
|
// result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private static byte toByte(char c) {
|
||||||
|
// byte b = (byte) "0123456789ABCDEF".indexOf(c);
|
||||||
|
// return b;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /** *//**
|
||||||
|
// * 把字节数组转换成16进制字符串
|
||||||
|
// * @param bArray
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// public static final String bytesToHexString(byte[] bArray) {
|
||||||
|
// StringBuffer sb = new StringBuffer(bArray.length);
|
||||||
|
// String sTemp;
|
||||||
|
// for (int i = 0; i < bArray.length; i++) {
|
||||||
|
// sTemp = Integer.toHexString(0xFF & bArray[i]);
|
||||||
|
// if (sTemp.length() < 2)
|
||||||
|
// sb.append(0);
|
||||||
|
// sb.append(sTemp.toUpperCase());
|
||||||
|
// }
|
||||||
|
// return sb.toString();
|
||||||
|
// }
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nankai.oram.interfaces;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
import nankai.oram.client.common.SlotObject;
|
||||||
|
|
||||||
|
public interface MultiCloudORAM {
|
||||||
|
|
||||||
|
public byte[] readCloud(String key);
|
||||||
|
|
||||||
|
public void writeCloud(Queue slot);
|
||||||
|
public byte[] readCloud(int key);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package nankai.oram.interfaces;
|
||||||
|
|
||||||
|
public interface ORAM {
|
||||||
|
|
||||||
|
public void write(String idStr, byte[] value);
|
||||||
|
public byte[] read(String idStr);
|
||||||
|
public void write(int id, byte[] value);
|
||||||
|
public byte[] read(int id);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package nankai.oram.server;
|
||||||
|
|
||||||
|
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<size; i++)
|
||||||
|
{
|
||||||
|
obj = (SessionObject) objects.get(i);
|
||||||
|
if (obj.isEqual(sessionID) )
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addObject(SessionObject obj)
|
||||||
|
{
|
||||||
|
objects.add(obj);
|
||||||
|
//System.out.println("2. add --------------------size: "+objects.size());
|
||||||
|
}
|
||||||
|
public synchronized void removeObject(SessionObject obj)
|
||||||
|
{
|
||||||
|
objects.remove(obj);
|
||||||
|
//System.out.println("4. remove -----------------size: "+objects.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
package nankai.oram.server;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import nankai.oram.client.MCloudCommInfo;
|
||||||
|
import nankai.oram.common.CommInfo;
|
||||||
|
import nankai.oram.common.SymmetricCypto;
|
||||||
|
import nankai.oram.common.Util;
|
||||||
|
|
||||||
|
public class SessionObject {
|
||||||
|
|
||||||
|
public byte[] sessionID;
|
||||||
|
public byte[] levels;
|
||||||
|
public int idsLen = 0;
|
||||||
|
byte[][] shffule;
|
||||||
|
public int filledLevelLength;
|
||||||
|
public SecretKey key[];
|
||||||
|
public int unfilledLevel;
|
||||||
|
SecretKey sfk; //onion level key and shuffle key
|
||||||
|
SymmetricCypto scp;
|
||||||
|
|
||||||
|
int bPos =0;
|
||||||
|
|
||||||
|
public SessionObject(byte[] sid)
|
||||||
|
{
|
||||||
|
scp =new SymmetricCypto(CommInfo.keySize);
|
||||||
|
//System.out.print("2. add session ");
|
||||||
|
sessionID = new byte[8];
|
||||||
|
for(int i=0;i<8;i++){
|
||||||
|
//System.out.print(sid[i]+" ");
|
||||||
|
sessionID[i]=sid[i];
|
||||||
|
}
|
||||||
|
//System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevels(byte[] ls, int len)
|
||||||
|
{
|
||||||
|
if (ls!=null)
|
||||||
|
;//System.out.println("has received IDs and levels Data!!");
|
||||||
|
idsLen=len;
|
||||||
|
levels=new byte[idsLen];
|
||||||
|
System.arraycopy(ls, 0, levels, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEqual(byte[] sid)
|
||||||
|
{
|
||||||
|
for(int i=0;i<8;i++)
|
||||||
|
{
|
||||||
|
if (sessionID[i]!=sid[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createShuffle(int filledLevelLength)
|
||||||
|
{
|
||||||
|
this.filledLevelLength = filledLevelLength;
|
||||||
|
shffule=new byte[filledLevelLength][CommInfo.blockSize];
|
||||||
|
bPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createkey(int unfilledLevel)
|
||||||
|
{
|
||||||
|
this.unfilledLevel = unfilledLevel;
|
||||||
|
key = new SecretKey[unfilledLevel+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(int level, byte[] bdata)
|
||||||
|
{
|
||||||
|
key[level] = new SecretKeySpec(bdata, "AES");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSFKey( byte[] bdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
// System.out.print("setSFKey " );
|
||||||
|
// for (int i=0;i<6;i++)
|
||||||
|
// System.out.print ( bdata[i]+" " );
|
||||||
|
// System.out.println( );
|
||||||
|
|
||||||
|
sfk = new SecretKeySpec(bdata, "AES");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockData(int pos, byte[] bdata)
|
||||||
|
{
|
||||||
|
bPos++;
|
||||||
|
System.arraycopy(bdata, 0, shffule[pos], 0, CommInfo.blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockData( byte[] bdata)
|
||||||
|
{
|
||||||
|
System.arraycopy(bdata, 0, shffule[bPos++], 0, CommInfo.blockSize);
|
||||||
|
}
|
||||||
|
public void setBlockDataWithOnionDecryption(int pos, byte[] bdata, int level)
|
||||||
|
{
|
||||||
|
// System.out.println("shuffleData: onion decryption: -> 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 <filledLevelLength; i++) {
|
||||||
|
|
||||||
|
int j = Util.fpeForPermution(i, sfk, filledLevelLength);
|
||||||
|
System.arraycopy(shffule[i], 0, bData, 0, CommInfo.blockSize);
|
||||||
|
System.arraycopy(shffule[j], 0, shffule[i], 0, CommInfo.blockSize);
|
||||||
|
System.arraycopy(bData, 0, shffule[j], 0, CommInfo.blockSize);
|
||||||
|
|
||||||
|
// System.out.println("permute: "+i+" "+j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onionEncryption() {
|
||||||
|
// for (int i = 0; i <filledLevelLength; i++) {
|
||||||
|
// scp.initEnc(sfk, null);
|
||||||
|
// scp.enc_decData(shffule[i], CommInfo.blockSize);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package nankai.oram.server;
|
||||||
|
|
||||||
|
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 ThinORAMserver {
|
||||||
|
public static ThinORAMserver 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 ThinORAMserver()
|
||||||
|
{
|
||||||
|
bBlockData=new byte[CommInfo.blockSize];
|
||||||
|
initFlag=false;
|
||||||
|
dbUtil=new MongDBUtil();
|
||||||
|
dbUtil.connect("localhost", 27017);
|
||||||
|
cloud = 0;
|
||||||
|
}
|
||||||
|
public static ThinORAMserver getInstance()
|
||||||
|
{
|
||||||
|
if (instance==null)
|
||||||
|
instance=new ThinORAMserver();
|
||||||
|
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("ThinPartitionORAM"+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("ThinPartitionORAM"+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<Document> 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<Document> collection = dbUtil
|
||||||
|
.getCollection("part_" + p);
|
||||||
|
// Find the data and return them
|
||||||
|
|
||||||
|
FindIterable<Document> findIterable = collection.find(new Document(
|
||||||
|
"_id", _id));
|
||||||
|
MongoCursor<Document> 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<n_partitions;i++)
|
||||||
|
{
|
||||||
|
dbUtil.createCollection("part_"+i);
|
||||||
|
|
||||||
|
//insert all the data records into the collection
|
||||||
|
|
||||||
|
MongoCollection<Document> 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
|
||||||
|
* ***********************************/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<len;i++)
|
||||||
|
System.out.print(recvCmd[i]+" ");
|
||||||
|
out.writeByte(ResponseType.wrong);
|
||||||
|
out.flush();
|
||||||
|
} else {
|
||||||
|
/**************************************
|
||||||
|
* partition+_id
|
||||||
|
* **********************************/
|
||||||
|
shuffleData(out, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
/*********
|
||||||
|
* 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;i<idsLen; i++)
|
||||||
|
{
|
||||||
|
if (in.read(recBlcokData, 0, CommInfo.blockSize) <= 0) {
|
||||||
|
System.out.println("shuffleData: ERROR id block data!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
/******************** do the onion decryption ********************************/
|
||||||
|
session.setBlockDataWithOnionDecryption(filledLevelLength - idsLen + i, recBlcokData, session.levels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
* Finally, shuffule them
|
||||||
|
*******************************************/
|
||||||
|
// System.out.println("begin psuedo_random_permute ");
|
||||||
|
session.psuedo_random_permute();
|
||||||
|
//re-encrypt them and send backs
|
||||||
|
session.onionEncryption();
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* return back the data
|
||||||
|
* ********************************/
|
||||||
|
byte[] backCmd=new byte[5];
|
||||||
|
backCmd[0]=CommandType.backData;
|
||||||
|
Util.intToByte(backCmd, 1, session.filledLevelLength);
|
||||||
|
|
||||||
|
out.write(backCmd, 0, 5);
|
||||||
|
out.flush();
|
||||||
|
for (int i=0;i<session.filledLevelLength;i++)
|
||||||
|
{
|
||||||
|
out.write(session.shffule[i], 0, CommInfo.blockSize);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
//The end of the session
|
||||||
|
manager.removeObject(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void directWriteCloud(DataOutputStream out, DataInputStream in)
|
||||||
|
throws IOException {
|
||||||
|
/****************************************
|
||||||
|
* (1)Send All the data, onionkeys in slots to the otherCloud
|
||||||
|
*
|
||||||
|
* CommandType: shuffleData
|
||||||
|
* Content: session ID | unfilled levels number |
|
||||||
|
* onion keys and slots data
|
||||||
|
* ************************************/
|
||||||
|
|
||||||
|
//System.out.println("directWriteCloud");
|
||||||
|
|
||||||
|
int partition = Util.byteToInt(recvCmd, 1, 4);
|
||||||
|
int unfilledLevel = Util.byteToInt(recvCmd, 5, 4);
|
||||||
|
int filledLevelLength = Util.byteToInt(recvCmd, 9, 4); ;
|
||||||
|
|
||||||
|
/*******************
|
||||||
|
* Has received the write operation command?
|
||||||
|
* If not, create the session object
|
||||||
|
* *********************/
|
||||||
|
byte[] recBlcokData = new byte[CommInfo.blockSize];
|
||||||
|
int beginID=(1 << (unfilledLevel + 1)) - 2;
|
||||||
|
for (int i=0;i<filledLevelLength;i++)
|
||||||
|
{
|
||||||
|
if (in.read(recBlcokData, 0, CommInfo.blockSize) <= 0) {
|
||||||
|
System.out.println("ERROR read data!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}else{
|
||||||
|
oram.writeBlock(partition, beginID+i, recBlcokData, 0);
|
||||||
|
}
|
||||||
|
//System.out.println("i: "+i+ " "+recBlcokData[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//read the sfk
|
||||||
|
byte[] sfk=new byte[2];
|
||||||
|
if (in.read(sfk, 0, 2) <= 0) {
|
||||||
|
System.out.println("ERROR read key data!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
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 noticeShuffle(DataOutputStream out, DataInputStream in)
|
||||||
|
throws IOException {
|
||||||
|
/****************************************
|
||||||
|
* (1)Send All the data, onionkeys in slots to the otherCloud
|
||||||
|
*
|
||||||
|
* CommandType: shuffleData
|
||||||
|
* Content: session ID | unfilled levels number |
|
||||||
|
* onion keys and slots data
|
||||||
|
* ************************************/
|
||||||
|
|
||||||
|
//System.out.println("1. noticeShuffle");
|
||||||
|
byte[] sessionID = new byte[8];
|
||||||
|
|
||||||
|
System.arraycopy(recvCmd, 1, sessionID, 0, 8);
|
||||||
|
int partition = Util.byteToInt(recvCmd, 9, 4);
|
||||||
|
int unfilledLevel = Util.byteToInt(recvCmd, 13, 4);
|
||||||
|
int filledLevelLength = Util.byteToInt(recvCmd, 17, 4);
|
||||||
|
int idsLen = Util.byteToInt(recvCmd, 21, 4);
|
||||||
|
int evictSize = Util.byteToInt(recvCmd, 25, 4);
|
||||||
|
// System.out.println(" partition "+ partition +" unfilledLevel "+ unfilledLevel+" filledLevelLength "+filledLevelLength+" idsLen "+idsLen );
|
||||||
|
int rndLength = filledLevelLength - idsLen - 2*evictSize;
|
||||||
|
if (rndLength<0)
|
||||||
|
System.out.println(" rndLength "+ rndLength +" filledLevelLength "+filledLevelLength+" idsLen "+idsLen+" evictSize "+evictSize );
|
||||||
|
|
||||||
|
|
||||||
|
if (filledLevelLength <=0 )
|
||||||
|
;//System.out.println("ERROR!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
|
||||||
|
/*******************
|
||||||
|
* Has received the write operation command?
|
||||||
|
* If not, create the session object
|
||||||
|
* *********************/
|
||||||
|
SessionManager manager=SessionManager.getInstance();
|
||||||
|
SessionObject session = manager.getObject(sessionID);
|
||||||
|
if (session==null)
|
||||||
|
{
|
||||||
|
//create it
|
||||||
|
session=new SessionObject(sessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//receive the IDs
|
||||||
|
byte[] levels = new byte[idsLen];
|
||||||
|
if (idsLen>0){
|
||||||
|
// 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<rndLength;i++)
|
||||||
|
{
|
||||||
|
int did=Util.byteToInt(rnds, i*4, 4);
|
||||||
|
//add the dummy block into the buffer
|
||||||
|
session.setBlockData(i+2*evictSize, this.generateXORBlock(did));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//receive the onion keys
|
||||||
|
session.createkey(unfilledLevel);
|
||||||
|
byte[] bkeyData = new byte[CommInfo.keySize];
|
||||||
|
for (int i=MCloudCommInfo.severBeginLevel; i<=unfilledLevel; i++)
|
||||||
|
{
|
||||||
|
if (in.read(bkeyData, 0, CommInfo.keySize) <= 0) {
|
||||||
|
System.out.println("ERROR read key data!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
session.setKey(i, bkeyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//read the sfk
|
||||||
|
byte[] sfk=new byte[16];
|
||||||
|
if (in.read(sfk, 0, 16) <= 0) {
|
||||||
|
System.out.println("ERROR read key data!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
session.setSFKey(sfk);
|
||||||
|
manager.addObject(session);
|
||||||
|
|
||||||
|
out.writeByte(ResponseType.normal);
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] generateXORBlock(int dummyID)
|
||||||
|
{
|
||||||
|
//Encrypt the 0x00 default value by the userkey
|
||||||
|
byte[] data=new byte[CommInfo.blockSize];
|
||||||
|
for (int i=0;i<CommInfo.blockSize;i++)
|
||||||
|
{
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretKey userKey;
|
||||||
|
// /****************************
|
||||||
|
// * The first 4 bytes is the dummmyID and the random value, to make sure it is less than 0
|
||||||
|
// *
|
||||||
|
// * But now, to simplify the implementation, we ignore the random value for the same 0000000
|
||||||
|
// * ******************************/
|
||||||
|
//
|
||||||
|
// byte[] iv = Util.generateIV(dummyID);
|
||||||
|
|
||||||
|
//encrypt
|
||||||
|
// SymmetricCypto scp=new SymmetricCypto(CommInfo.keySize);
|
||||||
|
// scp.initEnc(userKey, iv);
|
||||||
|
// scp.enc_decData(data, CommInfo.blockSize);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When receive this data, the cloud would read data and send them to the other cloud
|
||||||
|
* @param out
|
||||||
|
* @param in
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void noticeWriteCloud(DataOutputStream out, DataInputStream in)
|
||||||
|
throws IOException {
|
||||||
|
/****************************************
|
||||||
|
* (1)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
|
||||||
|
*
|
||||||
|
* When receive this data, the cloud would read data and send them to the other cloud
|
||||||
|
* ************************************/
|
||||||
|
|
||||||
|
//System.out.println("3. noticeWriteCloud "+recvCmd[1]);
|
||||||
|
byte[] sessionID = new byte[8];
|
||||||
|
|
||||||
|
System.arraycopy(recvCmd, 1, sessionID, 0, 8);
|
||||||
|
int partition = Util.byteToInt(recvCmd, 9, 4);
|
||||||
|
int unfilledLevel = Util.byteToInt(recvCmd, 13, 4);
|
||||||
|
int cloud = recvCmd[17];
|
||||||
|
int idsLen = Util.byteToInt(recvCmd, 18, 4);
|
||||||
|
|
||||||
|
byte[] ids = null;
|
||||||
|
// 4 ID + 1 level
|
||||||
|
if (idsLen > 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;i<length; i++)
|
||||||
|
{
|
||||||
|
if (SCU.receiving(bData, CommInfo.blockSize)!=CommInfo.blockSize)
|
||||||
|
System.out.println("wrong back data!");
|
||||||
|
else{
|
||||||
|
//System.out.println("write _id: "+(beginID+i)+" beginID: "+beginID);
|
||||||
|
//store it in the database
|
||||||
|
oram.writeBlock(partition, beginID+i, bData, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCU.disConnect();
|
||||||
|
|
||||||
|
out.writeByte(ResponseType.normal);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readSocketLongData(DataInputStream in, int dataLen, byte[] ids)
|
||||||
|
throws IOException {
|
||||||
|
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;i<num;i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (in.read(ids, hasRead, 512)!=512)
|
||||||
|
System.out.println("noticeWriteCloud 512 Error!!!");
|
||||||
|
hasRead += 512;
|
||||||
|
}
|
||||||
|
if (leftLen>0){
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue