diff --git a/api/net/sf/briar/api/crypto/CryptoComponent.java b/api/net/sf/briar/api/crypto/CryptoComponent.java index 6997072e54f7cad5c056a2e03dedafbf64d50d61..6b98dfad8902562933786c37f3ec797a261a7a87 100644 --- a/api/net/sf/briar/api/crypto/CryptoComponent.java +++ b/api/net/sf/briar/api/crypto/CryptoComponent.java @@ -2,6 +2,7 @@ package net.sf.briar.api.crypto; import java.security.KeyPair; import java.security.MessageDigest; +import java.security.SecureRandom; import java.security.Signature; import javax.crypto.Cipher; @@ -36,5 +37,7 @@ public interface CryptoComponent { MessageDigest getMessageDigest(); + SecureRandom getSecureRandom(); + Signature getSignature(); } diff --git a/api/net/sf/briar/api/protocol/Message.java b/api/net/sf/briar/api/protocol/Message.java index 252c73caa263529f584e571b4fa7722aa3ffc79c..5af513d283ad1c15714a996aaf0c2c1310d2b873 100644 --- a/api/net/sf/briar/api/protocol/Message.java +++ b/api/net/sf/briar/api/protocol/Message.java @@ -13,6 +13,9 @@ public interface Message { /** The maximum length of a signature in bytes. */ static final int MAX_SIGNATURE_LENGTH = 100; + /** The length of the random salt in bytes. */ + static final int SALT_LENGTH = 8; + /** Returns the message's unique identifier. */ MessageId getId(); diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java index 57ac876e5835953910d87ef7ebe02845bd0e8a01..352182701aa8460d82807dfae682a7c554042b86 100644 --- a/components/net/sf/briar/crypto/CryptoComponentImpl.java +++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java @@ -8,6 +8,7 @@ import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.util.Arrays; @@ -205,6 +206,11 @@ class CryptoComponentImpl implements CryptoComponent { } } + public SecureRandom getSecureRandom() { + // FIXME: Implement a PRNG (pony/rainbow/nyancat generator) + return new SecureRandom(); + } + public Signature getSignature() { try { return Signature.getInstance(SIGNATURE_ALGO, PROVIDER); diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java index 55ca48a4bfc811e162f518b9550815be2f6dabd9..5ecded11a1ede734b11829ace4446777f1625df0 100644 --- a/components/net/sf/briar/db/DatabaseComponentImpl.java +++ b/components/net/sf/briar/db/DatabaseComponentImpl.java @@ -178,7 +178,7 @@ DatabaseCleaner.Callback { */ protected boolean storeGroupMessage(Txn txn, Message m, ContactId sender) throws DbException { - if(m.getGroup() == null) throw new IllegalArgumentException(); + assert m.getGroup() != null; boolean stored = db.addGroupMessage(txn, m); // Mark the message as seen by the sender MessageId id = m.getId(); @@ -228,7 +228,8 @@ DatabaseCleaner.Callback { */ protected boolean storePrivateMessage(Txn txn, Message m, ContactId c, boolean incoming) throws DbException { - if(m.getGroup() != null) throw new IllegalArgumentException(); + assert m.getGroup() == null; + assert m.getAuthor() == null; if(!db.addPrivateMessage(txn, m, c)) return false; MessageId id = m.getId(); if(incoming) db.setStatus(txn, c, id, Status.SEEN); diff --git a/components/net/sf/briar/protocol/MessageEncoderImpl.java b/components/net/sf/briar/protocol/MessageEncoderImpl.java index f36e94a2227304131a2979c2b7ada59a8571f0a8..1c3a386c3b48ccadbee800c4c8475b27ab1cb9e1 100644 --- a/components/net/sf/briar/protocol/MessageEncoderImpl.java +++ b/components/net/sf/briar/protocol/MessageEncoderImpl.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.PrivateKey; +import java.security.SecureRandom; import java.security.Signature; import net.sf.briar.api.crypto.CryptoComponent; @@ -23,12 +24,14 @@ import com.google.inject.Inject; class MessageEncoderImpl implements MessageEncoder { private final Signature signature; + private final SecureRandom random; private final MessageDigest messageDigest; private final WriterFactory writerFactory; @Inject MessageEncoderImpl(CryptoComponent crypto, WriterFactory writerFactory) { signature = crypto.getSignature(); + random = crypto.getSecureRandom(); messageDigest = crypto.getMessageDigest(); this.writerFactory = writerFactory; } @@ -79,6 +82,9 @@ class MessageEncoderImpl implements MessageEncoder { if(author == null) w.writeNull(); else author.writeTo(w); w.writeInt64(timestamp); + byte[] salt = new byte[Message.SALT_LENGTH]; + random.nextBytes(salt); + w.writeBytes(salt); w.writeBytes(body); // Sign the message with the author's private key, if there is one if(authorKey == null) { diff --git a/components/net/sf/briar/protocol/MessageReader.java b/components/net/sf/briar/protocol/MessageReader.java index cdcef062c9b264935b2e521d8b8f881c5e175e76..30339c245356850b999dd751cd54399b97e5ccaf 100644 --- a/components/net/sf/briar/protocol/MessageReader.java +++ b/components/net/sf/briar/protocol/MessageReader.java @@ -79,6 +79,9 @@ class MessageReader implements ObjectReader<Message> { // Read the timestamp long timestamp = r.readInt64(); if(timestamp < 0L) throw new FormatException(); + // Read the salt + byte[] salt = r.readBytes(Message.SALT_LENGTH); + if(salt.length != Message.SALT_LENGTH) throw new FormatException(); // Skip the message body r.readBytes(Message.MAX_BODY_LENGTH); // Record the length of the data covered by the author's signature