From b5237d6c9f32b3946cb760bd2ffabe2ed1706dcb Mon Sep 17 00:00:00 2001 From: Arbel Deutsch Peled Date: Mon, 21 Dec 2015 23:16:06 +0200 Subject: [PATCH] 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. --- .../bulletinboard/BulletinClientWorker.java | 9 +- .../SimpleBulletinBoardClient.java | 8 +- .../ThreadedBulletinBoardClient.java | 2 +- .../sqlserver/BulletinBoardSQLServer.java | 117 ++++++++++++++---- .../sqlserver/MySQLQueryProvider.java | 46 +++++-- .../sqlserver/mappers/BatchDataMapper.java | 2 +- .../sqlserver/mappers/StringMapper.java | 18 +++ .../webapp/BulletinBoardWebApp.java | 35 +++--- ...BulletinBoardSQLServerIntegrationTest.java | 9 +- .../AsyncBulletinBoardClient.java | 2 +- .../meerkat/bulletinboard/BatchDigest.java | 20 +++ .../bulletinboard/BatchDigitalSignature.java | 34 +++++ .../bulletinboard/BulletinBoardConstants.java | 21 ++++ .../{SignedBatch.java => CompleteBatch.java} | 26 ++-- .../bulletinboard/GenericBatchDigest.java | 54 ++++++++ .../GenericBatchDigitalSignature.java | 95 ++++++++++++++ .../main/java/meerkat/crypto/BatchDigest.java | 20 --- .../crypto/concrete/GenericBatchDigest.java | 27 ---- .../meerkat/crypto/concrete/SHA256Digest.java | 3 +- .../src/main/java/meerkat/rest/Constants.java | 8 -- 20 files changed, 428 insertions(+), 128 deletions(-) create mode 100644 bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/StringMapper.java create mode 100644 meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigest.java create mode 100644 meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigitalSignature.java create mode 100644 meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardConstants.java rename meerkat-common/src/main/java/meerkat/bulletinboard/{SignedBatch.java => CompleteBatch.java} (50%) create mode 100644 meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigest.java create mode 100644 meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigitalSignature.java delete mode 100644 meerkat-common/src/main/java/meerkat/crypto/BatchDigest.java delete mode 100644 meerkat-common/src/main/java/meerkat/crypto/concrete/GenericBatchDigest.java diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/BulletinClientWorker.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/BulletinClientWorker.java index 51599d5..f03ab31 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/BulletinClientWorker.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/BulletinClientWorker.java @@ -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 { } msg = payload; - requestPath = Constants.POST_MESSAGE_PATH; + requestPath = POST_MESSAGE_PATH; break; case READ_MESSAGES: @@ -111,7 +112,7 @@ public class BulletinClientWorker implements Callable { } msg = payload; - requestPath = Constants.READ_MESSAGES_PATH; + requestPath = READ_MESSAGES_PATH; break; case GET_REDUNDANCY: @@ -120,7 +121,7 @@ public class BulletinClientWorker implements Callable { 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 { // 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 diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java index 4244f15..8cac04d 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java @@ -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)); diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/ThreadedBulletinBoardClient.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/ThreadedBulletinBoardClient.java index 5953bde..71d852e 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/ThreadedBulletinBoardClient.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/ThreadedBulletinBoardClient.java @@ -113,7 +113,7 @@ public class ThreadedBulletinBoardClient extends SimpleBulletinBoardClient imple } @Override - public void readBatch(byte[] signerId, int batchId, ClientCallback callback) { + public void readBatch(byte[] signerId, int batchId, ClientCallback callback) { // TODO: Implement } diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java index 5f9b461..1bb32d8 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java @@ -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 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 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 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 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 readBatch(BatchSpecificationMessage message) { - return null; // TODO: Implement this + public List 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 diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/MySQLQueryProvider.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/MySQLQueryProvider.java index 0093bd5..59e6106 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/MySQLQueryProvider.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/MySQLQueryProvider.java @@ -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; } diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/BatchDataMapper.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/BatchDataMapper.java index 0189584..81e6cda 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/BatchDataMapper.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/BatchDataMapper.java @@ -15,7 +15,7 @@ public class BatchDataMapper implements RowMapper { @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(); } } diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/StringMapper.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/StringMapper.java new file mode 100644 index 0000000..c5b1d85 --- /dev/null +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/mappers/StringMapper.java @@ -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 { + + @Override + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getString(1); + } + +} diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java index 27d7bd5..cab9d6d 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java @@ -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 { diff --git a/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java index 838adcc..4b8b586 100644 --- a/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java +++ b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java @@ -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() diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/AsyncBulletinBoardClient.java b/meerkat-common/src/main/java/meerkat/bulletinboard/AsyncBulletinBoardClient.java index 4d8075e..1663f7a 100644 --- a/meerkat-common/src/main/java/meerkat/bulletinboard/AsyncBulletinBoardClient.java +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/AsyncBulletinBoardClient.java @@ -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 callback); + public void readBatch(byte[] signerId, int batchId, ClientCallback callback); /** * Subscribes to a notifier that will return any new messages on the server that match the given filters diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigest.java b/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigest.java new file mode 100644 index 0000000..6e30fe9 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigest.java @@ -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); + +} diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigitalSignature.java b/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigitalSignature.java new file mode 100644 index 0000000..e04f3c5 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/BatchDigitalSignature.java @@ -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; + +} diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardConstants.java b/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardConstants.java new file mode 100644 index 0000000..7fe3a43 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardConstants.java @@ -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"; + +} diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/SignedBatch.java b/meerkat-common/src/main/java/meerkat/bulletinboard/CompleteBatch.java similarity index 50% rename from meerkat-common/src/main/java/meerkat/bulletinboard/SignedBatch.java rename to meerkat-common/src/main/java/meerkat/bulletinboard/CompleteBatch.java index 46cf07e..6deec77 100644 --- a/meerkat-common/src/main/java/meerkat/bulletinboard/SignedBatch.java +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/CompleteBatch.java @@ -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 batchDataList; private Signature signature; - public SignedBatch() { + public CompleteBatch() { batchDataList = new LinkedList(); } - public SignedBatch(List newDataList) { - this(); + public CompleteBatch(BeginBatchMessage newBeginBatchMessage) { + beginBatchMessage = newBeginBatchMessage; + } + + public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List newDataList) { + this(newBeginBatchMessage); appendBatchData(newDataList); } - public SignedBatch(List newDataList, Signature newSignature) { - this(newDataList); + public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List newDataList, Signature newSignature) { + this(newBeginBatchMessage, newDataList); signature = newSignature; } + public BeginBatchMessage getBeginBatchMessage() { + return beginBatchMessage; + } + public List getBatchDataList() { return batchDataList; } @@ -46,5 +55,8 @@ public class SignedBatch { batchDataList.addAll(newBatchDataList); } + public void setSignature(Signature newSignature) { + signature = newSignature; + } } diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigest.java b/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigest.java new file mode 100644 index 0000000..8171271 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigest.java @@ -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()); + } + +} diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigitalSignature.java b/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigitalSignature.java new file mode 100644 index 0000000..422e8b0 --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/GenericBatchDigitalSignature.java @@ -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(); + } + +} diff --git a/meerkat-common/src/main/java/meerkat/crypto/BatchDigest.java b/meerkat-common/src/main/java/meerkat/crypto/BatchDigest.java deleted file mode 100644 index ff257b2..0000000 --- a/meerkat-common/src/main/java/meerkat/crypto/BatchDigest.java +++ /dev/null @@ -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 batchDataList); - -} diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/GenericBatchDigest.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/GenericBatchDigest.java deleted file mode 100644 index 38b2192..0000000 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/GenericBatchDigest.java +++ /dev/null @@ -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 batchDataList) { - update(beginBatchMessage); - for (BatchData batchData : batchDataList) { - update(batchData); - } - } - - @Override - // Repeated here to circumvent compiler error - public abstract BatchDigest clone() throws CloneNotSupportedException; - -} diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java index ac58f3a..4aac501 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/SHA256Digest.java @@ -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"; diff --git a/restful-api-common/src/main/java/meerkat/rest/Constants.java b/restful-api-common/src/main/java/meerkat/rest/Constants.java index 8215641..2c04248 100644 --- a/restful-api-common/src/main/java/meerkat/rest/Constants.java +++ b/restful-api-common/src/main/java/meerkat/rest/Constants.java @@ -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"; - }