diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go
index ec22f0d1d0b64ba1145864bc09dba55150344518..96c4b0e6c4924f152cd76b445f5f02f0c812ab39 100644
--- a/whisper/whisperv5/api.go
+++ b/whisper/whisperv5/api.go
@@ -104,7 +104,7 @@ func (api *PublicWhisperAPI) Info(ctx context.Context) Info {
 	stats := api.w.Stats()
 	return Info{
 		Memory:         stats.memoryUsed,
-		Messages:        len(api.w.messageQueue) + len(api.w.p2pMsgQueue),
+		Messages:       len(api.w.messageQueue) + len(api.w.p2pMsgQueue),
 		MinPow:         api.w.MinPow(),
 		MaxMessageSize: api.w.MaxMessageSize(),
 	}
diff --git a/whisper/whisperv5/config.go b/whisper/whisperv5/config.go
index 290bf8962b0b7ba8162a80b8de499cbf83503702..fcc2307046aacbd10c820d444fe7499a3d29e4ce 100644
--- a/whisper/whisperv5/config.go
+++ b/whisper/whisperv5/config.go
@@ -25,5 +25,3 @@ var DefaultConfig = Config{
 	MaxMessageSize:     DefaultMaxMessageSize,
 	MinimumAcceptedPOW: DefaultMinimumPoW,
 }
-
-var ()
diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go
index d571160d7fc094af4dbd7f09901ad9cd893a57a2..b5e893e0ff5c026d57c13449a7698b1439866560 100644
--- a/whisper/whisperv5/filter.go
+++ b/whisper/whisperv5/filter.go
@@ -22,6 +22,7 @@ import (
 	"sync"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/log"
 )
 
@@ -68,6 +69,10 @@ func (fs *Filters) Install(watcher *Filter) (string, error) {
 		return "", fmt.Errorf("failed to generate unique ID")
 	}
 
+	if watcher.expectsSymmetricEncryption() {
+		watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
+	}
+
 	fs.watchers[id] = watcher
 	return id, err
 }
@@ -119,7 +124,9 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
 
 		if match && msg != nil {
 			log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
-			watcher.Trigger(msg)
+			if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) {
+				watcher.Trigger(msg)
+			}
 		}
 	}
 }
@@ -172,9 +179,6 @@ func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
 	if f.PoW > 0 && msg.PoW < f.PoW {
 		return false
 	}
-	if f.Src != nil && !IsPubKeyEqual(msg.Src, f.Src) {
-		return false
-	}
 
 	if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() {
 		return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) && f.MatchTopic(msg.Topic)
diff --git a/whisper/whisperv5/filter_test.go b/whisper/whisperv5/filter_test.go
index 4ce87eee2215ce7c8344f56017707d135a899a06..bd35e7f20f584afb97f5c93be86f760cc3998f6b 100644
--- a/whisper/whisperv5/filter_test.go
+++ b/whisper/whisperv5/filter_test.go
@@ -132,6 +132,103 @@ func TestInstallFilters(t *testing.T) {
 	}
 }
 
+func TestInstallSymKeyGeneratesHash(t *testing.T) {
+	InitSingleTest()
+
+	w := New(&Config{})
+	filters := NewFilters(w)
+	filter, _ := generateFilter(t, true)
+
+	// save the current SymKeyHash for comparison
+	initialSymKeyHash := filter.SymKeyHash
+
+	// ensure the SymKeyHash is invalid, for Install to recreate it
+	var invalid common.Hash
+	filter.SymKeyHash = invalid
+
+	_, err := filters.Install(filter)
+
+	if err != nil {
+		t.Fatalf("Error installing the filter: %s", err)
+	}
+
+	for i, b := range filter.SymKeyHash {
+		if b != initialSymKeyHash[i] {
+			t.Fatalf("The filter's symmetric key hash was not properly generated by Install")
+		}
+	}
+}
+
+func TestInstallIdenticalFilters(t *testing.T) {
+	InitSingleTest()
+
+	w := New(&Config{})
+	filters := NewFilters(w)
+	filter1, _ := generateFilter(t, true)
+
+	// Copy the first filter since some of its fields
+	// are randomly gnerated.
+	filter2 := &Filter{
+		KeySym:   filter1.KeySym,
+		Topics:   filter1.Topics,
+		PoW:      filter1.PoW,
+		AllowP2P: filter1.AllowP2P,
+		Messages: make(map[common.Hash]*ReceivedMessage),
+	}
+
+	_, err := filters.Install(filter1)
+
+	if err != nil {
+		t.Fatalf("Error installing the first filter with seed %d: %s", seed, err)
+	}
+
+	_, err = filters.Install(filter2)
+
+	if err != nil {
+		t.Fatalf("Error installing the second filter with seed %d: %s", seed, err)
+	}
+
+	params, err := generateMessageParams()
+	if err != nil {
+		t.Fatalf("Error generating message parameters with seed %d: %s", seed, err)
+	}
+
+	params.KeySym = filter1.KeySym
+	params.Topic = BytesToTopic(filter1.Topics[0])
+
+	filter1.Src = &params.Src.PublicKey
+	filter2.Src = &params.Src.PublicKey
+
+	sentMessage, err := NewSentMessage(params)
+	if err != nil {
+		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
+	}
+	env, err := sentMessage.Wrap(params)
+	if err != nil {
+		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
+	}
+	msg := env.Open(filter1)
+	if msg == nil {
+		t.Fatalf("failed to Open with filter1")
+	}
+
+	if !filter1.MatchEnvelope(env) {
+		t.Fatalf("failed matching with the first filter")
+	}
+
+	if !filter2.MatchEnvelope(env) {
+		t.Fatalf("failed matching with the first filter")
+	}
+
+	if !filter1.MatchMessage(msg) {
+		t.Fatalf("failed matching with the second filter")
+	}
+
+	if !filter2.MatchMessage(msg) {
+		t.Fatalf("failed matching with the second filter")
+	}
+}
+
 func TestComparePubKey(t *testing.T) {
 	InitSingleTest()
 
@@ -345,11 +442,6 @@ func TestMatchMessageSym(t *testing.T) {
 		t.Fatalf("failed Open with seed %d.", seed)
 	}
 
-	// Src mismatch
-	if f.MatchMessage(msg) {
-		t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed)
-	}
-
 	// Src: match
 	*f.Src.X = *params.Src.PublicKey.X
 	*f.Src.Y = *params.Src.PublicKey.Y
@@ -443,11 +535,6 @@ func TestMatchMessageAsym(t *testing.T) {
 		t.Fatalf("failed to open with seed %d.", seed)
 	}
 
-	// Src mismatch
-	if f.MatchMessage(msg) {
-		t.Fatalf("failed MatchMessage(src mismatch) with seed %d.", seed)
-	}
-
 	// Src: match
 	*f.Src.X = *params.Src.PublicKey.X
 	*f.Src.Y = *params.Src.PublicKey.Y
diff --git a/whisper/whisperv5/whisper_test.go b/whisper/whisperv5/whisper_test.go
index 025be5b544bf01b6abba8b639084e5efc4e39d05..8af085292acf3cf260d9dfeeccf99da7759f3ec9 100644
--- a/whisper/whisperv5/whisper_test.go
+++ b/whisper/whisperv5/whisper_test.go
@@ -22,6 +22,8 @@ import (
 	mrand "math/rand"
 	"testing"
 	"time"
+
+	"github.com/ethereum/go-ethereum/common"
 )
 
 func TestWhisperBasic(t *testing.T) {
@@ -624,3 +626,226 @@ func TestCustomization(t *testing.T) {
 		t.Fatalf("failed to get whisper messages")
 	}
 }
+
+func TestSymmetricSendCycle(t *testing.T) {
+	InitSingleTest()
+
+	w := New(&DefaultConfig)
+	defer w.SetMinimumPoW(DefaultMinimumPoW)
+	defer w.SetMaxMessageSize(DefaultMaxMessageSize)
+	w.Start(nil)
+	defer w.Stop()
+
+	filter1, err := generateFilter(t, true)
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+	filter1.PoW = DefaultMinimumPoW
+
+	// Copy the first filter since some of its fields
+	// are randomly gnerated.
+	filter2 := &Filter{
+		KeySym:   filter1.KeySym,
+		Topics:   filter1.Topics,
+		PoW:      filter1.PoW,
+		AllowP2P: filter1.AllowP2P,
+		Messages: make(map[common.Hash]*ReceivedMessage),
+	}
+
+	params, err := generateMessageParams()
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+
+	filter1.Src = &params.Src.PublicKey
+	filter2.Src = &params.Src.PublicKey
+
+	params.KeySym = filter1.KeySym
+	params.Topic = BytesToTopic(filter1.Topics[2])
+	params.PoW = filter1.PoW
+	params.WorkTime = 10
+	params.TTL = 50
+	msg, err := NewSentMessage(params)
+	if err != nil {
+		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
+	}
+	env, err := msg.Wrap(params)
+	if err != nil {
+		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
+	}
+
+	_, err = w.Subscribe(filter1)
+	if err != nil {
+		t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err)
+	}
+
+	_, err = w.Subscribe(filter2)
+	if err != nil {
+		t.Fatalf("failed subscribe 2 with seed %d: %s.", seed, err)
+	}
+
+	err = w.Send(env)
+	if err != nil {
+		t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err)
+	}
+
+	// wait till received or timeout
+	var received bool
+	for j := 0; j < 200; j++ {
+		time.Sleep(10 * time.Millisecond)
+		if len(w.Envelopes()) > 0 {
+			received = true
+			break
+		}
+	}
+
+	if !received {
+		t.Fatalf("did not receive the sent envelope, seed: %d.", seed)
+	}
+
+	// check w.messages()
+	time.Sleep(5 * time.Millisecond)
+	mail1 := filter1.Retrieve()
+	mail2 := filter2.Retrieve()
+	if len(mail2) == 0 {
+		t.Fatalf("did not receive any email for filter 2")
+	}
+	if len(mail1) == 0 {
+		t.Fatalf("did not receive any email for filter 1")
+	}
+
+}
+
+func TestSymmetricSendWithoutAKey(t *testing.T) {
+	InitSingleTest()
+
+	w := New(&DefaultConfig)
+	defer w.SetMinimumPoW(DefaultMinimumPoW)
+	defer w.SetMaxMessageSize(DefaultMaxMessageSize)
+	w.Start(nil)
+	defer w.Stop()
+
+	filter, err := generateFilter(t, true)
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+	filter.PoW = DefaultMinimumPoW
+
+	params, err := generateMessageParams()
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+
+	filter.Src = nil
+
+	params.KeySym = filter.KeySym
+	params.Topic = BytesToTopic(filter.Topics[2])
+	params.PoW = filter.PoW
+	params.WorkTime = 10
+	params.TTL = 50
+	msg, err := NewSentMessage(params)
+	if err != nil {
+		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
+	}
+	env, err := msg.Wrap(params)
+	if err != nil {
+		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
+	}
+
+	_, err = w.Subscribe(filter)
+	if err != nil {
+		t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err)
+	}
+
+	err = w.Send(env)
+	if err != nil {
+		t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err)
+	}
+
+	// wait till received or timeout
+	var received bool
+	for j := 0; j < 200; j++ {
+		time.Sleep(10 * time.Millisecond)
+		if len(w.Envelopes()) > 0 {
+			received = true
+			break
+		}
+	}
+
+	if !received {
+		t.Fatalf("did not receive the sent envelope, seed: %d.", seed)
+	}
+
+	// check w.messages()
+	time.Sleep(5 * time.Millisecond)
+	mail := filter.Retrieve()
+	if len(mail) == 0 {
+		t.Fatalf("did not receive message in spite of not setting a public key")
+	}
+}
+
+func TestSymmetricSendKeyMismatch(t *testing.T) {
+	InitSingleTest()
+
+	w := New(&DefaultConfig)
+	defer w.SetMinimumPoW(DefaultMinimumPoW)
+	defer w.SetMaxMessageSize(DefaultMaxMessageSize)
+	w.Start(nil)
+	defer w.Stop()
+
+	filter, err := generateFilter(t, true)
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+	filter.PoW = DefaultMinimumPoW
+
+	params, err := generateMessageParams()
+	if err != nil {
+		t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err)
+	}
+
+	params.KeySym = filter.KeySym
+	params.Topic = BytesToTopic(filter.Topics[2])
+	params.PoW = filter.PoW
+	params.WorkTime = 10
+	params.TTL = 50
+	msg, err := NewSentMessage(params)
+	if err != nil {
+		t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
+	}
+	env, err := msg.Wrap(params)
+	if err != nil {
+		t.Fatalf("failed Wrap with seed %d: %s.", seed, err)
+	}
+
+	_, err = w.Subscribe(filter)
+	if err != nil {
+		t.Fatalf("failed subscribe 1 with seed %d: %s.", seed, err)
+	}
+
+	err = w.Send(env)
+	if err != nil {
+		t.Fatalf("Failed sending envelope with PoW %.06f (seed %d): %s", env.PoW(), seed, err)
+	}
+
+	// wait till received or timeout
+	var received bool
+	for j := 0; j < 200; j++ {
+		time.Sleep(10 * time.Millisecond)
+		if len(w.Envelopes()) > 0 {
+			received = true
+			break
+		}
+	}
+
+	if !received {
+		t.Fatalf("did not receive the sent envelope, seed: %d.", seed)
+	}
+
+	// check w.messages()
+	time.Sleep(5 * time.Millisecond)
+	mail := filter.Retrieve()
+	if len(mail) > 0 {
+		t.Fatalf("received a message when keys weren't matching")
+	}
+}