Defined semi-final versions of the batch interfaces.
Implemented in part extended BB Server interface. Added Digest support for Batch messages. Made GlobalCryptoSetup a final singleton.Bulletin-Board-Batch
parent
37fdc0bb83
commit
37f962d520
|
@ -117,6 +117,11 @@ public class ThreadedBulletinBoardClient extends SimpleBulletinBoardClient imple
|
|||
// TODO: Implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(MessageFilterList filterList, MessageHandler messageHandler) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
package meerkat.bulletinboard.callbacks;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import meerkat.bulletinboard.BulletinClientJob;
|
||||
import meerkat.bulletinboard.BulletinClientJobResult;
|
||||
import meerkat.bulletinboard.BulletinClientWorker;
|
||||
import meerkat.protobuf.BulletinBoardAPI;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a future callback used to listen to workers and run on job finish
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package meerkat.bulletinboard.callbacks;
|
||||
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import meerkat.bulletinboard.BulletinBoardClient;
|
||||
import meerkat.bulletinboard.AsyncBulletinBoardClient.*;
|
||||
import meerkat.bulletinboard.BulletinClientJobResult;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
|
@ -13,10 +13,10 @@ import java.util.List;
|
|||
*/
|
||||
public class GetRedundancyFutureCallback extends ClientFutureCallback {
|
||||
|
||||
private BulletinBoardClient.ClientCallback<Float> callback;
|
||||
private ClientCallback<Float> callback;
|
||||
|
||||
public GetRedundancyFutureCallback(ListeningExecutorService listeningExecutor,
|
||||
BulletinBoardClient.ClientCallback<Float> callback) {
|
||||
ClientCallback<Float> callback) {
|
||||
super(listeningExecutor);
|
||||
this.callback = callback;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,11 @@ package meerkat.bulletinboard.callbacks;
|
|||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import meerkat.bulletinboard.BulletinBoardClient;
|
||||
import meerkat.bulletinboard.AsyncBulletinBoardClient.*;
|
||||
import meerkat.bulletinboard.BulletinClientJob;
|
||||
import meerkat.bulletinboard.BulletinClientJobResult;
|
||||
import meerkat.bulletinboard.BulletinClientWorker;
|
||||
import meerkat.protobuf.BulletinBoardAPI;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a future callback used to listen to workers and run on job finish
|
||||
|
@ -16,10 +14,10 @@ import java.util.List;
|
|||
*/
|
||||
public class PostMessageFutureCallback extends ClientFutureCallback {
|
||||
|
||||
private BulletinBoardClient.ClientCallback<?> callback;
|
||||
private ClientCallback<?> callback;
|
||||
|
||||
public PostMessageFutureCallback(ListeningExecutorService listeningExecutor,
|
||||
BulletinBoardClient.ClientCallback<?> callback) {
|
||||
ClientCallback<?> callback) {
|
||||
super(listeningExecutor);
|
||||
this.callback = callback;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package meerkat.bulletinboard.callbacks;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import meerkat.bulletinboard.BulletinBoardClient;
|
||||
import meerkat.bulletinboard.BulletinClientJob;
|
||||
import meerkat.bulletinboard.AsyncBulletinBoardClient.*;
|
||||
import meerkat.bulletinboard.BulletinClientJobResult;
|
||||
import meerkat.bulletinboard.BulletinClientWorker;
|
||||
import meerkat.protobuf.BulletinBoardAPI;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -16,10 +13,10 @@ import java.util.List;
|
|||
*/
|
||||
public class ReadMessagesFutureCallback extends ClientFutureCallback {
|
||||
|
||||
private BulletinBoardClient.ClientCallback<List<BulletinBoardAPI.BulletinBoardMessage>> callback;
|
||||
private ClientCallback<List<BulletinBoardAPI.BulletinBoardMessage>> callback;
|
||||
|
||||
public ReadMessagesFutureCallback(ListeningExecutorService listeningExecutor,
|
||||
BulletinBoardClient.ClientCallback<List<BulletinBoardAPI.BulletinBoardMessage>> callback) {
|
||||
ClientCallback<List<BulletinBoardAPI.BulletinBoardMessage>> callback) {
|
||||
super(listeningExecutor);
|
||||
this.callback = callback;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import com.google.protobuf.ByteString;
|
||||
import meerkat.bulletinboard.AsyncBulletinBoardClient;
|
||||
import meerkat.bulletinboard.BulletinBoardClient;
|
||||
import meerkat.bulletinboard.BulletinBoardClient.ClientCallback;
|
||||
import meerkat.bulletinboard.AsyncBulletinBoardClient.ClientCallback;
|
||||
import meerkat.bulletinboard.ThreadedBulletinBoardClient;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.protobuf.Crypto;
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
package meerkat.bulletinboard.sqlserver;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.ProtocolStringList;
|
||||
|
||||
import meerkat.bulletinboard.BulletinBoardServer;
|
||||
import meerkat.bulletinboard.sqlserver.mappers.EntryNumMapper;
|
||||
import meerkat.bulletinboard.sqlserver.mappers.MessageMapper;
|
||||
import meerkat.bulletinboard.sqlserver.mappers.SignatureMapper;
|
||||
import meerkat.bulletinboard.sqlserver.mappers.*;
|
||||
|
||||
import meerkat.comm.CommunicationException;
|
||||
|
||||
import meerkat.crypto.BatchDigest;
|
||||
import meerkat.crypto.DigitalSignature;
|
||||
import meerkat.crypto.concrete.ECDSASignature;
|
||||
import meerkat.crypto.concrete.SHA256Digest;
|
||||
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.protobuf.Crypto.Signature;
|
||||
import meerkat.protobuf.Crypto.SignatureVerificationKey;
|
||||
import meerkat.crypto.Digest;
|
||||
import meerkat.crypto.concrete.SHA256Digest;
|
||||
|
||||
|
||||
import static meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer.SQLQueryProvider.*;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -23,6 +32,8 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
|||
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
||||
import org.springframework.jdbc.support.KeyHolder;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is a generic SQL implementation of the BulletinBoardServer API.
|
||||
*/
|
||||
|
@ -46,7 +57,12 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
CONNECT_TAG(new String[] {"EntryNum","Tag"}),
|
||||
ADD_SIGNATURE(new String[] {"EntryNum","SignerId","Signature"}),
|
||||
GET_SIGNATURES(new String[] {"EntryNum"}),
|
||||
GET_MESSAGES(new String[] {});
|
||||
GET_MESSAGES(new String[] {}),
|
||||
GET_BATCH_MESSAGE_ENTRY(new String[] {"SignerId", "BatchId"}),
|
||||
CHECK_BATCH_LENGTH(new String[] {"SignerId", "BatchId"}),
|
||||
GET_BATCH_MESSAGE_DATA(new String[] {"SignerId", "BatchId", "StartPosition"}),
|
||||
INSERT_BATCH_DATA(new String[] {"SignerId", "BatchId", "SerialNum", "Data"}),
|
||||
CONNECT_BATCH_TAG(new String[] {"SignerId", "BatchId", "Tag"});
|
||||
|
||||
private String[] paramNames;
|
||||
|
||||
|
@ -58,6 +74,10 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
return paramNames;
|
||||
}
|
||||
|
||||
public String getParamName(int num) {
|
||||
return paramNames[num];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,6 +172,11 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the value of the parameter specified in a message filter
|
||||
* @param messageFilter is the filter
|
||||
* @return the object parameter for the SQL query embedded in the filter (this depends on the filter type)
|
||||
*/
|
||||
private Object getParam(MessageFilter messageFilter) {
|
||||
|
||||
switch (messageFilter.getType()) {
|
||||
|
@ -170,7 +195,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
case MAX_MESSAGES:
|
||||
return messageFilter.getMaxMessages();
|
||||
|
||||
default:
|
||||
default: // Unsupported filter type
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -193,7 +218,8 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
protected NamedParameterJdbcTemplate jdbcTemplate;
|
||||
|
||||
protected Digest digest;
|
||||
protected BatchDigest digest;
|
||||
protected DigitalSignature signer;
|
||||
|
||||
protected List<SignatureVerificationKey> trusteeSignatureVerificationArray;
|
||||
protected int minTrusteeSignatures;
|
||||
|
@ -232,6 +258,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
// TODO write signature reading part.
|
||||
|
||||
digest = new SHA256Digest();
|
||||
signer = new ECDSASignature();
|
||||
|
||||
jdbcTemplate = new NamedParameterJdbcTemplate(sqlQueryProvider.getDataSource());
|
||||
|
||||
|
@ -264,12 +291,12 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
String sql;
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.INSERT_NEW_TAG);
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.INSERT_NEW_TAG);
|
||||
Map namedParameters[] = new HashMap[tags.length];
|
||||
|
||||
for (int i = 0 ; i < tags.length ; i++){
|
||||
namedParameters[i] = new HashMap();
|
||||
namedParameters[i].put("Tag", tags[i]);
|
||||
namedParameters[i].put(QueryType.INSERT_NEW_TAG.getParamName(0), tags[i]);
|
||||
}
|
||||
|
||||
jdbcTemplate.batchUpdate(sql, namedParameters);
|
||||
|
@ -316,11 +343,11 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
// Add message to table if needed and store entry number of message.
|
||||
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.FIND_MSG_ID);
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.FIND_MSG_ID);
|
||||
Map namedParameters = new HashMap();
|
||||
namedParameters.put("MsgId",msgID);
|
||||
namedParameters.put(QueryType.FIND_MSG_ID.getParamName(0),msgID);
|
||||
|
||||
List<Long> entryNums = jdbcTemplate.query(sql, new MapSqlParameterSource(namedParameters), new EntryNumMapper());
|
||||
List<Long> entryNums = jdbcTemplate.query(sql, new MapSqlParameterSource(namedParameters), new LongMapper());
|
||||
|
||||
if (entryNums.size() > 0){
|
||||
|
||||
|
@ -328,8 +355,8 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
} else{
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.INSERT_MSG);
|
||||
namedParameters.put("Msg", msg.getMsg().toByteArray());
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.INSERT_MSG);
|
||||
namedParameters.put(QueryType.INSERT_MSG.getParamName(0), msg.getMsg().toByteArray());
|
||||
|
||||
KeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
jdbcTemplate.update(sql,new MapSqlParameterSource(namedParameters),keyHolder);
|
||||
|
@ -354,14 +381,14 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
// Connect message to tags.
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.CONNECT_TAG);
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.CONNECT_TAG);
|
||||
|
||||
namedParameterArray = new HashMap[tags.length];
|
||||
|
||||
for (int i = 0 ; i < tags.length ; i++) {
|
||||
namedParameterArray[i] = new HashMap();
|
||||
namedParameterArray[i].put("EntryNum", entryNum);
|
||||
namedParameterArray[i].put("Tag", tags[i]);
|
||||
namedParameterArray[i].put(QueryType.CONNECT_TAG.getParamName(0), entryNum);
|
||||
namedParameterArray[i].put(QueryType.CONNECT_TAG.getParamName(1), tags[i]);
|
||||
}
|
||||
|
||||
jdbcTemplate.batchUpdate(sql, namedParameterArray);
|
||||
|
@ -374,15 +401,15 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
// Connect message to signatures.
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.ADD_SIGNATURE);
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.ADD_SIGNATURE);
|
||||
|
||||
namedParameterArray = new HashMap[signatures.length];
|
||||
|
||||
for (int i = 0 ; i < signatures.length ; i++) {
|
||||
namedParameterArray[i] = new HashMap();
|
||||
namedParameterArray[i].put("EntryNum", entryNum);
|
||||
namedParameterArray[i].put("SignerId", signatures[i].getSignerId().toByteArray());
|
||||
namedParameterArray[i].put("Signature", signatures[i].toByteArray());
|
||||
namedParameterArray[i].put(QueryType.ADD_SIGNATURE.getParamName(0), entryNum);
|
||||
namedParameterArray[i].put(QueryType.ADD_SIGNATURE.getParamName(1), signatures[i].getSignerId().toByteArray());
|
||||
namedParameterArray[i].put(QueryType.ADD_SIGNATURE.getParamName(2), signatures[i].toByteArray());
|
||||
}
|
||||
|
||||
jdbcTemplate.batchUpdate(sql,namedParameterArray);
|
||||
|
@ -412,7 +439,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
// Check if Tag/Signature tables are required for filtering purposes
|
||||
|
||||
sqlBuilder.append(sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.GET_MESSAGES));
|
||||
sqlBuilder.append(sqlQueryProvider.getSQLString(QueryType.GET_MESSAGES));
|
||||
// Add conditions
|
||||
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
|
@ -434,7 +461,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
sqlBuilder.append(sqlQueryProvider.getCondition(filter.getType(), paramNum));
|
||||
|
||||
SQLQueryProvider.FilterTypeParam filterTypeParam = SQLQueryProvider.FilterTypeParam.getFilterTypeParamName(filter.getType());
|
||||
FilterTypeParam filterTypeParam = FilterTypeParam.getFilterTypeParamName(filter.getType());
|
||||
|
||||
namedParameters.addValue(
|
||||
filterTypeParam.getParamName() + Integer.toString(paramNum),
|
||||
|
@ -457,10 +484,10 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
// Retrieve signatures
|
||||
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
namedParameters.addValue("EntryNum", msgBuilder.getEntryNum());
|
||||
namedParameters.addValue(QueryType.GET_SIGNATURES.getParamName(0), msgBuilder.getEntryNum());
|
||||
|
||||
List<Signature> signatures = jdbcTemplate.query(
|
||||
sqlQueryProvider.getSQLString(SQLQueryProvider.QueryType.GET_SIGNATURES),
|
||||
sqlQueryProvider.getSQLString(QueryType.GET_SIGNATURES),
|
||||
namedParameters,
|
||||
signatureMapper);
|
||||
|
||||
|
@ -478,6 +505,130 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if a specified batch exists and is already closed
|
||||
* @param signerId is the ID of the publisher of the batch
|
||||
* @param batchId is the unique (per signer) batch ID
|
||||
* @return TRUE if the batch is closed and FALSE if it is still open or doesn't exist at all
|
||||
*/
|
||||
private boolean isBatchClosed(ByteString signerId, int batchId){
|
||||
|
||||
String sql = sqlQueryProvider.getSQLString(QueryType.GET_BATCH_MESSAGE_ENTRY);
|
||||
|
||||
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_ENTRY.getParamName(0), signerId);
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_ENTRY.getParamName(1), batchId);
|
||||
|
||||
List<Long> result = jdbcTemplate.query(sql,namedParameters,new LongMapper());
|
||||
|
||||
return (result.size() > 0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoolMsg beginBatch(BeginBatchMessage message) throws CommunicationException {
|
||||
|
||||
// Check if batch is closed
|
||||
if (isBatchClosed(message.getSignerId(), message.getBatchId())) {
|
||||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
// Add new tags to table
|
||||
ProtocolStringList tagList = message.getTagList();
|
||||
String[] tags = new String[tagList.size()];
|
||||
tags = tagList.toArray(tags);
|
||||
try {
|
||||
insertNewTags(tags);
|
||||
} catch (SQLException e) {
|
||||
throw new CommunicationException(e.getMessage());
|
||||
}
|
||||
|
||||
// Connect tags
|
||||
String sql = sqlQueryProvider.getSQLString(QueryType.CONNECT_BATCH_TAG);
|
||||
MapSqlParameterSource namedParameters[] = new MapSqlParameterSource[tags.length];
|
||||
|
||||
for (int i=0 ; i < tags.length ; i++) {
|
||||
namedParameters[i] = new MapSqlParameterSource();
|
||||
namedParameters[i].addValue(QueryType.CONNECT_BATCH_TAG.getParamName(0),message.getSignerId());
|
||||
namedParameters[i].addValue(QueryType.CONNECT_BATCH_TAG.getParamName(1),message.getBatchId());
|
||||
namedParameters[i].addValue(QueryType.CONNECT_BATCH_TAG.getParamName(2),tags[i]);
|
||||
}
|
||||
|
||||
jdbcTemplate.batchUpdate(sql,namedParameters);
|
||||
|
||||
return BoolMsg.newBuilder().setValue(true).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoolMsg postBatchMessage(BatchMessage batchMessage) {
|
||||
|
||||
// Check if batch is closed
|
||||
if (isBatchClosed(batchMessage.getSignerId(), batchMessage.getBatchId())) {
|
||||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
// Add data
|
||||
String sql = sqlQueryProvider.getSQLString(QueryType.INSERT_BATCH_DATA);
|
||||
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.INSERT_BATCH_DATA.getParamName(0),batchMessage.getSignerId());
|
||||
namedParameters.addValue(QueryType.INSERT_BATCH_DATA.getParamName(1),batchMessage.getBatchId());
|
||||
namedParameters.addValue(QueryType.INSERT_BATCH_DATA.getParamName(2),batchMessage.getSerialNum());
|
||||
namedParameters.addValue(QueryType.INSERT_BATCH_DATA.getParamName(3),batchMessage.getData());
|
||||
|
||||
jdbcTemplate.update(sql, namedParameters);
|
||||
|
||||
return BoolMsg.newBuilder().setValue(true).build();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoolMsg closeBatchMessage(CloseBatchMessage message) throws CommunicationException {
|
||||
|
||||
// Check batch size
|
||||
|
||||
String sql = sqlQueryProvider.getSQLString(QueryType.CHECK_BATCH_LENGTH);
|
||||
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.CHECK_BATCH_LENGTH.getParamName(0),message.getSig().getSignerId());
|
||||
namedParameters.addValue(QueryType.CHECK_BATCH_LENGTH.getParamName(1),message.getBatchId());
|
||||
|
||||
List<Long> lengthResult = jdbcTemplate.query(sql, namedParameters, new LongMapper());
|
||||
|
||||
if (lengthResult.get(0) != message.getBatchLength()) {
|
||||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
// Check signature
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.GET_BATCH_MESSAGE_DATA);
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(0),message.getSig().getSignerId());
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1),message.getBatchId());
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(2),0); // Read from the beginning
|
||||
|
||||
List<BatchData> batchDataList = jdbcTemplate.query(sql, namedParameters, new BatchDataMapper());
|
||||
|
||||
try {
|
||||
signer.initVerify(message.getSig());
|
||||
} catch (CertificateException | InvalidKeyException e) {
|
||||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
//TODO: FInish this
|
||||
|
||||
//signer.updateContent(msgStream);
|
||||
//assertTrue("Signature did not verify!", signer.verify());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BatchData> readBatch(BatchSpecificationMessage message) {
|
||||
return null; // TODO: Implement this
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer.SQLQueryProvider;
|
|||
import meerkat.protobuf.BulletinBoardAPI.FilterType;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -32,21 +33,72 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
public String getSQLString(QueryType queryType) throws IllegalArgumentException{
|
||||
|
||||
switch(queryType) {
|
||||
|
||||
case ADD_SIGNATURE:
|
||||
return "INSERT IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (:EntryNum, :SignerId, :Signature)";
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES ({0}, {1}, {2})",
|
||||
QueryType.ADD_SIGNATURE.getParamName(0),
|
||||
QueryType.ADD_SIGNATURE.getParamName(1),
|
||||
QueryType.ADD_SIGNATURE.getParamName(2));
|
||||
|
||||
case CONNECT_TAG:
|
||||
return "INSERT IGNORE INTO MsgTagTable (TagId, EntryNum)"
|
||||
+ " SELECT TagTable.TagId, :EntryNum AS EntryNum FROM TagTable WHERE Tag = :Tag";
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO MsgTagTable (TagId, EntryNum)"
|
||||
+ " SELECT TagTable.TagId, {0} AS EntryNum FROM TagTable WHERE Tag = {1}",
|
||||
QueryType.CONNECT_TAG.getParamName(0),
|
||||
QueryType.CONNECT_TAG.getParamName(1));
|
||||
|
||||
case FIND_MSG_ID:
|
||||
return "SELECT EntryNum From MsgTable WHERE MsgId = :MsgId";
|
||||
return MessageFormat.format(
|
||||
"SELECT EntryNum From MsgTable WHERE MsgId = {0}",
|
||||
QueryType.FIND_MSG_ID.getParamName(0));
|
||||
|
||||
case GET_MESSAGES:
|
||||
return "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
|
||||
|
||||
case GET_SIGNATURES:
|
||||
return "SELECT Signature FROM SignatureTable WHERE EntryNum = :EntryNum";
|
||||
return MessageFormat.format(
|
||||
"SELECT Signature FROM SignatureTable WHERE EntryNum = {0}",
|
||||
QueryType.GET_SIGNATURES.getParamName(0));
|
||||
|
||||
case INSERT_MSG:
|
||||
return "INSERT INTO MsgTable (MsgId, Msg) VALUES(:MsgId, :Msg)";
|
||||
return MessageFormat.format(
|
||||
"INSERT INTO MsgTable (MsgId, Msg) VALUES({0}, {1})",
|
||||
QueryType.INSERT_MSG.getParamName(0),
|
||||
QueryType.INSERT_MSG.getParamName(1));
|
||||
|
||||
case INSERT_NEW_TAG:
|
||||
return "INSERT IGNORE INTO TagTable(Tag) VALUES (:Tag)";
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO TagTable(Tag) VALUES ({0})",
|
||||
QueryType.INSERT_NEW_TAG.getParamName(0));
|
||||
|
||||
case GET_BATCH_MESSAGE_ENTRY:
|
||||
return MessageFormat.format(
|
||||
"SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable"
|
||||
+ "INNER JOIN SignatureTable ON MsgTable.EntryNum = SignatureTable.EntryNum"
|
||||
+ "INNER JOIN MsgTagTable ON MsgTable.EntryNum = MsgTagTable.EntryNum"
|
||||
+ "INNER JOIN TagTable ON MsgTagTable.TagId = TagTable.TagId"
|
||||
+ "WHERE SignatureTable.SignerId = {0}"
|
||||
+ "AND TagTable.Tag = {1}",
|
||||
QueryType.GET_BATCH_MESSAGE_ENTRY.getParamName(0),
|
||||
QueryType.GET_BATCH_MESSAGE_ENTRY.getParamName(1));
|
||||
|
||||
case GET_BATCH_MESSAGE_DATA:
|
||||
return MessageFormat.format(
|
||||
"SELECT Data FROM BatchTable"
|
||||
+ " WHERE SignerId = {0} AND BatchId = {1} AND SerialNum >= {2}"
|
||||
+ " ORDER BY SerialNum ASC",
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(0),
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1),
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(2));
|
||||
|
||||
case CHECK_BATCH_LENGTH:
|
||||
return MessageFormat.format(
|
||||
"SELECT COUNT(Data) AS BatchLength FROM BatchTable"
|
||||
+ " WHERE SignerId = {0} AND BatchId = {1}",
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(0),
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1));
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot serve a query of type " + queryType);
|
||||
}
|
||||
|
@ -119,7 +171,8 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
public List<String> getSchemaCreationCommands() {
|
||||
List<String> list = new LinkedList<String>();
|
||||
|
||||
list.add("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INT NOT NULL AUTO_INCREMENT PRIMARY KEY, MsgId TINYBLOB, Msg BLOB, UNIQUE(MsgId(50)))");
|
||||
list.add("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INT NOT NULL AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ " MsgId TINYBLOB, Msg BLOB, UNIQUE(MsgId(50)))");
|
||||
|
||||
list.add("CREATE TABLE IF NOT EXISTS TagTable (TagId INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Tag VARCHAR(50), UNIQUE(Tag))");
|
||||
|
||||
|
@ -129,7 +182,14 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
+ " CONSTRAINT UNIQUE (EntryNum, TagID))");
|
||||
|
||||
list.add("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum INT, SignerId TINYBLOB, Signature TINYBLOB,"
|
||||
+ " INDEX(SignerId(32)), CONSTRAINT Uni UNIQUE(SignerId(32), EntryNum), CONSTRAINT FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
|
||||
+ " INDEX(SignerId(32)), CONSTRAINT Unique_Signature UNIQUE(SignerId(32), EntryNum),"
|
||||
+ " CONSTRAINT FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
|
||||
|
||||
list.add("CREATE TABLE IF NOT EXISTS BatchTable (SignerId TINYBLOB, BatchId INT, SerialNum INT, Data BLOB,"
|
||||
+ " CONSTRAINT Unique_Batch UNIQUE(SignerId(32), BatchId, SerialNum))");
|
||||
|
||||
list.add("CREATE TABLE IF NOT EXISTS BatchTagTable (SignerId TINYBLOB, BatchId INT, TagId INT,"
|
||||
+ " INDEX(SignerId, BatchId), CONSTRAINT FOREIGN KEY (TagId) REFERENCES TagTable(TagId))");
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -138,6 +198,8 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
public List<String> getSchemaDeletionCommands() {
|
||||
List<String> list = new LinkedList<String>();
|
||||
|
||||
list.add("DROP TABLE IF EXISTS BatchTagTable");
|
||||
list.add("DROP TABLE IF EXISTS BatchTable");
|
||||
list.add("DROP TABLE IF EXISTS MsgTagTable");
|
||||
list.add("DROP TABLE IF EXISTS SignatureTable");
|
||||
list.add("DROP TABLE IF EXISTS TagTable");
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package meerkat.bulletinboard.sqlserver.mappers;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BatchData;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 19-Dec-15.
|
||||
*/
|
||||
public class BatchDataMapper implements RowMapper<BatchData> {
|
||||
|
||||
@Override
|
||||
public BatchData mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
return BatchData.newBuilder().setData(ByteString.copyFrom(rs.getBytes(rowNum))).build();
|
||||
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import java.sql.SQLException;
|
|||
/**
|
||||
* Created by Arbel Deutsch Peled on 11-Dec-15.
|
||||
*/
|
||||
public class EntryNumMapper implements RowMapper<Long> {
|
||||
public class LongMapper implements RowMapper<Long> {
|
||||
|
||||
@Override
|
||||
public Long mapRow(ResultSet rs, int rowNum) throws SQLException {
|
|
@ -17,12 +17,11 @@ import meerkat.bulletinboard.sqlserver.H2QueryProvider;
|
|||
import meerkat.bulletinboard.sqlserver.MySQLQueryProvider;
|
||||
import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BoolMsg;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessageList;
|
||||
import meerkat.protobuf.BulletinBoardAPI.MessageFilterList;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.rest.Constants;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Path(Constants.BULLETIN_BOARD_SERVER_PATH)
|
||||
public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextListener{
|
||||
|
||||
|
@ -99,6 +98,58 @@ public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextL
|
|||
return bulletinBoard.readMessages(filterList);
|
||||
}
|
||||
|
||||
@Path(Constants.BEGIN_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg beginBatch(BeginBatchMessage message) {
|
||||
try {
|
||||
return bulletinBoard.beginBatch(message);
|
||||
} catch (CommunicationException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Path(Constants.POST_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg postBatchMessage(BatchMessage batchMessage) {
|
||||
try {
|
||||
return bulletinBoard.postBatchMessage(batchMessage);
|
||||
} catch (CommunicationException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Path(Constants.CLOSE_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg closeBatchMessage(CloseBatchMessage message) {
|
||||
try {
|
||||
return bulletinBoard.closeBatchMessage(message);
|
||||
} catch (CommunicationException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BatchData> readBatch(BatchSpecificationMessage message) {
|
||||
try {
|
||||
return bulletinBoard.readBatch(message);
|
||||
} catch (CommunicationException | IllegalArgumentException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
try {
|
||||
|
|
|
@ -9,13 +9,22 @@ import java.util.List;
|
|||
*/
|
||||
public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
||||
|
||||
public interface ClientCallback<T> {
|
||||
void handleCallback(T msg);
|
||||
void handleFailure(Throwable t);
|
||||
}
|
||||
|
||||
public interface MessageHandler {
|
||||
void handleNewMessages(List<BulletinBoardMessage> messageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a message to the bulletin board in an asynchronous manner
|
||||
* @param msg is the message to be posted
|
||||
* @param callback is a class containing methods to handle the result of the operation
|
||||
* @return a unique message ID for the message, that can be later used to retrieve the batch
|
||||
*/
|
||||
MessageID postMessage(BulletinBoardMessage msg, ClientCallback<?> callback);
|
||||
public MessageID postMessage(BulletinBoardMessage msg, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* This method allows for sending large messages as a batch to the bulletin board
|
||||
|
@ -26,12 +35,12 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
|||
* @param callback is a callback function class for handling results of the operation
|
||||
* @return a unique message ID for the entire message, that can be later used to retrieve the batch
|
||||
*/
|
||||
MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, int startPosition, ClientCallback<?> callback);
|
||||
public MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, int startPosition, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* Overloading of the postBatch method in which startPosition is set to the default value 0
|
||||
*/
|
||||
MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, ClientCallback<?> callback);
|
||||
public MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* Check how "safe" a given message is in an asynchronous manner
|
||||
|
@ -39,7 +48,7 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
|||
* @param id is the unique message identifier for retrieval
|
||||
* @param callback is a callback function class for handling results of the operation
|
||||
*/
|
||||
void getRedundancy(MessageID id, ClientCallback<Float> callback);
|
||||
public void getRedundancy(MessageID id, ClientCallback<Float> callback);
|
||||
|
||||
/**
|
||||
* Read all messages posted matching the given filter in an asynchronous manner
|
||||
|
@ -49,7 +58,7 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
|||
* @param filterList return only messages that match the filters (null means no filtering).
|
||||
* @param callback is a callback function class for handling results of the operation
|
||||
*/
|
||||
void readMessages(MessageFilterList filterList, ClientCallback<List<BulletinBoardMessage>> callback);
|
||||
public void readMessages(MessageFilterList filterList, ClientCallback<List<BulletinBoardMessage>> callback);
|
||||
|
||||
/**
|
||||
* Read a given batch message from the bulletin board
|
||||
|
@ -57,6 +66,13 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
|||
* @param batchId is the unique (per signer) ID of the batch
|
||||
* @param callback is a callback class for handling the result of the operation
|
||||
*/
|
||||
void readBatch(byte[] signerId, int batchId, ClientCallback<SignedBatch> callback);
|
||||
public void readBatch(byte[] signerId, int batchId, ClientCallback<SignedBatch> callback);
|
||||
|
||||
/**
|
||||
* Subscribes to a notifier that will return any new messages on the server that match the given filters
|
||||
* @param filterList defines the set of filters for message retrieval
|
||||
* @param messageHandler defines the handler for new messages received
|
||||
*/
|
||||
public void subscribe(MessageFilterList filterList, MessageHandler messageHandler);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,11 +12,6 @@ import java.util.List;
|
|||
*/
|
||||
public interface BulletinBoardClient {
|
||||
|
||||
interface ClientCallback<T> {
|
||||
void handleCallback(T msg);
|
||||
void handleFailure(Throwable t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the client to use some specified servers
|
||||
* @param clientParams contains the parameters required for the client setup
|
||||
|
|
|
@ -3,40 +3,83 @@ package meerkat.bulletinboard;
|
|||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel on 07/11/15.
|
||||
*
|
||||
* This interface refers to a single instance of a Bulletin Board.
|
||||
* An implementation of this interface may use any DB and be hosted on any machine.
|
||||
* This interface refers to a single instance of a Bulletin Board
|
||||
* An implementation of this interface may use any DB and be hosted on any machine.
|
||||
*/
|
||||
|
||||
public interface BulletinBoardServer{
|
||||
|
||||
/**
|
||||
* This method initializes the server by reading the signature data and storing it.
|
||||
* It also establishes the connection to the DB.
|
||||
* @throws CommunicationException on DB connection error.
|
||||
* This method initializes the server by reading the signature data and storing it
|
||||
* It also establishes the connection to the DB
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public void init(String meerkatDB) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Post a message to bulletin board.
|
||||
* @param msg is the actual (signed) message
|
||||
* @return TRUE if the message has been authenticated and FALSE otherwise (in ProtoBuf form).
|
||||
* @throws CommunicationException on DB connection error.
|
||||
* @return TRUE if the message has been authenticated and FALSE otherwise (in ProtoBuf form)
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Read all messages posted matching the given filter.
|
||||
* @param filter return only messages that match the filter (empty list means no filtering).
|
||||
* Read all messages posted matching the given filter
|
||||
* @param filterList return only messages that match the filters (empty list or null means no filtering)
|
||||
* @return
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException;
|
||||
|
||||
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Informs server about a new batch message
|
||||
* @param message contains the required data about the new batch
|
||||
* @return TRUE if the batch request is accepted amd FALSE otherwise
|
||||
* Specifically, if such a batch already exists and is not yet closed: the value returned will be TRUE
|
||||
* However, if such a batch exists and is already closed: the value returned will be FALSE
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public BoolMsg beginBatch(BeginBatchMessage message) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Posts a (part of a) batch message to the bulletin board
|
||||
* Note that the existence and contents of a batch message are not available for reading before the batch is finalized
|
||||
* @param batchMessage contains the (partial) data this message carries as well as meta-data required in order to place the data
|
||||
* in the correct position inside the correct batch
|
||||
* @return TRUE if the message is accepted and successfully saved and FALSE otherwise
|
||||
* Specifically, if the batch is already closed: the value returned will be FALSE
|
||||
* However, requiring to open a batch before insertion of messages is implementation-dependent
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public BoolMsg postBatchMessage(BatchMessage batchMessage) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Attempts to close and finalize a batch message
|
||||
* @param message contains the data necessary to close the batch; in particular: the signature for the batch
|
||||
* @return TRUE if the batch was successfully closed, FALSE otherwise
|
||||
* Specifically, if the signature is invalid or if some of the batch parts have not yet been submitted: the value returned will be FALSE
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public BoolMsg closeBatchMessage(CloseBatchMessage message) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Reads a batch message from the server (starting with the supplied position)
|
||||
* @param message specifies the signer ID and the batch ID to read as well as an (optional) start position
|
||||
* @return an ordered list of batch messages starting from the specified start position (if given) or from the beginning (if omitted)
|
||||
* @throws CommunicationException on DB connection error
|
||||
* @throws IllegalArgumentException if message does not specify a batch
|
||||
*/
|
||||
public List<BatchData> readBatch(BatchSpecificationMessage message) throws CommunicationException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This method closes the connection to the DB.
|
||||
* @throws CommunicationException on DB connection error.
|
||||
* This method closes the connection to the DB
|
||||
* @throws CommunicationException on DB connection error
|
||||
*/
|
||||
public void close() throws CommunicationException;
|
||||
public void close() throws CommunicationException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package meerkat.crypto;
|
||||
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 18-Dec-15.
|
||||
* Extends the Digest interface with a method for digesting Batch messages
|
||||
*/
|
||||
public interface BatchDigest extends Digest{
|
||||
|
||||
/**
|
||||
* Update the digest with the
|
||||
* @param beginBatchMessage is the message that starts the batch
|
||||
* @param batchDataList is the (ordered) list of data in the batch
|
||||
*/
|
||||
public void update(BeginBatchMessage beginBatchMessage, List<BatchData> batchDataList);
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@ public interface Digest {
|
|||
* (copied from {@link MessageDigest#digest()})
|
||||
* @return
|
||||
*/
|
||||
byte[] digest();
|
||||
public byte[] digest();
|
||||
|
||||
/**
|
||||
* Updates the digest using the specified message (in serialized wire form)
|
||||
|
@ -22,12 +22,12 @@ public interface Digest {
|
|||
* @param msg
|
||||
* @return
|
||||
*/
|
||||
void update(Message msg);
|
||||
public void update(Message msg);
|
||||
|
||||
/**
|
||||
* Resets the digest for further use.
|
||||
*/
|
||||
void reset();
|
||||
public void reset();
|
||||
|
||||
/**
|
||||
* Clone the current digest state
|
||||
|
|
|
@ -30,7 +30,10 @@ import javax.security.auth.callback.UnsupportedCallbackException;
|
|||
*
|
||||
* This class is not thread-safe (each thread should have its own instance).
|
||||
*/
|
||||
public class ECDSASignature extends GlobalCryptoSetup implements DigitalSignature {
|
||||
public class ECDSASignature implements DigitalSignature {
|
||||
|
||||
private static GlobalCryptoSetup globalCryptoSetup = GlobalCryptoSetup.getInstance();
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
final public static String KEYSTORE_TYPE = "PKCS12";
|
||||
|
|
|
@ -31,7 +31,10 @@ import java.util.Random;
|
|||
/**
|
||||
* Created by talm on 17/11/15.
|
||||
*/
|
||||
public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption {
|
||||
public class ECElGamalEncryption implements Encryption {
|
||||
|
||||
private static GlobalCryptoSetup globalCryptoSetup = GlobalCryptoSetup.getInstance();
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public final static String KEY_ALGORITHM = "ECDH";
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package meerkat.crypto.concrete;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.BatchDigest;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 19-Dec-15.
|
||||
*/
|
||||
public abstract class GenericBatchDigest implements BatchDigest{
|
||||
|
||||
|
||||
@Override
|
||||
public void update(BeginBatchMessage beginBatchMessage, List<BatchData> batchDataList) {
|
||||
update(beginBatchMessage);
|
||||
for (BatchData batchData : batchDataList) {
|
||||
update(batchData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// Repeated here to circumvent compiler error
|
||||
public abstract BatchDigest clone() throws CloneNotSupportedException;
|
||||
|
||||
}
|
|
@ -10,13 +10,26 @@ import java.security.Security;
|
|||
/**
|
||||
* A class that performs required crypto setup
|
||||
*/
|
||||
public class GlobalCryptoSetup {
|
||||
public final class GlobalCryptoSetup {
|
||||
|
||||
private static GlobalCryptoSetup globalCryptoSetup;
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(GlobalCryptoSetup.class);
|
||||
|
||||
static boolean loadedBouncyCastle = false;
|
||||
static Provider bouncyCastleProvider;
|
||||
private boolean loadedBouncyCastle = false;
|
||||
private Provider bouncyCastleProvider;
|
||||
|
||||
public static boolean hasSecp256k1Curve() {
|
||||
private GlobalCryptoSetup() { doSetup(); }
|
||||
|
||||
public static GlobalCryptoSetup getInstance() {
|
||||
if (globalCryptoSetup == null) {
|
||||
globalCryptoSetup = new GlobalCryptoSetup();
|
||||
}
|
||||
|
||||
return globalCryptoSetup;
|
||||
}
|
||||
|
||||
public boolean hasSecp256k1Curve() {
|
||||
// For now we just check if the java version is at least 8
|
||||
String[] version = System.getProperty("java.version").split("\\.");
|
||||
int major = Integer.parseInt(version[0]);
|
||||
|
@ -24,9 +37,11 @@ public class GlobalCryptoSetup {
|
|||
return ((major > 1) || ((major > 0) && (minor > 7)));
|
||||
}
|
||||
|
||||
public static Provider getBouncyCastleProvider() { doSetup(); return bouncyCastleProvider; }
|
||||
public Provider getBouncyCastleProvider() {
|
||||
return bouncyCastleProvider;
|
||||
}
|
||||
|
||||
public static synchronized void doSetup() {
|
||||
public void doSetup() {
|
||||
if (bouncyCastleProvider == null) {
|
||||
bouncyCastleProvider = new BouncyCastleProvider();
|
||||
// Make bouncycastle our default provider if we're running on a JVM version < 8
|
||||
|
@ -39,5 +54,4 @@ public class GlobalCryptoSetup {
|
|||
}
|
||||
}
|
||||
|
||||
public GlobalCryptoSetup() { doSetup(); }
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package meerkat.crypto.concrete;
|
|||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.BatchDigest;
|
||||
import meerkat.crypto.Digest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -13,7 +14,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
/**
|
||||
* Created by talm on 11/9/15.
|
||||
*/
|
||||
public class SHA256Digest extends GlobalCryptoSetup implements Digest {
|
||||
public class SHA256Digest extends GenericBatchDigest {
|
||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
public static final String SHA256 = "SHA-256";
|
||||
|
||||
|
|
|
@ -104,4 +104,11 @@ message BatchMessage {
|
|||
int32 batchId = 2; // Unique identifier for the batch (unique per signer)
|
||||
int32 serialNum = 3; // Location of the message in the batch: starting from 0
|
||||
BatchData data = 4; // Actual data
|
||||
}
|
||||
|
||||
// This message defines which batch to read and from which location to start reading
|
||||
message BatchSpecificationMessage {
|
||||
bytes signerId = 1; // Unique signer identifier
|
||||
int32 batchId = 2; // Unique identifier for the batch (unique per signer)
|
||||
int32 startPosition = 3; // Position in batch to start reading from
|
||||
}
|
|
@ -26,6 +26,9 @@ import java.security.spec.InvalidKeySpecException;
|
|||
* utilities for ECElgamal
|
||||
*/
|
||||
public class ECElGamalUtils {
|
||||
|
||||
private static GlobalCryptoSetup globalCryptoSetup = GlobalCryptoSetup.getInstance();
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(ECElGamalUtils.class);
|
||||
|
||||
public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH";
|
||||
|
@ -43,7 +46,7 @@ public class ECElGamalUtils {
|
|||
|
||||
try {
|
||||
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
|
||||
GlobalCryptoSetup.getBouncyCastleProvider());
|
||||
globalCryptoSetup.getBouncyCastleProvider());
|
||||
PublicKey javaPk = fact.generatePublic(pubKeySpec);
|
||||
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
|
||||
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
|
||||
|
|
|
@ -9,4 +9,8 @@ public interface Constants {
|
|||
public static final String BULLETIN_BOARD_SERVER_PATH = "/bbserver";
|
||||
public static final String READ_MESSAGES_PATH = "/readmessages";
|
||||
public static final String POST_MESSAGE_PATH = "/postmessage";
|
||||
public static final String BEGIN_BATCH_PATH = "/beginbatch";
|
||||
public static final String POST_BATCH_PATH = "/postbatch";
|
||||
public static final String CLOSE_BATCH_PATH = "/closebatch";
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue