diff --git a/channels/send.go b/channels/send.go
index 8764a04634b3409bb19cfc9f338206b1547b56c5..26188aa8889483784adb22002bee126114aae903 100644
--- a/channels/send.go
+++ b/channels/send.go
@@ -10,6 +10,7 @@ package channels
 import (
 	"bytes"
 	"crypto/ed25519"
+	"crypto/hmac"
 	"encoding/base64"
 	"fmt"
 	"time"
@@ -60,10 +61,12 @@ const (
 	// SendAdminReplayTag is the base tag used when generating a debug tag for an
 	// admin replay message.
 	SendAdminReplayTag = "ChAdminReplay"
+
+	// The size of the nonce used in the message ID.
+	messageNonceSize = 4
 )
 
-// The size of the nonce used in the message ID.
-const messageNonceSize = 4
+var emptyChannelID = &id.ID{}
 
 // Prints current time without the monotonic clock (m=) for easier reading
 func dateNow() string { return netTime.Now().Round(0).String() }
@@ -93,6 +96,11 @@ func (m *manager) SendGeneric(channelID *id.ID, messageType MessageType,
 	msg []byte, validUntil time.Duration, tracked bool, params cmix.CMIXParams) (
 	message.ID, rounds.Round, ephemeral.Id, error) {
 
+	if hmac.Equal(channelID.Bytes(), emptyChannelID.Bytes()) {
+		return message.ID{}, rounds.Round{}, ephemeral.Id{},
+			errors.New("cannot send to channel id with all 0s")
+	}
+
 	// Reject the send if the user is muted in the channel they are sending to
 	if m.events.mutedUsers.isMuted(channelID, m.me.PubKey) {
 		return message.ID{}, rounds.Round{}, ephemeral.Id{},
@@ -386,6 +394,11 @@ func (m *manager) SendAdminGeneric(channelID *id.ID, messageType MessageType,
 	msg []byte, validUntil time.Duration, tracked bool, params cmix.CMIXParams) (
 	message.ID, rounds.Round, ephemeral.Id, error) {
 
+	if hmac.Equal(channelID.Bytes(), emptyChannelID.Bytes()) {
+		return message.ID{}, rounds.Round{}, ephemeral.Id{},
+			errors.New("cannot send to channel id with all 0s")
+	}
+
 	// Note: We log sends on exit, and append what happened to the message
 	// this cuts down on clutter in the log.
 	log := fmt.Sprintf(
diff --git a/channels/send_test.go b/channels/send_test.go
index f30bdef8d2fc32c9bd4a3e6b9a0999cee88d2cd3..ccf81e715266c4a9189f1426e648c42791684ec4 100644
--- a/channels/send_test.go
+++ b/channels/send_test.go
@@ -64,7 +64,9 @@ func Test_manager_SendGeneric(t *testing.T) {
 		}, crng),
 	}
 
-	channelID := new(id.ID)
+	rng := crng.GetStream()
+	defer rng.Close()
+	channelID, _ := id.NewRandomID(rng, id.User)
 	messageType := Text
 	msg := []byte("hello world")
 	validUntil := time.Hour
@@ -215,7 +217,9 @@ func Test_manager_SendMessage(t *testing.T) {
 		}, crng),
 	}
 
-	channelID := new(id.ID)
+	rng := crng.GetStream()
+	defer rng.Close()
+	channelID, _ := id.NewRandomID(rng, id.User)
 	messageType := Text
 	msg := "hello world"
 	validUntil := time.Hour
@@ -300,7 +304,9 @@ func Test_manager_SendReply(t *testing.T) {
 		}, crng),
 	}
 
-	channelID := new(id.ID)
+	rng := crng.GetStream()
+	defer rng.Close()
+	channelID, _ := id.NewRandomID(rng, id.User)
 	messageType := Text
 	msg := "hello world"
 	validUntil := time.Hour
@@ -387,7 +393,9 @@ func Test_manager_SendReaction(t *testing.T) {
 		}, crng),
 	}
 
-	channelID := new(id.ID)
+	rng := crng.GetStream()
+	defer rng.Close()
+	channelID, _ := id.NewRandomID(rng, id.User)
 	messageType := Reaction
 	msg := "🍆"
 	params := new(cmix.CMIXParams)
diff --git a/dm/send.go b/dm/send.go
index acab686c3ec372a3dc5b84ed154dffb1972b4f44..a2cae2a88c11e90ff5a78129635b3eaacd3912a2 100644
--- a/dm/send.go
+++ b/dm/send.go
@@ -54,6 +54,11 @@ const (
 	messageNonceSize = 4
 )
 
+var (
+	emptyPubKeyBytes = make([]byte, ed25519.PublicKeySize)
+	emptyPubKey      = ed25519.PublicKey(emptyPubKeyBytes)
+)
+
 // SendText is used to send a formatted message to another user.
 func (dc *dmClient) SendText(partnerPubKey *ed25519.PublicKey,
 	partnerToken uint32,
@@ -156,6 +161,21 @@ func (dc *dmClient) Send(partnerEdwardsPubKey *ed25519.PublicKey,
 	params cmix.CMIXParams) (
 	cryptoMessage.ID, rounds.Round, ephemeral.Id, error) {
 
+	if partnerToken == 0 {
+		return cryptoMessage.ID{}, rounds.Round{},
+			ephemeral.Id{},
+			errors.Errorf("invalid dmToken value: %d", partnerToken)
+
+	}
+
+	if partnerEdwardsPubKey == nil ||
+		partnerEdwardsPubKey.Equal(emptyPubKey) {
+		return cryptoMessage.ID{}, rounds.Round{},
+			ephemeral.Id{},
+			errors.Errorf("invalid public key value: %v",
+				partnerEdwardsPubKey)
+	}
+
 	partnerPubKey := ecdh.Edwards2ECDHNIKEPublicKey(partnerEdwardsPubKey)
 
 	partnerID := deriveReceptionID(partnerPubKey.Bytes(), partnerToken)