diff --git a/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java b/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java index 0b2226f523..625a125db7 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/P2PDataStorage.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.io.File; +import java.io.Serializable; import java.security.KeyPair; import java.security.PublicKey; import java.util.*; @@ -239,7 +240,7 @@ public class P2PDataStorage implements MessageListener { else sequenceNumber = 0; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(payload, sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(payload, sequenceNumber)); byte[] signature = Sig.sign(ownerStoragePubKey.getPrivate(), hashOfDataAndSeqNr); return new ProtectedData(payload, payload.getTTL(), ownerStoragePubKey.getPublic(), sequenceNumber, signature); } @@ -255,7 +256,7 @@ public class P2PDataStorage implements MessageListener { else sequenceNumber = 0; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(expirableMailboxPayload, sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(expirableMailboxPayload, sequenceNumber)); byte[] signature = Sig.sign(storageSignaturePubKey.getPrivate(), hashOfDataAndSeqNr); return new ProtectedMailboxData(expirableMailboxPayload, expirableMailboxPayload.getTTL(), storageSignaturePubKey.getPublic(), sequenceNumber, signature, receiversPublicKey); @@ -300,7 +301,7 @@ public class P2PDataStorage implements MessageListener { private boolean checkSignature(ProtectedData data) { Log.traceCall(); - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, data.sequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNrPair(data.expirablePayload, data.sequenceNumber)); try { boolean result = Sig.verify(data.ownerStoragePubKey, hashOfDataAndSeqNr, data.signature); if (!result) @@ -368,4 +369,28 @@ public class P2PDataStorage implements MessageListener { return new ByteArray(Hash.getHash(payload)); } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Static class + /////////////////////////////////////////////////////////////////////////////////////////// + + public static class DataAndSeqNrPair implements Serializable { + // data are only used for getting cryptographic hash from both values + private final Serializable data; + private final int sequenceNumber; + + public DataAndSeqNrPair(Serializable data, int sequenceNumber) { + this.data = data; + this.sequenceNumber = sequenceNumber; + } + + @Override + public String toString() { + return "DataAndSeqNr{" + + "data=" + data + + ", sequenceNumber=" + sequenceNumber + + '}'; + } + } + } diff --git a/network/src/main/java/io/bitsquare/p2p/storage/data/DataAndSeqNr.java b/network/src/main/java/io/bitsquare/p2p/storage/data/DataAndSeqNr.java deleted file mode 100644 index 36cc7d3bf6..0000000000 --- a/network/src/main/java/io/bitsquare/p2p/storage/data/DataAndSeqNr.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.bitsquare.p2p.storage.data; - -import java.io.Serializable; - -public class DataAndSeqNr implements Serializable { - // data are only used for getting cryptographic hash from both values - private final Serializable data; - private final int sequenceNumber; - - public DataAndSeqNr(Serializable data, int sequenceNumber) { - this.data = data; - this.sequenceNumber = sequenceNumber; - } - - @Override - public String toString() { - return "DataAndSeqNr{" + - "data=" + data + - ", sequenceNumber=" + sequenceNumber + - '}'; - } -} diff --git a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java b/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java index 241375b1d8..72a892b9f1 100644 --- a/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java +++ b/network/src/test/java/io/bitsquare/p2p/P2PServiceTest.java @@ -10,7 +10,7 @@ import io.bitsquare.p2p.mocks.MockMailboxMessage; import io.bitsquare.p2p.network.LocalhostNetworkNode; import io.bitsquare.p2p.peers.PeerManager; import io.bitsquare.p2p.seed.SeedNode; -import io.bitsquare.p2p.storage.data.DataAndSeqNr; +import io.bitsquare.p2p.storage.P2PDataStorage; import io.bitsquare.p2p.storage.data.ProtectedData; import io.bitsquare.p2p.storage.mocks.MockData; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -175,7 +175,7 @@ public class P2PServiceTest { // try to manipulate seq nr. + pubKey + sig -> fails int sequenceNumberManipulated = origProtectedData.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(origProtectedData.expirablePayload, sequenceNumberManipulated)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(origProtectedData.expirablePayload, sequenceNumberManipulated)); byte[] signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertFalse(p2PService3.removeData(protectedDataManipulated.expirablePayload)); @@ -197,7 +197,7 @@ public class P2PServiceTest { // first he tries to use the orig. pubKey in the data -> fails as pub keys not matching MockData manipulatedData = new MockData("mockData1_manipulated", origData.publicKey); sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); @@ -209,7 +209,7 @@ public class P2PServiceTest { // then he tries to use his pubKey but orig data payload -> fails as pub keys nto matching manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic()); sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); @@ -222,7 +222,7 @@ public class P2PServiceTest { // payload data has adversary's pubKey so he could hijack the owners data manipulatedData = new MockData("mockData1_manipulated", msgSignatureKeyPairAdversary.getPublic()); sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload)); @@ -242,7 +242,7 @@ public class P2PServiceTest { // finally he tries both previous attempts with same data - > same as before manipulatedData = new MockData("mockData1", origData.publicKey); sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(origProtectedData.expirablePayload, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertFalse(p2PService3.addData(protectedDataManipulated.expirablePayload)); @@ -253,7 +253,7 @@ public class P2PServiceTest { manipulatedData = new MockData("mockData1", msgSignatureKeyPairAdversary.getPublic()); sequenceNumberManipulated = 0; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(manipulatedData, sequenceNumberManipulated)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(manipulatedData, sequenceNumberManipulated)); signature = Sig.sign(msgSignatureKeyPairAdversary.getPrivate(), hashOfDataAndSeqNr); protectedDataManipulated = new ProtectedData(manipulatedData, origProtectedData.ttl, msgSignatureKeyPairAdversary.getPublic(), sequenceNumberManipulated, signature); Assert.assertTrue(p2PService3.addData(protectedDataManipulated.expirablePayload)); diff --git a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java index 45ebb3c092..1da9244725 100644 --- a/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java +++ b/network/src/test/java/io/bitsquare/p2p/storage/ProtectedDataStorageTest.java @@ -11,7 +11,6 @@ import io.bitsquare.p2p.mocks.MockMessage; import io.bitsquare.p2p.network.NetworkNode; import io.bitsquare.p2p.peers.Broadcaster; import io.bitsquare.p2p.peers.PeerManager; -import io.bitsquare.p2p.storage.data.DataAndSeqNr; import io.bitsquare.p2p.storage.data.ExpirableMailboxPayload; import io.bitsquare.p2p.storage.data.ProtectedData; import io.bitsquare.p2p.storage.data.ProtectedMailboxData; @@ -103,7 +102,7 @@ public class ProtectedDataStorageTest { Assert.assertEquals(1, dataStorage1.getMap().size()); int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.remove(dataToRemove, null)); @@ -135,7 +134,7 @@ public class ProtectedDataStorageTest { // add with date in future data = dataStorage1.getDataWithSignedSeqNr(mockData, storageSignatureKeyPair1); int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataWithFutureDate = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); dataWithFutureDate.date = new Date(new Date().getTime() + 60 * 60 * sleepTime); @@ -156,63 +155,63 @@ public class ProtectedDataStorageTest { // remove with not updated seq nr -> failure int newSequenceNumber = 0; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); byte[] signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertFalse(dataStorage1.remove(dataToRemove, null)); // remove with too high updated seq nr -> ok newSequenceNumber = 2; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.remove(dataToRemove, null)); // add to empty map, any seq nr. -> ok newSequenceNumber = 2; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.add(dataToAdd, null)); // add with updated seq nr below previous -> failure newSequenceNumber = 1; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertFalse(dataStorage1.add(dataToAdd, null)); // add with updated seq nr over previous -> ok newSequenceNumber = 3; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.add(dataToAdd, null)); // add with same seq nr -> failure newSequenceNumber = 3; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertFalse(dataStorage1.add(dataToAdd, null)); // add with same data but higher seq nr. -> ok, ignore newSequenceNumber = 4; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.add(dataToAdd, null)); // remove with with same seq nr as prev. ignored -> failed newSequenceNumber = 4; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertFalse(dataStorage1.remove(dataToRemove, null)); // remove with with higher seq nr -> ok newSequenceNumber = 5; - hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = Sig.sign(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.remove(dataToRemove, null)); @@ -237,7 +236,7 @@ public class ProtectedDataStorageTest { // receiver (storageSignatureKeyPair2) int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = Hash.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = Hash.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); byte[] signature; ProtectedMailboxData dataToRemove; @@ -283,7 +282,7 @@ public class ProtectedDataStorageTest { // hackers key pair is storageSignatureKeyPair2 // change seq nr. and signature: fails on both own and peers dataStorage int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = cryptoService2.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = cryptoService2.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); byte[] signature = cryptoService2.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertFalse(dataStorage1.add(dataToAdd, null)); @@ -291,7 +290,7 @@ public class ProtectedDataStorageTest { // change seq nr. and signature and data pub key. fails on peers dataStorage, succeeds on own dataStorage newSequenceNumber = data.sequenceNumber + 2; - hashOfDataAndSeqNr = cryptoService2.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = cryptoService2.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = cryptoService2.signStorageData(storageSignatureKeyPair2.getPrivate(), hashOfDataAndSeqNr); dataToAdd = new ProtectedData(data.expirablePayload, data.ttl, storageSignatureKeyPair2.getPublic(), newSequenceNumber, signature); Assert.assertTrue(dataStorage2.add(dataToAdd, null)); @@ -305,7 +304,7 @@ public class ProtectedDataStorageTest { Assert.assertNotEquals(data, dataToAdd); newSequenceNumber = data.sequenceNumber + 3; - hashOfDataAndSeqNr = cryptoService1.getHash(new DataAndSeqNr(data.expirablePayload, newSequenceNumber)); + hashOfDataAndSeqNr = cryptoService1.getHash(new P2PDataStorage.DataAndSeqNrPair(data.expirablePayload, newSequenceNumber)); signature = cryptoService1.signStorageData(storageSignatureKeyPair1.getPrivate(), hashOfDataAndSeqNr); ProtectedData dataToRemove = new ProtectedData(data.expirablePayload, data.ttl, data.ownerStoragePubKey, newSequenceNumber, signature); Assert.assertTrue(dataStorage1.remove(dataToRemove, null)); @@ -328,7 +327,7 @@ public class ProtectedDataStorageTest { // receiver (storageSignatureKeyPair2) int newSequenceNumber = data.sequenceNumber + 1; - byte[] hashOfDataAndSeqNr = cryptoService2.getHash(new DataAndSeqNr(expirableMailboxPayload, newSequenceNumber)); + byte[] hashOfDataAndSeqNr = cryptoService2.getHash(new P2PDataStorage.DataAndSeqNrPair(expirableMailboxPayload, newSequenceNumber)); byte[] signature; ProtectedMailboxData dataToRemove;