From dbf5727cee8817ba19fb84d8dd03733f8baab7a7 Mon Sep 17 00:00:00 2001 From: Arbel Deutsch Peled Date: Sun, 22 Nov 2015 23:36:24 +0200 Subject: [PATCH] Added Some unit tests and fixed several bugs. --- .../sqlserver/BulletinBoardSQLServer.java | 2 +- .../sqlserver/SQLiteBulletinBoardServer.java | 28 +-- .../BulletinBoardServerTest.java | 33 ++++ .../GenericBulletinBoardServerTest.java | 178 ++++++++++++++++++ .../crypto/concrete/TestECDSASignature.java | 4 +- 5 files changed, 229 insertions(+), 16 deletions(-) create mode 100644 bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardServerTest.java create mode 100644 bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java 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 e121da2..777d3bc 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 @@ -118,7 +118,7 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{ sql = "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)"; pstmt = connection.prepareStatement(sql); pstmt.setBytes(1, msgID); - pstmt.setBytes(2, msg.toByteArray()); + pstmt.setBytes(2, msg.getMsg().toByteArray()); pstmt.executeUpdate(); rs = pstmt.getGeneratedKeys(); diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/SQLiteBulletinBoardServer.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/SQLiteBulletinBoardServer.java index abc87a2..dd86549 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/SQLiteBulletinBoardServer.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/SQLiteBulletinBoardServer.java @@ -24,24 +24,28 @@ public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer { * 2. The database tables (if they do not yet exist). */ + private void createSchema() throws SQLException { + Statement statement = connection.createStatement(); + statement.setQueryTimeout(TIMEOUT); + + statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER PRIMARY KEY, MsgId BLOB UNIQUE, Msg BLOB)"); + + statement.executeUpdate("CREATE TABLE IF NOT EXISTS TagTable (TagId INTEGER PRIMARY KEY, Tag varchar(50) UNIQUE)"); + statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum BLOB, TagId INTEGER, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum), FOREIGN KEY (TagId) REFERENCES TagTable(TagId), UNIQUE (EntryNum, TagID))"); + + statement.executeUpdate("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum BLOB, SignerId BLOB, Signature BLOB UNIQUE, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))"); + statement.executeUpdate("CREATE INDEX IF NOT EXISTS SignerIndex ON SignatureTable(SignerId)"); + + statement.close(); + } + @Override public void init() throws CommunicationException { try{ connection = DriverManager.getConnection("jdbc:sqlite:local-instances/meerkat.db"); - Statement statement = connection.createStatement(); - statement.setQueryTimeout(TIMEOUT); - - statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER PRIMARY KEY, MsgId BLOB UNIQUE, Msg BLOB)"); - - statement.executeUpdate("CREATE TABLE IF NOT EXISTS TagTable (TagId INTEGER PRIMARY KEY, Tag varchar(50) UNIQUE)"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum BLOB, TagId INTEGER, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum), FOREIGN KEY (TagId) REFERENCES TagTable(TagId), UNIQUE (EntryNum, TagID))"); - - statement.executeUpdate("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum BLOB, SignerId BLOB, Signature BLOB UNIQUE, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))"); - statement.executeUpdate("CREATE INDEX IF NOT EXISTS SignerIndex ON SignatureTable(SignerId)"); - - statement.close(); + createSchema(); super.init(); diff --git a/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardServerTest.java b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardServerTest.java new file mode 100644 index 0000000..ff1e48f --- /dev/null +++ b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardServerTest.java @@ -0,0 +1,33 @@ +package meerkat.bulletinboard; + +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.Test; + +import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer; + +public class BulletinBoardServerTest { + + @Test + public void testAllServers(){ + GenericBulletinBoardServerTest bbst = new GenericBulletinBoardServerTest(); + try { + try{ + Path path = Paths.get("local-instances/meerkat.db"); + Files.delete(path); + } catch(NoSuchFileException e){} + + bbst.init(SQLiteBulletinBoardServer.class); + bbst.bulkTest(); + bbst.close(); + + } catch (Exception e) { + System.err.println(e.getMessage() + e.getClass()); + assert false; + } + + } +} diff --git a/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java b/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java new file mode 100644 index 0000000..3130560 --- /dev/null +++ b/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java @@ -0,0 +1,178 @@ +package meerkat.bulletinboard; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.List; + +import com.google.protobuf.ByteString; + +import meerkat.comm.CommunicationException; +import meerkat.crypto.concrete.ECDSASignature; +import meerkat.crypto.concrete.TestECDSASignature; +import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage; +import meerkat.protobuf.BulletinBoardAPI.FilterType; +import meerkat.protobuf.BulletinBoardAPI.MessageFilter; +import meerkat.protobuf.BulletinBoardAPI.MessageFilterList; +import meerkat.protobuf.BulletinBoardAPI.UnsignedBulletinBoardMessage; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; + +public class GenericBulletinBoardServerTest { + private BulletinBoardServer bulletinBoardServer; + private ECDSASignature signers[]; + + private SecureRandom random; + + private static String KEYFILE_EXAMPLE = "/certs/enduser-certs/user1-key-with-password-secret.p12"; + private static String KEYFILE_PASSWORD = "secret"; + + public static String CERT1_PEM_EXAMPLE = "/certs/enduser-certs/user1.crt"; + +// private static String KEYFILE_EXAMPLE2 = "/certs/enduser-certs/user2-key.pem"; + + public void init(Class cls) throws InstantiationException, IllegalAccessException, CertificateException, KeyStoreException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException, CommunicationException{ + bulletinBoardServer = (BulletinBoardServer) cls.newInstance(); + bulletinBoardServer.init(); + + signers = new ECDSASignature[2]; + signers[0] = new ECDSASignature(); + signers[1] = new ECDSASignature(); + + InputStream keyStream = TestECDSASignature.class.getResourceAsStream(KEYFILE_EXAMPLE); + char[] password = KEYFILE_PASSWORD.toCharArray(); + + KeyStore.Builder keyStore = signers[0].getPKCS12KeyStoreBuilder(keyStream, password); + signers[0].loadSigningCertificate(keyStore); + + signers[0].loadVerificationCertificates(TestECDSASignature.class.getResourceAsStream(CERT1_PEM_EXAMPLE)); + + random = new SecureRandom(); + } + + private byte randomByte(){ + return (byte) ((Math.random() * 256) - 128); + } + + private String randomString(){ + return new BigInteger(130, random).toString(32); + } + + public void bulkTest() throws CommunicationException, SignatureException, InvalidKeyException, CertificateException, IOException{ + + final int TAG_NUM = 5; // Number of tags. + final int MESSAGE_NUM = 32; // Number of messages (2^TAG_NUM). + final int BYTES_PER_MESSAGE_DATA = 50; // Message size. + + String[] tags = new String[TAG_NUM]; + byte[][] data = new byte[MESSAGE_NUM][BYTES_PER_MESSAGE_DATA]; + + UnsignedBulletinBoardMessage.Builder unsignedMsgBuilder; + BulletinBoardMessage.Builder msgBuilder; + + int i,j; + + // Generate random data. + + for (i = 1 ; i <= MESSAGE_NUM ; i++){ + for (j = 0 ; j < BYTES_PER_MESSAGE_DATA ; j++){ + data[i-1][j] = randomByte(); + } + } + + for (i = 0 ; i < TAG_NUM ; i++){ + tags[i] = randomString(); + } + + // Build messages. + + for (i = 1 ; i <= MESSAGE_NUM ; i++){ + unsignedMsgBuilder = UnsignedBulletinBoardMessage.newBuilder() + .setData(ByteString.copyFrom(data[i-1])); + + // Add tags based on bit-representation of message number. + + int copyI = i; + for (j = 0 ; j < TAG_NUM ; j++){ + if (copyI % 2 == 1){ + unsignedMsgBuilder.addTag(tags[j]); + } + + copyI >>>= 1; + } + + // Build message. + + msgBuilder = BulletinBoardMessage.newBuilder() + .setMsg(unsignedMsgBuilder.build()); + + // Add signatures. + + if (i % 2 == 1){ + signers[0].updateContent(msgBuilder.getMsg()); + msgBuilder.addSig(signers[0].sign()); + } + + // Post message. + + bulletinBoardServer.postMessage(msgBuilder.build()); + } + + // Check tag mechanism + + for (i = 0 ; i < TAG_NUM ; i++){ + + // Retrieve messages having tag i + + List messages = + bulletinBoardServer.readMessages( + MessageFilterList.newBuilder() + .addFilter(MessageFilter.newBuilder() + .setType(FilterType.TAG) + .setTag(tags[i]) + .build() + ) + .build() + ) + .getMessageList(); + + // Assert that the number of retrieved messages is correct. + + assertThat(messages.size(), is(MESSAGE_NUM / 2)); + + // Assert the identity of the messages. + + for (BulletinBoardMessage msg : messages){ + + // Assert serial number and raw data. + + assertThat((msg.getEntryNum() >>> i) % 2 , is((long) 1)); + assertThat(msg.getMsg().getData().toByteArray(), is(data[(int) msg.getEntryNum() - 1])); + + // Assert signatures. + + if (msg.getEntryNum() % 2 == 1){ + signers[0].initVerify(msg.getSig(0)); + signers[0].updateContent(msg.getMsg()); + assertTrue("Signature did not verify!", signers[0].verify()); + } + } + + } + + } + + public void close(){ + signers[0].clearSigningKey(); + signers[1].clearSigningKey(); + } +} diff --git a/meerkat-common/src/test/meerkat/crypto/concrete/TestECDSASignature.java b/meerkat-common/src/test/meerkat/crypto/concrete/TestECDSASignature.java index 4230e6e..a3a0ec7 100644 --- a/meerkat-common/src/test/meerkat/crypto/concrete/TestECDSASignature.java +++ b/meerkat-common/src/test/meerkat/crypto/concrete/TestECDSASignature.java @@ -2,14 +2,12 @@ package meerkat.crypto.concrete; import com.google.protobuf.ByteString; import meerkat.protobuf.Crypto; +import meerkat.crypto.concrete.ECDSASignature; import meerkat.protobuf.BulletinBoardAPI.*; import org.junit.Test; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.security.KeyStore; -import java.util.Arrays; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue;