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