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