Implemented (untested) batch messages in Bulletin Board Server (MySQL implementation only).
Implemented generic batch message signatures and digests. Created new interface for Bulletin Board constants.Bulletin-Board-Batch
parent
37f962d520
commit
b5237d6c9f
|
@ -8,6 +8,7 @@ import meerkat.protobuf.BulletinBoardAPI.*;
|
|||
import meerkat.rest.Constants;
|
||||
import meerkat.rest.ProtobufMessageBodyReader;
|
||||
import meerkat.rest.ProtobufMessageBodyWriter;
|
||||
import static meerkat.bulletinboard.BulletinBoardConstants.*;
|
||||
|
||||
import javax.ws.rs.ProcessingException;
|
||||
import javax.ws.rs.client.Client;
|
||||
|
@ -101,7 +102,7 @@ public class BulletinClientWorker implements Callable<BulletinClientJobResult> {
|
|||
}
|
||||
|
||||
msg = payload;
|
||||
requestPath = Constants.POST_MESSAGE_PATH;
|
||||
requestPath = POST_MESSAGE_PATH;
|
||||
break;
|
||||
|
||||
case READ_MESSAGES:
|
||||
|
@ -111,7 +112,7 @@ public class BulletinClientWorker implements Callable<BulletinClientJobResult> {
|
|||
}
|
||||
|
||||
msg = payload;
|
||||
requestPath = Constants.READ_MESSAGES_PATH;
|
||||
requestPath = READ_MESSAGES_PATH;
|
||||
break;
|
||||
|
||||
case GET_REDUNDANCY:
|
||||
|
@ -120,7 +121,7 @@ public class BulletinClientWorker implements Callable<BulletinClientJobResult> {
|
|||
throw new IllegalArgumentException("Cannot search for an object that is not an instance of MessageID");
|
||||
}
|
||||
|
||||
requestPath = Constants.READ_MESSAGES_PATH;
|
||||
requestPath = READ_MESSAGES_PATH;
|
||||
|
||||
msg = MessageFilterList.newBuilder()
|
||||
.addFilter(MessageFilter.newBuilder()
|
||||
|
@ -144,7 +145,7 @@ public class BulletinClientWorker implements Callable<BulletinClientJobResult> {
|
|||
|
||||
// Send request to Server
|
||||
String address = addressIterator.next();
|
||||
webTarget = client.target(address).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(requestPath);
|
||||
webTarget = client.target(address).path(BULLETIN_BOARD_SERVER_PATH).path(requestPath);
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
|
||||
|
||||
// Retrieve answer
|
||||
|
|
|
@ -16,6 +16,8 @@ import javax.ws.rs.client.Entity;
|
|||
import javax.ws.rs.client.WebTarget;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import static meerkat.bulletinboard.BulletinBoardConstants.*;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 05-Dec-15.
|
||||
* Implements BulletinBoardClient interface in a simple, straightforward manner
|
||||
|
@ -61,7 +63,7 @@ public class SimpleBulletinBoardClient implements BulletinBoardClient{
|
|||
// Post message to all databases
|
||||
try {
|
||||
for (String db : meerkatDBs) {
|
||||
webTarget = client.target(db).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(Constants.POST_MESSAGE_PATH);
|
||||
webTarget = client.target(db).path(BULLETIN_BOARD_SERVER_PATH).path(POST_MESSAGE_PATH);
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
|
||||
|
||||
// Only consider valid responses
|
||||
|
@ -104,7 +106,7 @@ public class SimpleBulletinBoardClient implements BulletinBoardClient{
|
|||
|
||||
for (String db : meerkatDBs) {
|
||||
try {
|
||||
webTarget = client.target(db).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(Constants.READ_MESSAGES_PATH);
|
||||
webTarget = client.target(db).path(BULLETIN_BOARD_SERVER_PATH).path(READ_MESSAGES_PATH);
|
||||
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF));
|
||||
|
||||
|
@ -138,7 +140,7 @@ public class SimpleBulletinBoardClient implements BulletinBoardClient{
|
|||
|
||||
for (String db : meerkatDBs) {
|
||||
try {
|
||||
webTarget = client.target(db).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(Constants.READ_MESSAGES_PATH);
|
||||
webTarget = client.target(db).path(BULLETIN_BOARD_SERVER_PATH).path(READ_MESSAGES_PATH);
|
||||
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF));
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ public class ThreadedBulletinBoardClient extends SimpleBulletinBoardClient imple
|
|||
}
|
||||
|
||||
@Override
|
||||
public void readBatch(byte[] signerId, int batchId, ClientCallback<SignedBatch> callback) {
|
||||
public void readBatch(byte[] signerId, int batchId, ClientCallback<CompleteBatch> callback) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package meerkat.bulletinboard.sqlserver;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
@ -8,13 +9,12 @@ import java.util.*;
|
|||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.ProtocolStringList;
|
||||
|
||||
import meerkat.bulletinboard.BulletinBoardServer;
|
||||
import meerkat.bulletinboard.*;
|
||||
import meerkat.bulletinboard.sqlserver.mappers.*;
|
||||
import static meerkat.bulletinboard.BulletinBoardConstants.*;
|
||||
|
||||
import meerkat.comm.CommunicationException;
|
||||
|
||||
import meerkat.crypto.BatchDigest;
|
||||
import meerkat.crypto.DigitalSignature;
|
||||
import meerkat.crypto.concrete.ECDSASignature;
|
||||
import meerkat.crypto.concrete.SHA256Digest;
|
||||
|
||||
|
@ -62,7 +62,9 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
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"});
|
||||
CONNECT_BATCH_TAG(new String[] {"SignerId", "BatchId", "Tag"}),
|
||||
GET_BATCH_TAGS(new String[] {"SignerId", "BatchId"}),
|
||||
MOVE_BATCH_TAGS(new String[] {"EntryNum", "SignerId", "BatchId"});
|
||||
|
||||
private String[] paramNames;
|
||||
|
||||
|
@ -219,7 +221,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
protected NamedParameterJdbcTemplate jdbcTemplate;
|
||||
|
||||
protected BatchDigest digest;
|
||||
protected DigitalSignature signer;
|
||||
protected BatchDigitalSignature signer;
|
||||
|
||||
protected List<SignatureVerificationKey> trusteeSignatureVerificationArray;
|
||||
protected int minTrusteeSignatures;
|
||||
|
@ -257,8 +259,8 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
public void init(String meerkatDB) throws CommunicationException {
|
||||
// TODO write signature reading part.
|
||||
|
||||
digest = new SHA256Digest();
|
||||
signer = new ECDSASignature();
|
||||
digest = new GenericBatchDigest(new SHA256Digest());
|
||||
signer = new GenericBatchDigitalSignature(new ECDSASignature());
|
||||
|
||||
jdbcTemplate = new NamedParameterJdbcTemplate(sqlQueryProvider.getDataSource());
|
||||
|
||||
|
@ -356,7 +358,7 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
} else{
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.INSERT_MSG);
|
||||
namedParameters.put(QueryType.INSERT_MSG.getParamName(0), msg.getMsg().toByteArray());
|
||||
namedParameters.put(QueryType.INSERT_MSG.getParamName(1), msg.getMsg().toByteArray());
|
||||
|
||||
KeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
jdbcTemplate.update(sql,new MapSqlParameterSource(namedParameters),keyHolder);
|
||||
|
@ -585,13 +587,19 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
@Override
|
||||
public BoolMsg closeBatchMessage(CloseBatchMessage message) throws CommunicationException {
|
||||
|
||||
ByteString signerId = message.getSig().getSignerId();
|
||||
int batchId = message.getBatchId();
|
||||
|
||||
KeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
|
||||
// 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());
|
||||
|
||||
namedParameters.addValue(QueryType.CHECK_BATCH_LENGTH.getParamName(0),signerId);
|
||||
namedParameters.addValue(QueryType.CHECK_BATCH_LENGTH.getParamName(1),batchId);
|
||||
|
||||
List<Long> lengthResult = jdbcTemplate.query(sql, namedParameters, new LongMapper());
|
||||
|
||||
|
@ -599,34 +607,99 @@ public class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
// Check signature
|
||||
|
||||
// Get Tags and add them to CompleteBatch
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.GET_BATCH_TAGS);
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.GET_BATCH_TAGS.getParamName(0),signerId);
|
||||
namedParameters.addValue(QueryType.GET_BATCH_TAGS.getParamName(1),batchId);
|
||||
|
||||
List<String> tags = jdbcTemplate.query(sql, namedParameters, new StringMapper());
|
||||
|
||||
CompleteBatch completeBatch = new CompleteBatch(
|
||||
BeginBatchMessage.newBuilder()
|
||||
.setSignerId(signerId)
|
||||
.setBatchId(batchId)
|
||||
.addAllTag(tags)
|
||||
.build()
|
||||
);
|
||||
|
||||
// Add actual batch data to CompleteBatch
|
||||
|
||||
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(0),signerId);
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1),batchId);
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(2),0); // Read from the beginning
|
||||
|
||||
List<BatchData> batchDataList = jdbcTemplate.query(sql, namedParameters, new BatchDataMapper());
|
||||
completeBatch.appendBatchData(jdbcTemplate.query(sql, namedParameters, new BatchDataMapper()));
|
||||
|
||||
// Verify signature
|
||||
|
||||
completeBatch.setSignature(message.getSig());
|
||||
|
||||
try {
|
||||
signer.initVerify(message.getSig());
|
||||
} catch (CertificateException | InvalidKeyException e) {
|
||||
signer.verify(completeBatch);
|
||||
} catch (CertificateException | InvalidKeyException | SignatureException e) {
|
||||
return BoolMsg.newBuilder().setValue(false).build();
|
||||
}
|
||||
|
||||
//TODO: FInish this
|
||||
// Batch verified: finalize it
|
||||
|
||||
//signer.updateContent(msgStream);
|
||||
//assertTrue("Signature did not verify!", signer.verify());
|
||||
// Calculate message ID
|
||||
digest.reset();
|
||||
digest.update(completeBatch);
|
||||
MessageID msgID = MessageID.newBuilder().setID(ByteString.copyFrom(digest.digest())).build();
|
||||
|
||||
return null;
|
||||
// Create Bulletin Board message
|
||||
BulletinBoardMessage bulletinBoardMessage = BulletinBoardMessage.newBuilder()
|
||||
.addSig(message.getSig())
|
||||
.setMsg(UnsignedBulletinBoardMessage.newBuilder()
|
||||
.addAllTag(tags)
|
||||
.addTag(BATCH_TAG)
|
||||
.setData(message.getSig().getSignerId())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.INSERT_MSG);
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.INSERT_MSG.getParamName(0), msgID);
|
||||
namedParameters.addValue(QueryType.INSERT_MSG.getParamName(1), bulletinBoardMessage);
|
||||
|
||||
jdbcTemplate.update(sql, namedParameters, keyHolder);
|
||||
long entryNum = keyHolder.getKey().longValue();
|
||||
|
||||
sql = sqlQueryProvider.getSQLString(QueryType.MOVE_BATCH_TAGS);
|
||||
namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.MOVE_BATCH_TAGS.getParamName(0), entryNum);
|
||||
namedParameters.addValue(QueryType.MOVE_BATCH_TAGS.getParamName(1), signerId);
|
||||
namedParameters.addValue(QueryType.MOVE_BATCH_TAGS.getParamName(2), batchId);
|
||||
|
||||
jdbcTemplate.update(sql, namedParameters);
|
||||
|
||||
return BoolMsg.newBuilder().setValue(true).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BatchData> readBatch(BatchSpecificationMessage message) {
|
||||
return null; // TODO: Implement this
|
||||
public List<BatchData> readBatch(BatchSpecificationMessage message) throws CommunicationException, IllegalArgumentException{
|
||||
|
||||
// Check that batch is closed
|
||||
if (!isBatchClosed(message.getSignerId(), message.getBatchId())) {
|
||||
throw new IllegalArgumentException("No such batch");
|
||||
}
|
||||
|
||||
String sql = sqlQueryProvider.getSQLString(QueryType.GET_BATCH_MESSAGE_DATA);
|
||||
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
|
||||
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(0),message.getSignerId());
|
||||
namedParameters.addValue(QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1),message.getBatchId());
|
||||
|
||||
return jdbcTemplate.query(sql, namedParameters, new BatchDataMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,7 +36,7 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
|
||||
case ADD_SIGNATURE:
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES ({0}, {1}, {2})",
|
||||
"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));
|
||||
|
@ -44,13 +44,13 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
case CONNECT_TAG:
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO MsgTagTable (TagId, EntryNum)"
|
||||
+ " SELECT TagTable.TagId, {0} AS EntryNum FROM TagTable WHERE Tag = {1}",
|
||||
+ " 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 MessageFormat.format(
|
||||
"SELECT EntryNum From MsgTable WHERE MsgId = {0}",
|
||||
"SELECT EntryNum From MsgTable WHERE MsgId = :{0}",
|
||||
QueryType.FIND_MSG_ID.getParamName(0));
|
||||
|
||||
case GET_MESSAGES:
|
||||
|
@ -58,18 +58,18 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
|
||||
case GET_SIGNATURES:
|
||||
return MessageFormat.format(
|
||||
"SELECT Signature FROM SignatureTable WHERE EntryNum = {0}",
|
||||
"SELECT Signature FROM SignatureTable WHERE EntryNum = :{0}",
|
||||
QueryType.GET_SIGNATURES.getParamName(0));
|
||||
|
||||
case INSERT_MSG:
|
||||
return MessageFormat.format(
|
||||
"INSERT INTO MsgTable (MsgId, Msg) VALUES({0}, {1})",
|
||||
"INSERT INTO MsgTable (MsgId, Msg) VALUES(:{0}, :{1})",
|
||||
QueryType.INSERT_MSG.getParamName(0),
|
||||
QueryType.INSERT_MSG.getParamName(1));
|
||||
|
||||
case INSERT_NEW_TAG:
|
||||
return MessageFormat.format(
|
||||
"INSERT IGNORE INTO TagTable(Tag) VALUES ({0})",
|
||||
"INSERT IGNORE INTO TagTable(Tag) VALUES (:{0})",
|
||||
QueryType.INSERT_NEW_TAG.getParamName(0));
|
||||
|
||||
case GET_BATCH_MESSAGE_ENTRY:
|
||||
|
@ -78,15 +78,15 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
+ "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}",
|
||||
+ "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}"
|
||||
+ " 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),
|
||||
|
@ -95,10 +95,34 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
case CHECK_BATCH_LENGTH:
|
||||
return MessageFormat.format(
|
||||
"SELECT COUNT(Data) AS BatchLength FROM BatchTable"
|
||||
+ " WHERE SignerId = {0} AND BatchId = {1}",
|
||||
+ " WHERE SignerId = :{0} AND BatchId = :{1}",
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(0),
|
||||
QueryType.GET_BATCH_MESSAGE_DATA.getParamName(1));
|
||||
|
||||
case CONNECT_BATCH_TAG:
|
||||
return MessageFormat.format(
|
||||
"INSERT INTO BatchTagTable (SignerId, BatchId, TagId) SELECT :{0}, :{1}, TagId FROM TagTable"
|
||||
+ " WHERE Tag = :{2}",
|
||||
QueryType.CONNECT_BATCH_TAG.getParamName(0),
|
||||
QueryType.CONNECT_BATCH_TAG.getParamName(1),
|
||||
QueryType.CONNECT_BATCH_TAG.getParamName(2));
|
||||
|
||||
case GET_BATCH_TAGS:
|
||||
return MessageFormat.format(
|
||||
"SELECT Tag FROM TagTable INNER JOIN BatchTagTable ON TagTable.TagId = BatchTagTable.Tag ID"
|
||||
+ " WHERE SignerId = :{0} AND BatchId = :{1} ORDER BY Tag ASC",
|
||||
QueryType.GET_BATCH_TAGS.getParamName(0),
|
||||
QueryType.GET_BATCH_TAGS.getParamName(1));
|
||||
|
||||
case MOVE_BATCH_TAGS:
|
||||
return MessageFormat.format(
|
||||
"INSERT INTO MsgTagTable (EntryNum, TagId) "
|
||||
+ " SELECT {0}, TagId FROM BatchTagTable WHERE SignerId = {1} AND BatchId = {2};"
|
||||
+ " DELETE FROM BatchTagTable WHERE SignerId = {1} AND BatchId = {2}",
|
||||
QueryType.GET_BATCH_TAGS.getParamName(0),
|
||||
QueryType.GET_BATCH_TAGS.getParamName(1),
|
||||
QueryType.GET_BATCH_TAGS.getParamName(2));
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot serve a query of type " + queryType);
|
||||
}
|
||||
|
@ -189,7 +213,7 @@ public class MySQLQueryProvider implements SQLQueryProvider {
|
|||
+ " 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))");
|
||||
+ " INDEX(SignerId(32), BatchId), CONSTRAINT FOREIGN KEY (TagId) REFERENCES TagTable(TagId))");
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ 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();
|
||||
return BatchData.newBuilder().setData(ByteString.copyFrom(rs.getBytes(1))).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package meerkat.bulletinboard.sqlserver.mappers;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 20-Dec-15.
|
||||
*/
|
||||
public class StringMapper implements RowMapper<String> {
|
||||
|
||||
@Override
|
||||
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return rs.getString(1);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,11 +18,12 @@ import meerkat.bulletinboard.sqlserver.MySQLQueryProvider;
|
|||
import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.rest.Constants;
|
||||
import static meerkat.bulletinboard.BulletinBoardConstants.*;
|
||||
import static meerkat.rest.Constants.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Path(Constants.BULLETIN_BOARD_SERVER_PATH)
|
||||
@Path(BULLETIN_BOARD_SERVER_PATH)
|
||||
public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextListener{
|
||||
|
||||
private static final String BULLETIN_BOARD_ATTRIBUTE_NAME = "bulletinBoard";
|
||||
|
@ -78,30 +79,30 @@ public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextL
|
|||
}
|
||||
}
|
||||
|
||||
@Path(Constants.POST_MESSAGE_PATH)
|
||||
@Path(POST_MESSAGE_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Consumes(MEDIATYPE_PROTOBUF)
|
||||
@Produces(MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||
init();
|
||||
return bulletinBoard.postMessage(msg);
|
||||
}
|
||||
|
||||
@Path(Constants.READ_MESSAGES_PATH)
|
||||
@Path(READ_MESSAGES_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Consumes(MEDIATYPE_PROTOBUF)
|
||||
@Produces(MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException {
|
||||
init();
|
||||
return bulletinBoard.readMessages(filterList);
|
||||
}
|
||||
|
||||
@Path(Constants.BEGIN_BATCH_PATH)
|
||||
@Path(BEGIN_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Consumes(MEDIATYPE_PROTOBUF)
|
||||
@Produces(MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg beginBatch(BeginBatchMessage message) {
|
||||
try {
|
||||
|
@ -112,10 +113,10 @@ public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextL
|
|||
}
|
||||
}
|
||||
|
||||
@Path(Constants.POST_BATCH_PATH)
|
||||
@Path(POST_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Consumes(MEDIATYPE_PROTOBUF)
|
||||
@Produces(MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg postBatchMessage(BatchMessage batchMessage) {
|
||||
try {
|
||||
|
@ -126,10 +127,10 @@ public class BulletinBoardWebApp implements BulletinBoardServer, ServletContextL
|
|||
}
|
||||
}
|
||||
|
||||
@Path(Constants.CLOSE_BATCH_PATH)
|
||||
@Path(CLOSE_BATCH_PATH)
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Consumes(MEDIATYPE_PROTOBUF)
|
||||
@Produces(MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg closeBatchMessage(CloseBatchMessage message) {
|
||||
try {
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.google.protobuf.TextFormat;
|
|||
|
||||
import meerkat.protobuf.Crypto.*;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import static meerkat.bulletinboard.BulletinBoardConstants.*;
|
||||
import meerkat.rest.Constants;
|
||||
import meerkat.rest.ProtobufMessageBodyReader;
|
||||
import meerkat.rest.ProtobufMessageBodyWriter;
|
||||
|
@ -54,8 +55,8 @@ public class BulletinBoardSQLServerIntegrationTest {
|
|||
|
||||
// Test writing mechanism
|
||||
|
||||
System.err.println("******** Testing: " + Constants.POST_MESSAGE_PATH);
|
||||
webTarget = client.target(BASE_URL).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(Constants.POST_MESSAGE_PATH);
|
||||
System.err.println("******** Testing: " + POST_MESSAGE_PATH);
|
||||
webTarget = client.target(BASE_URL).path(BULLETIN_BOARD_SERVER_PATH).path(POST_MESSAGE_PATH);
|
||||
System.err.println(webTarget.getUri());
|
||||
|
||||
msg = BulletinBoardMessage.newBuilder()
|
||||
|
@ -101,8 +102,8 @@ public class BulletinBoardSQLServerIntegrationTest {
|
|||
|
||||
// Test reading mechanism
|
||||
|
||||
System.err.println("******** Testing: " + Constants.READ_MESSAGES_PATH);
|
||||
webTarget = client.target(BASE_URL).path(Constants.BULLETIN_BOARD_SERVER_PATH).path(Constants.READ_MESSAGES_PATH);
|
||||
System.err.println("******** Testing: " + READ_MESSAGES_PATH);
|
||||
webTarget = client.target(BASE_URL).path(BULLETIN_BOARD_SERVER_PATH).path(READ_MESSAGES_PATH);
|
||||
filterList = MessageFilterList.newBuilder()
|
||||
.addFilter(
|
||||
MessageFilter.newBuilder()
|
||||
|
|
|
@ -66,7 +66,7 @@ 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
|
||||
*/
|
||||
public void readBatch(byte[] signerId, int batchId, ClientCallback<SignedBatch> callback);
|
||||
public void readBatch(byte[] signerId, int batchId, ClientCallback<CompleteBatch> callback);
|
||||
|
||||
/**
|
||||
* Subscribes to a notifier that will return any new messages on the server that match the given filters
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import meerkat.crypto.Digest;
|
||||
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 batch message data (ignore the signature)
|
||||
* @param completeBatch is the batch message that needs to be digested
|
||||
*/
|
||||
public void update(CompleteBatch completeBatch);
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import meerkat.crypto.DigitalSignature;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BeginBatchMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BatchData;
|
||||
import meerkat.protobuf.Crypto.Signature;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 20-Dec-15.
|
||||
* Extends the DigitalSignature interface with methods for signing and authenticating Batch messages
|
||||
*/
|
||||
public interface BatchDigitalSignature extends DigitalSignature {
|
||||
|
||||
/**
|
||||
* Appends the batch data to the signed content (ignoring the signature)
|
||||
* @param completeBatch contains all the data about the batch
|
||||
* @throws SignatureException
|
||||
*/
|
||||
public void updateContent(CompleteBatch completeBatch) throws SignatureException;
|
||||
|
||||
/**
|
||||
* Performs a complete verification process on the given batch message
|
||||
* @param completeBatch contains the batch data as well as the signature
|
||||
* @return TRUE if the batch is verified and FALSE otherwise
|
||||
* @throws SignatureException | SignatureException | InvalidKeyException when underlying methods do so
|
||||
*/
|
||||
public boolean verify(CompleteBatch completeBatch) throws SignatureException, CertificateException, InvalidKeyException;
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 21-Dec-15.
|
||||
*/
|
||||
public interface BulletinBoardConstants {
|
||||
|
||||
// Relative addresses for Bulletin Board operations
|
||||
|
||||
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";
|
||||
|
||||
// Other Constants
|
||||
|
||||
public static final String BATCH_TAG = "Batch";
|
||||
|
||||
}
|
|
@ -9,27 +9,36 @@ import java.util.List;
|
|||
/**
|
||||
* Created by Arbel Deutsch Peled on 14-Dec-15.
|
||||
*
|
||||
* A data structure for holding both a batch message and its signature
|
||||
* A data structure for holding a complete batch message along with its signature
|
||||
*/
|
||||
public class SignedBatch {
|
||||
public class CompleteBatch {
|
||||
|
||||
private BeginBatchMessage beginBatchMessage;
|
||||
private List<BatchData> batchDataList;
|
||||
private Signature signature;
|
||||
|
||||
public SignedBatch() {
|
||||
public CompleteBatch() {
|
||||
batchDataList = new LinkedList<BatchData>();
|
||||
}
|
||||
|
||||
public SignedBatch(List<BatchData> newDataList) {
|
||||
this();
|
||||
public CompleteBatch(BeginBatchMessage newBeginBatchMessage) {
|
||||
beginBatchMessage = newBeginBatchMessage;
|
||||
}
|
||||
|
||||
public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List<BatchData> newDataList) {
|
||||
this(newBeginBatchMessage);
|
||||
appendBatchData(newDataList);
|
||||
}
|
||||
|
||||
public SignedBatch(List<BatchData> newDataList, Signature newSignature) {
|
||||
this(newDataList);
|
||||
public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List<BatchData> newDataList, Signature newSignature) {
|
||||
this(newBeginBatchMessage, newDataList);
|
||||
signature = newSignature;
|
||||
}
|
||||
|
||||
public BeginBatchMessage getBeginBatchMessage() {
|
||||
return beginBatchMessage;
|
||||
}
|
||||
|
||||
public List<BatchData> getBatchDataList() {
|
||||
return batchDataList;
|
||||
}
|
||||
|
@ -46,5 +55,8 @@ public class SignedBatch {
|
|||
batchDataList.addAll(newBatchDataList);
|
||||
}
|
||||
|
||||
public void setSignature(Signature newSignature) {
|
||||
signature = newSignature;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.Digest;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BeginBatchMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BatchData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 19-Dec-15.
|
||||
* Wrapper class for digesting Batches in a standardized way
|
||||
*/
|
||||
public class GenericBatchDigest implements BatchDigest{
|
||||
|
||||
private Digest digest;
|
||||
|
||||
public GenericBatchDigest(Digest digest) {
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(CompleteBatch completeBatch) {
|
||||
|
||||
update(completeBatch.getBeginBatchMessage());
|
||||
|
||||
for (BatchData batchData : completeBatch.getBatchDataList()) {
|
||||
update(batchData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] digest() {
|
||||
return digest.digest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Message msg) {
|
||||
digest.update(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
digest.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericBatchDigest clone() throws CloneNotSupportedException{
|
||||
return new GenericBatchDigest(digest.clone());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.DigitalSignature;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BeginBatchMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BatchData;
|
||||
import meerkat.protobuf.Crypto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SignatureException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 20-Dec-15.
|
||||
* Wrapper class for signing and verifying Batch signatures in a standardized way
|
||||
*/
|
||||
public class GenericBatchDigitalSignature implements BatchDigitalSignature{
|
||||
|
||||
private DigitalSignature digitalSignature;
|
||||
|
||||
public GenericBatchDigitalSignature(DigitalSignature digitalSignature) {
|
||||
this.digitalSignature = digitalSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateContent(CompleteBatch completeBatch) throws SignatureException {
|
||||
|
||||
digitalSignature.updateContent(completeBatch.getBeginBatchMessage());
|
||||
for (BatchData batchData : completeBatch.getBatchDataList()) {
|
||||
digitalSignature.updateContent(batchData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(CompleteBatch completeBatch) throws SignatureException, CertificateException, InvalidKeyException {
|
||||
|
||||
digitalSignature.initVerify(completeBatch.getSignature());
|
||||
updateContent(completeBatch);
|
||||
return digitalSignature.verify();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadVerificationCertificates(InputStream certStream) throws CertificateException {
|
||||
digitalSignature.loadVerificationCertificates(certStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVerificationCertificates() {
|
||||
digitalSignature.clearVerificationCertificates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateContent(Message msg) throws SignatureException {
|
||||
digitalSignature.updateContent(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Crypto.Signature sign() throws SignatureException {
|
||||
return digitalSignature.sign();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initVerify(Crypto.Signature sig) throws CertificateException, InvalidKeyException {
|
||||
digitalSignature.initVerify(sig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify() {
|
||||
return digitalSignature.verify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) throws IOException, CertificateException, UnrecoverableKeyException {
|
||||
digitalSignature.loadSigningCertificate(keyStoreBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteString getSignerID() {
|
||||
return digitalSignature.getSignerID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSigningKey() {
|
||||
digitalSignature.clearSigningKey();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
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);
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
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;
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@ 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;
|
||||
|
@ -14,7 +13,7 @@ import java.security.NoSuchAlgorithmException;
|
|||
/**
|
||||
* Created by talm on 11/9/15.
|
||||
*/
|
||||
public class SHA256Digest extends GenericBatchDigest {
|
||||
public class SHA256Digest implements Digest {
|
||||
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
public static final String SHA256 = "SHA-256";
|
||||
|
||||
|
|
|
@ -5,12 +5,4 @@ package meerkat.rest;
|
|||
*/
|
||||
public interface Constants {
|
||||
public static final String MEDIATYPE_PROTOBUF = "application/x-protobuf";
|
||||
|
||||
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