diff --git a/api/params.go b/api/params.go
index 6430eb60c5860be420c11b0715da0c960ddbc5e5..39f9d8db3768ac00c454bf89d2ba8b5326c9fb4e 100644
--- a/api/params.go
+++ b/api/params.go
@@ -8,6 +8,7 @@
 package api
 
 import (
+	"encoding/json"
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
 )
@@ -23,3 +24,16 @@ func GetDefaultParams() Params {
 		Session: session.GetDefaultParams(),
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
diff --git a/api/params_test.go b/api/params_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..35bf61d8f10e5b494a8459f64d239d1569df36b4
--- /dev/null
+++ b/api/params_test.go
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package api
+
+import (
+	"bytes"
+	"encoding/json"
+	"testing"
+)
+
+// Tests that no data is lost when marshaling and
+// unmarshaling the Params object.
+func TestParams_MarshalUnmarshal(t *testing.T) {
+	// Construct a set of params
+	p := GetDefaultParams()
+
+	// Marshal the params
+	data, err := json.Marshal(&p)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data))
+
+	// Unmarshal the params object
+	received := Params{}
+	err = json.Unmarshal(data, &received)
+	if err != nil {
+		t.Fatalf("Unmarshal error: %v", err)
+	}
+
+	// Re-marshal this params object
+	data2, err := json.Marshal(received)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data2))
+
+	// Check that they match (it is done this way to avoid
+	// false failures with the reflect.DeepEqual function and
+	// pointers)
+	if !bytes.Equal(data, data2) {
+		t.Fatalf("Data was lost in marshal/unmarshal.")
+	}
+}
diff --git a/auth/params.go b/auth/params.go
index 92cb6e57de8f1e39efafccfc8d8d93ce5f30b917..907fa4ad825c3c6ef068d9dc7e6cd8b92d70a773 100644
--- a/auth/params.go
+++ b/auth/params.go
@@ -1,18 +1,44 @@
 package auth
 
-import "gitlab.com/elixxir/client/catalog"
+import (
+	"encoding/json"
+	"gitlab.com/elixxir/client/catalog"
+)
 
-type Param struct {
-	ReplayRequests bool
+// Params is are the parameters for the auth package.
+type Params struct {
+	ReplayRequests  bool
+	RequestTag      string
+	ConfirmTag      string
+	ResetRequestTag string
+	ResetConfirmTag string
+}
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	ReplayRequests  bool
 	RequestTag      string
 	ConfirmTag      string
 	ResetRequestTag string
 	ResetConfirmTag string
 }
 
-func GetDefaultParams() Param {
-	return Param{
+// GetParameters Obtain default Params, or override with
+// given parameters if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// GetDefaultParams returns a default set of Params.
+func GetDefaultParams() Params {
+	return Params{
 		ReplayRequests:  false,
 		RequestTag:      catalog.Request,
 		ConfirmTag:      catalog.Confirm,
@@ -21,7 +47,7 @@ func GetDefaultParams() Param {
 	}
 }
 
-func GetDefaultTemporaryParams() Param {
+func GetDefaultTemporaryParams() Params {
 	p := GetDefaultParams()
 	p.RequestTag = catalog.RequestEphemeral
 	p.ConfirmTag = catalog.ConfirmEphemeral
@@ -30,7 +56,38 @@ func GetDefaultTemporaryParams() Param {
 	return p
 }
 
-func (p Param) getConfirmTag(reset bool) string {
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		ReplayRequests:  p.ReplayRequests,
+		RequestTag:      p.ResetRequestTag,
+		ConfirmTag:      p.ConfirmTag,
+		ResetRequestTag: p.RequestTag,
+		ResetConfirmTag: p.ResetConfirmTag,
+	}
+	return json.Marshal(&pDisk)
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		ReplayRequests:  pDisk.ReplayRequests,
+		RequestTag:      pDisk.ResetRequestTag,
+		ConfirmTag:      pDisk.ConfirmTag,
+		ResetRequestTag: pDisk.RequestTag,
+		ResetConfirmTag: pDisk.ResetConfirmTag,
+	}
+
+	return nil
+}
+
+func (p Params) getConfirmTag(reset bool) string {
 	if reset {
 		return p.ResetConfirmTag
 	} else {
diff --git a/auth/state.go b/auth/state.go
index 2be3d4d6b3a63f0b9706a1bcccbf862828cc06d5..859b4015e3bc4beda1d5fe80dc78c70ea9d0af02 100644
--- a/auth/state.go
+++ b/auth/state.go
@@ -41,7 +41,7 @@ type state struct {
 	store *store.Store
 	event event.Reporter
 
-	params Param
+	params Params
 
 	backupTrigger func(reason string)
 }
@@ -101,7 +101,7 @@ type Callbacks interface {
 //   with a memory only versioned.KV) as well as a memory only versioned.KV for
 //   NewState and use GetDefaultTemporaryParams() for the parameters
 func NewState(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
-	rng *fastRNG.StreamGenerator, event event.Reporter, params Param,
+	rng *fastRNG.StreamGenerator, event event.Reporter, params Params,
 	callbacks Callbacks, backupTrigger func(reason string)) (State, error) {
 	kv = kv.Prefix(makeStorePrefix(e2e.GetReceptionID()))
 	return NewStateLegacy(
@@ -114,7 +114,7 @@ func NewState(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
 // Does not modify the kv prefix for backwards compatibility
 // Otherwise, acts the same as NewState
 func NewStateLegacy(kv *versioned.KV, net cmix.Client, e2e e2e.Handler,
-	rng *fastRNG.StreamGenerator, event event.Reporter, params Param,
+	rng *fastRNG.StreamGenerator, event event.Reporter, params Params,
 	callbacks Callbacks, backupTrigger func(reason string)) (State, error) {
 
 	s := &state{
diff --git a/auth/state_test.go b/auth/state_test.go
index 8b7e7305c4a198194ef0444ed59013c8dac4f3dc..10ebb2d3ed4d9d99c654da78dfacc260a877a771 100644
--- a/auth/state_test.go
+++ b/auth/state_test.go
@@ -146,7 +146,7 @@ func TestManager_ReplayRequests(t *testing.T) {
 		rng:   fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
 		store: s,
 		event: &mockEventManager{},
-		params: Param{
+		params: Params{
 			ReplayRequests: true,
 		},
 	}
diff --git a/auth/utils_test.go b/auth/utils_test.go
index a1b3291a197ac8a0b5a9d44522a6227ea9a14285..4d6b50ade9db9ff930e3824af62515a098578e77 100644
--- a/auth/utils_test.go
+++ b/auth/utils_test.go
@@ -32,6 +32,26 @@ type mockE2eHandler struct {
 	privKey *cyclic.Int
 }
 
+func (m mockE2eHandler) HasAuthenticatedChannel(partner *id.ID) bool {
+	panic("implement me")
+}
+
+func (m mockE2eHandler) FirstPartitionSize() uint {
+	panic("implement me")
+}
+
+func (m mockE2eHandler) SecondPartitionSize() uint {
+	panic("implement me")
+}
+
+func (m mockE2eHandler) PartitionSize(payloadIndex uint) uint {
+	panic("implement me")
+}
+
+func (m mockE2eHandler) PayloadSize() uint {
+	panic("implement me")
+}
+
 func (m mockE2eHandler) GetHistoricalDHPrivkey() *cyclic.Int {
 	return m.privKey
 }
diff --git a/bindings/connect.go b/bindings/connect.go
index 3c414bd8bfa376434e62a5d4db7cb02e7824601c..d8e6db0acf984caa4b320f978e8e0b5059592dd5 100644
--- a/bindings/connect.go
+++ b/bindings/connect.go
@@ -15,12 +15,17 @@ var connectionTrackerSingleton = &connectionTracker{
 	count:       0,
 }
 
-// Connection is the bindings representation of a connect.Connection object that can be tracked
+// Connection is the bindings representation of a connect.Connection object that can be tracked by id
 type Connection struct {
 	connection connect.Connection
 	id         int
 }
 
+// GetId returns the Connection.id
+func (c *Connection) GetId() int {
+	return c.id
+}
+
 // Connect performs auth key negotiation with the given recipient,
 // and returns a Connection object for the newly-created partner.Manager
 // This function is to be used sender-side and will block until the
diff --git a/bindings/delivery.go b/bindings/delivery.go
index 3066880c4ed27a9474b9cc8bcd4aedcb2ff5c194..57fcbfa4d34ede1307cb628691ca5fde4210bd47 100644
--- a/bindings/delivery.go
+++ b/bindings/delivery.go
@@ -48,6 +48,9 @@ func makeRoundsList(rounds []id.Round) RoundsList {
 
 // MessageDeliveryCallback gets called on the determination if all events
 // related to a message send were successful.
+// If delivered == true, timedOut == false && roundResults != nil
+// If delivered == false, roundResults == nil
+// If timedOut == true, delivered == false && roundResults == nil
 type MessageDeliveryCallback interface {
 	EventCallback(delivered, timedOut bool, roundResults []byte)
 }
diff --git a/bindings/follow.go b/bindings/follow.go
index 4ad4620d19d5a385ac9d6b7fbad3efa00716bf5e..ae81595b23ed0bbb627f6e112b86c5af47903919 100644
--- a/bindings/follow.go
+++ b/bindings/follow.go
@@ -1,6 +1,8 @@
 package bindings
 
 import (
+	"fmt"
+	"github.com/pkg/errors"
 	"gitlab.com/xx_network/primitives/netTime"
 	"time"
 )
@@ -38,6 +40,19 @@ func (c *Client) StartNetworkFollower(timeoutMS int) error {
 	return c.api.StartNetworkFollower(timeout)
 }
 
+// StopNetworkFollower stops the network follower if it is running.
+// It returns errors if the Follower is in the wrong status to stop or if it
+// fails to stop it.
+// if the network follower is running and this fails, the client object will
+// most likely be in an unrecoverable state and need to be trashed.
+func (c *Client) StopNetworkFollower() error {
+	if err := c.api.StopNetworkFollower(); err != nil {
+		return errors.New(fmt.Sprintf("Failed to stop the "+
+			"network follower: %+v", err))
+	}
+	return nil
+}
+
 // WaitForNewtwork will block until either the network is healthy or the
 // passed timeout. It will return true if the network is healthy
 func (c *Client) WaitForNetwork(timeoutMS int) bool {
diff --git a/bindings/version.go b/bindings/version.go
new file mode 100644
index 0000000000000000000000000000000000000000..7e84bbd2ed1a0de0825e47a24e5e62ffa2f9f78a
--- /dev/null
+++ b/bindings/version.go
@@ -0,0 +1,24 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 Privategrity Corporation                                   /
+//                                                                             /
+// All rights reserved.                                                        /
+////////////////////////////////////////////////////////////////////////////////
+
+package bindings
+
+import "gitlab.com/elixxir/client/api"
+
+// GetVersion returns the api SEMVER
+func GetVersion() string {
+	return api.SEMVER
+}
+
+// GetGitVersion rturns the api GITVERSION
+func GetGitVersion() string {
+	return api.GITVERSION
+}
+
+// GetDependencies returns the api DEPENDENCIES
+func GetDependencies() string {
+	return api.DEPENDENCIES
+}
diff --git a/broadcast/asymmetric.go b/broadcast/asymmetric.go
new file mode 100644
index 0000000000000000000000000000000000000000..79fc4b4d0988319d6f9e0380fa6bbb4cd6d038ff
--- /dev/null
+++ b/broadcast/asymmetric.go
@@ -0,0 +1,91 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package broadcast
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/cmix/message"
+	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/xx_network/crypto/multicastRSA"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+)
+
+const (
+	asymmetricBroadcastServiceTag = "AsymmBcast"
+	asymmCMixSendTag              = "AsymmetricBroadcast"
+)
+
+// MaxAsymmetricPayloadSize returns the maximum size for an asymmetric broadcast payload
+func (bc *broadcastClient) maxAsymmetricPayload() int {
+	return bc.maxParts() * bc.channel.MaxAsymmetricPayloadSize()
+}
+
+// BroadcastAsymmetric broadcasts the payload to the channel. Requires a healthy network state to send
+// Payload must be equal to bc.MaxAsymmetricPayloadSize, and the channel PrivateKey must be passed in
+// Broadcast method must be set to asymmetric
+// When a payload is sent, it is split into partitons of size bc.channel.MaxAsymmetricPayloadSize
+// which are each encrypted using multicastRSA
+func (bc *broadcastClient) BroadcastAsymmetric(pk multicastRSA.PrivateKey, payload []byte, cMixParams cmix.CMIXParams) (
+	id.Round, ephemeral.Id, error) {
+	if bc.param.Method != Asymmetric {
+		return 0, ephemeral.Id{}, errors.Errorf(errBroadcastMethodType, Asymmetric, bc.param.Method)
+	}
+
+	if !bc.net.IsHealthy() {
+		return 0, ephemeral.Id{}, errors.New(errNetworkHealth)
+	}
+
+	if len(payload) != bc.maxAsymmetricPayload() {
+		return 0, ephemeral.Id{},
+			errors.Errorf(errPayloadSize, len(payload), bc.maxAsymmetricPayload())
+	}
+
+	numParts := bc.maxParts()
+	size := bc.channel.MaxAsymmetricPayloadSize()
+	var mac []byte
+	var fp format.Fingerprint
+	var sequential []byte
+	for i := 0; i < numParts; i++ {
+		// Encrypt payload to send using asymmetric channel
+		var encryptedPayload []byte
+		var err error
+		encryptedPayload, mac, fp, err = bc.channel.EncryptAsymmetric(payload[:size], pk, bc.rng.GetStream())
+		if err != nil {
+			return 0, ephemeral.Id{}, errors.WithMessage(err, "Failed to encrypt asymmetric broadcast message")
+		}
+		payload = payload[size:]
+		sequential = append(sequential, encryptedPayload...)
+	}
+
+	// Create service object to send message
+	service := message.Service{
+		Identifier: bc.channel.ReceptionID.Bytes(),
+		Tag:        asymmetricBroadcastServiceTag,
+	}
+
+	if cMixParams.DebugTag == cmix.DefaultDebugTag {
+		cMixParams.DebugTag = asymmCMixSendTag
+	}
+
+	sizedPayload, err := NewSizedBroadcast(bc.net.GetMaxMessageLength(), sequential)
+	if err != nil {
+		return id.Round(0), ephemeral.Id{}, err
+	}
+
+	return bc.net.Send(
+		bc.channel.ReceptionID, fp, service, sizedPayload, mac, cMixParams)
+}
+
+// Helper function for maximum number of encrypted message parts
+func (bc *broadcastClient) maxParts() int {
+	encPartSize := bc.channel.RsaPubKey.Size()
+	maxSend := bc.net.GetMaxMessageLength()
+	return maxSend / encPartSize
+}
diff --git a/broadcast/asymmetric_test.go b/broadcast/asymmetric_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2df1c2eb3d5c46de22c0c530b01f08ab97e6cd94
--- /dev/null
+++ b/broadcast/asymmetric_test.go
@@ -0,0 +1,139 @@
+package broadcast
+
+import (
+	"bytes"
+	"fmt"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	crypto "gitlab.com/elixxir/crypto/broadcast"
+	cMixCrypto "gitlab.com/elixxir/crypto/cmix"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"reflect"
+	"sync"
+	"testing"
+	"time"
+)
+
+// Tests that symmetricClient adheres to the Symmetric interface.
+var _ Channel = (*broadcastClient)(nil)
+
+// Tests that symmetricClient adheres to the Symmetric interface.
+var _ Client = (cmix.Client)(nil)
+
+func Test_asymmetricClient_Smoke(t *testing.T) {
+	cMixHandler := newMockCmixHandler()
+	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
+	pk, err := rsa.GenerateKey(rngGen.GetStream(), 4096)
+	if err != nil {
+		t.Fatalf("Failed to generate priv key: %+v", err)
+	}
+	cname := "MyChannel"
+	cdesc := "This is my channel about stuff."
+	csalt := cMixCrypto.NewSalt(csprng.NewSystemRNG(), 32)
+	cpubkey := pk.GetPublic()
+	cid, err := crypto.NewChannelID(cname, cdesc, csalt, rsa.CreatePublicKeyPem(cpubkey))
+	if err != nil {
+		t.Errorf("Failed to create channel ID: %+v", err)
+	}
+	channel := crypto.Channel{
+		ReceptionID: cid,
+		Name:        cname,
+		Description: cdesc,
+		Salt:        csalt,
+		RsaPubKey:   cpubkey,
+	}
+
+	const n = 5
+	cbChans := make([]chan []byte, n)
+	clients := make([]Channel, n)
+	for i := range clients {
+		cbChan := make(chan []byte, 10)
+		cb := func(payload []byte, _ receptionID.EphemeralIdentity,
+			_ rounds.Round) {
+			cbChan <- payload
+		}
+
+		s, err := NewBroadcastChannel(channel, cb, newMockCmix(cMixHandler), rngGen, Param{Method: Asymmetric})
+		if err != nil {
+			t.Errorf("Failed to create broadcast channel: %+v", err)
+		}
+
+		cbChans[i] = cbChan
+		clients[i] = s
+
+		// Test that Get returns the expected channel
+		if !reflect.DeepEqual(s.Get(), channel) {
+			t.Errorf("Client %d returned wrong channel."+
+				"\nexpected: %+v\nreceived: %+v", i, channel, s.Get())
+		}
+	}
+
+	// Send broadcast from each client
+	for i := range clients {
+		payload := make([]byte, clients[i].MaxPayloadSize())
+		copy(payload,
+			fmt.Sprintf("Hello from client %d of %d.", i, len(clients)))
+
+		// Start processes that waits for each client to receive broadcast
+		var wg sync.WaitGroup
+		for j := range cbChans {
+			wg.Add(1)
+			go func(i, j int, cbChan chan []byte) {
+				defer wg.Done()
+				select {
+				case r := <-cbChan:
+					if !bytes.Equal(payload, r) {
+						t.Errorf("Client %d failed to receive expected "+
+							"payload from client %d."+
+							"\nexpected: %q\nreceived: %q", j, i, payload, r)
+					}
+				case <-time.After(time.Second):
+					t.Errorf("Client %d timed out waiting for broadcast "+
+						"payload from client %d.", j, i)
+				}
+			}(i, j, cbChans[j])
+		}
+
+		// Broadcast payload
+		_, _, err := clients[i].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams())
+		if err != nil {
+			t.Errorf("Client %d failed to send broadcast: %+v", i, err)
+		}
+
+		// Wait for all clients to receive payload or time out
+		wg.Wait()
+	}
+
+	// Stop each client
+	for i := range clients {
+		clients[i].Stop()
+	}
+
+	payload := make([]byte, clients[0].MaxPayloadSize())
+	copy(payload, "This message should not get through.")
+
+	// Start waiting on channels and error if anything is received
+	var wg sync.WaitGroup
+	for i := range cbChans {
+		wg.Add(1)
+		go func(i int, cbChan chan []byte) {
+			defer wg.Done()
+			select {
+			case r := <-cbChan:
+				t.Errorf("Client %d received message: %q", i, r)
+			case <-time.After(25 * time.Millisecond):
+			}
+		}(i, cbChans[i])
+	}
+
+	// Broadcast payload
+	_, _, err = clients[0].BroadcastAsymmetric(pk, payload, cmix.GetDefaultCMIXParams())
+	if err != nil {
+		t.Errorf("Client 0 failed to send broadcast: %+v", err)
+	}
+
+	wg.Wait()
+}
diff --git a/broadcast/broadcastClient.go b/broadcast/broadcastClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..54555a3875db03af4331438e0dcb92922ad3aa06
--- /dev/null
+++ b/broadcast/broadcastClient.go
@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package broadcast
+
+import (
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/cmix/identity"
+	"gitlab.com/elixxir/client/cmix/message"
+	crypto "gitlab.com/elixxir/crypto/broadcast"
+	"gitlab.com/elixxir/crypto/fastRNG"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+)
+
+// Param encapsulates configuration options for a broadcastClient
+type Param struct {
+	Method Method
+}
+
+// broadcastClient implements the Channel interface for sending/receiving asymmetric or symmetric broadcast messages
+type broadcastClient struct {
+	channel crypto.Channel
+	net     Client
+	rng     *fastRNG.StreamGenerator
+	param   Param
+}
+
+// NewBroadcastChannel creates a channel interface based on crypto.Channel, accepts net client connection & callback for received messages
+func NewBroadcastChannel(channel crypto.Channel, listenerCb ListenerFunc, net Client, rng *fastRNG.StreamGenerator, param Param) (Channel, error) {
+	bc := &broadcastClient{
+		channel: channel,
+		net:     net,
+		rng:     rng,
+		param:   param,
+	}
+
+	if !bc.verifyID() {
+		jww.FATAL.Panicf("Failed ID verification for broadcast channel")
+	}
+
+	// Add channel's identity
+	net.AddIdentity(channel.ReceptionID, identity.Forever, true)
+
+	p := &processor{
+		c:      &channel,
+		cb:     listenerCb,
+		method: param.Method,
+	}
+	var tag string
+	switch param.Method {
+	case Symmetric:
+		tag = symmetricBroadcastServiceTag
+	case Asymmetric:
+		tag = asymmetricBroadcastServiceTag
+	default:
+		return nil, errors.Errorf("Cannot make broadcast client for unknown broadcast method %s", param.Method)
+	}
+	service := message.Service{
+		Identifier: channel.ReceptionID.Bytes(),
+		Tag:        tag,
+	}
+
+	net.AddService(channel.ReceptionID, service, p)
+
+	jww.INFO.Printf("New %s broadcast client created for channel %q (%s)",
+		param.Method, channel.Name, channel.ReceptionID)
+
+	return bc, nil
+}
+
+// Stop unregisters the listener callback and stops the channel's identity
+// from being tracked.
+func (bc *broadcastClient) Stop() {
+	// Removes currently tracked identity
+	bc.net.RemoveIdentity(bc.channel.ReceptionID)
+
+	// Delete all registered services
+	bc.net.DeleteClientService(bc.channel.ReceptionID)
+}
+
+// Get returns the underlying crypto.Channel object
+func (bc *broadcastClient) Get() crypto.Channel {
+	return bc.channel
+}
+
+// verifyID generates a symmetric ID based on the info in the channel & compares it to the one passed in
+// TODO: it seems very odd to me that we do this, rather than just making the ID a private/ephemeral component like the key
+func (bc *broadcastClient) verifyID() bool {
+	gen, err := crypto.NewChannelID(bc.channel.Name, bc.channel.Description, bc.channel.Salt, rsa.CreatePublicKeyPem(bc.channel.RsaPubKey))
+	if err != nil {
+		jww.FATAL.Panicf("[verifyID] Failed to generate verified channel ID")
+		return false
+	}
+	return bc.channel.ReceptionID.Cmp(gen)
+}
+
+func (bc *broadcastClient) MaxPayloadSize() int {
+	switch bc.param.Method {
+	case Symmetric:
+		return bc.maxSymmetricPayload()
+	case Asymmetric:
+		return bc.maxAsymmetricPayload()
+	default:
+		return -1
+	}
+}
diff --git a/broadcast/interface.go b/broadcast/interface.go
index 1da049fc8807fd0d170242b4d1c0de9ff68060e4..2c7d9e33820ce78a1532b693ace989fa7ea386f2 100644
--- a/broadcast/interface.go
+++ b/broadcast/interface.go
@@ -10,33 +10,54 @@ package broadcast
 import (
 	"gitlab.com/elixxir/client/cmix"
 	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/message"
 	"gitlab.com/elixxir/client/cmix/rounds"
 	crypto "gitlab.com/elixxir/crypto/broadcast"
+	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/xx_network/crypto/multicastRSA"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/id/ephemeral"
+	"time"
 )
 
-// ListenerFunc is registered when creating a new symmetric broadcasting channel
+// ListenerFunc is registered when creating a new broadcasting channel
 // and receives all new broadcast messages for the channel.
 type ListenerFunc func(payload []byte,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round)
 
-// Symmetric manages the listening and broadcasting of a symmetric broadcast
-// channel.
-type Symmetric interface {
-	// MaxPayloadSize returns the maximum size for a broadcasted payload.
+type Channel interface {
+	// MaxPayloadSize returns the maximum size for a broadcast payload.  Different math depending on broadcast method.
 	MaxPayloadSize() int
 
-	// Get returns the crypto.Symmetric object containing the cryptographic and
-	// identifying information about the channel.
-	Get() crypto.Symmetric
+	// Get returns the underlying crypto.Channel
+	Get() crypto.Channel
 
 	// Broadcast broadcasts the payload to the channel. The payload size must be
 	// equal to MaxPayloadSize.
 	Broadcast(payload []byte, cMixParams cmix.CMIXParams) (
 		id.Round, ephemeral.Id, error)
 
+	// BroadcastAsymmetric broadcasts an asymmetric payload to the channel. The payload size must be
+	// equal to MaxPayloadSize & private key for channel must be passed in
+	BroadcastAsymmetric(pk multicastRSA.PrivateKey, payload []byte, cMixParams cmix.CMIXParams) (
+		id.Round, ephemeral.Id, error)
+
 	// Stop unregisters the listener callback and stops the channel's identity
 	// from being tracked.
 	Stop()
 }
+
+// Client contains the methods from cmix.Client that are required by
+// symmetricClient.
+type Client interface {
+	GetMaxMessageLength() int
+	Send(recipient *id.ID, fingerprint format.Fingerprint,
+		service message.Service, payload, mac []byte,
+		cMixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error)
+	IsHealthy() bool
+	AddIdentity(id *id.ID, validUntil time.Time, persistent bool)
+	AddService(clientID *id.ID, newService message.Service,
+		response message.Processor)
+	DeleteClientService(clientID *id.ID)
+	RemoveIdentity(id *id.ID)
+}
diff --git a/broadcast/method.go b/broadcast/method.go
new file mode 100644
index 0000000000000000000000000000000000000000..e493151504b00fabf320429b5da52a474f23efed
--- /dev/null
+++ b/broadcast/method.go
@@ -0,0 +1,27 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package broadcast
+
+// Method enum for broadcast type
+type Method uint8
+
+const (
+	Symmetric Method = iota
+	Asymmetric
+)
+
+func (m Method) String() string {
+	switch m {
+	case Symmetric:
+		return "Symmetric"
+	case Asymmetric:
+		return "Asymmetric"
+	default:
+		return "Unknown"
+	}
+}
diff --git a/broadcast/processor.go b/broadcast/processor.go
index 419072fdc06517f57b0ec1d788d9ec284dc4acfd..ec9ab810dc0aa16eefbb0add3ee44c53f55597d3 100644
--- a/broadcast/processor.go
+++ b/broadcast/processor.go
@@ -20,27 +20,55 @@ const (
 	errDecrypt = "[BCAST] Failed to decrypt payload for broadcast %s (%q): %+v"
 )
 
-// processor manages the reception and decryption of a broadcast message.
-// Adheres to the message.Processor interface.
+// processor struct for message handling
 type processor struct {
-	s  *crypto.Symmetric
-	cb ListenerFunc
+	c      *crypto.Channel
+	cb     ListenerFunc
+	method Method
 }
 
 // Process decrypts the broadcast message and sends the results on the callback.
 func (p *processor) Process(msg format.Message,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 
-	payload, err := p.s.Decrypt(msg.GetContents(), msg.GetMac(), msg.GetKeyFP())
-	if err != nil {
-		jww.ERROR.Printf(errDecrypt, p.s.ReceptionID, p.s.Name, err)
-		return
+	var payload []byte
+	var err error
+	switch p.method {
+	case Asymmetric:
+		// We use sized broadcast to fill any remaining bytes in the cmix payload, decode it here
+		unsizedPayload, err := DecodeSizedBroadcast(msg.GetContents())
+		if err != nil {
+			jww.ERROR.Printf("Failed to decode sized broadcast: %+v", err)
+			return
+		}
+		encPartSize := p.c.RsaPubKey.Size()           // Size of each chunk returned by multicast RSA encryption
+		numParts := len(unsizedPayload) / encPartSize // Number of chunks in the payload
+		// Iterate through & decrypt each chunk, appending to aggregate payload
+		for i := 0; i < numParts; i++ {
+			var decrypted []byte
+			decrypted, err = p.c.DecryptAsymmetric(unsizedPayload[:encPartSize])
+			if err != nil {
+				jww.ERROR.Printf(errDecrypt, p.c.ReceptionID, p.c.Name, err)
+				return
+			}
+			unsizedPayload = unsizedPayload[encPartSize:]
+			payload = append(payload, decrypted...)
+		}
+
+	case Symmetric:
+		payload, err = p.c.DecryptSymmetric(msg.GetContents(), msg.GetMac(), msg.GetKeyFP())
+		if err != nil {
+			jww.ERROR.Printf(errDecrypt, p.c.ReceptionID, p.c.Name, err)
+			return
+		}
+	default:
+		jww.ERROR.Printf("Unrecognized broadcast method %d", p.method)
 	}
 
 	go p.cb(payload, receptionID, round)
 }
 
-// String returns a string identifying the processor for debugging purposes.
+// String returns a string identifying the symmetricProcessor for debugging purposes.
 func (p *processor) String() string {
-	return "symmetricChannel-" + p.s.Name
+	return "broadcastChannel-" + p.c.Name
 }
diff --git a/broadcast/processor_test.go b/broadcast/processor_test.go
index 04e2f4a791485e7b5b7410f62785164d9d18f753..9e48f372e92663eea061a8a7d72e0fbe13d58eee 100644
--- a/broadcast/processor_test.go
+++ b/broadcast/processor_test.go
@@ -29,7 +29,7 @@ func Test_processor_Process(t *testing.T) {
 	if err != nil {
 		t.Errorf("Failed to generate RSA key: %+v", err)
 	}
-	s := &crypto.Symmetric{
+	s := &crypto.Channel{
 		ReceptionID: id.NewIdFromString("channel", id.User, t),
 		Name:        "MyChannel",
 		Description: "This is my channel that I channel stuff on.",
@@ -43,14 +43,15 @@ func Test_processor_Process(t *testing.T) {
 	}
 
 	p := &processor{
-		s:  s,
-		cb: cb,
+		c:      s,
+		cb:     cb,
+		method: Symmetric,
 	}
 
 	msg := format.NewMessage(4092)
 	payload := make([]byte, msg.ContentsSize())
 	_, _ = rng.Read(payload)
-	encryptedPayload, mac, fp := p.s.Encrypt(payload, rng)
+	encryptedPayload, mac, fp := p.c.EncryptSymmetric(payload, rng)
 	msg.SetContents(encryptedPayload)
 	msg.SetMac(mac)
 	msg.SetKeyFP(fp)
diff --git a/broadcast/sizedBroadcast.go b/broadcast/sizedBroadcast.go
index e909ab30014ca926ad03a9040d8e5bbc9211ca29..d05effe1bcf93b07a0f3cd3533c28df8136c3a46 100644
--- a/broadcast/sizedBroadcast.go
+++ b/broadcast/sizedBroadcast.go
@@ -37,9 +37,12 @@ const (
 +---------+-----------------+
 */
 
-// NewSizedBroadcast creates a new broadcast with its size information embedded.
+// NewSizedBroadcast creates a new broadcast payload of size maxPayloadSize that
+// contains the given payload so that it fits completely inside a broadcasted
+// cMix message payload. The length of the payload is stored internally and used
+// to strip extraneous padding when decoding the payload.
 // The maxPayloadSize is the maximum size of the resulting payload. Returns an
-// error when the sized broadcast cannot fit in the max payload size.
+// error when the provided payload cannot fit in the max payload size.
 func NewSizedBroadcast(maxPayloadSize int, payload []byte) ([]byte, error) {
 	if len(payload)+sizedBroadcastMinSize > maxPayloadSize {
 		return nil, errors.Errorf(errNewSizedBroadcastMaxSize,
@@ -49,10 +52,14 @@ func NewSizedBroadcast(maxPayloadSize int, payload []byte) ([]byte, error) {
 	b := make([]byte, sizeSize)
 	binary.LittleEndian.PutUint16(b, uint16(len(payload)))
 
-	return append(b, payload...), nil
+	sizedPayload := make([]byte, maxPayloadSize)
+	copy(sizedPayload, append(b, payload...))
+
+	return sizedPayload, nil
 }
 
-// DecodeSizedBroadcast  the data into its original payload of the correct size.
+// DecodeSizedBroadcast decodes the data into its original payload stripping off
+// extraneous padding.
 func DecodeSizedBroadcast(data []byte) ([]byte, error) {
 	if len(data) < sizedBroadcastMinSize {
 		return nil, errors.Errorf(
@@ -68,8 +75,9 @@ func DecodeSizedBroadcast(data []byte) ([]byte, error) {
 	return data[sizeSize : size+sizeSize], nil
 }
 
-// MaxSizedBroadcastPayloadSize returns the maximum payload size in a sized
-// broadcast for the given out message max payload size.
+// MaxSizedBroadcastPayloadSize returns the maximum size of a payload that can
+// fit in a sized broadcast message for the given maximum cMix message payload
+// size.
 func MaxSizedBroadcastPayloadSize(maxPayloadSize int) int {
 	return maxPayloadSize - sizedBroadcastMinSize
 }
diff --git a/broadcast/symmetric.go b/broadcast/symmetric.go
new file mode 100644
index 0000000000000000000000000000000000000000..ca0c528c588b184a72dc788a2fa83c0423ca5268
--- /dev/null
+++ b/broadcast/symmetric.go
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package broadcast
+
+import (
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/cmix/message"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/id/ephemeral"
+)
+
+// Error messages.
+const (
+	// symmetricClient.Broadcast
+	errNetworkHealth       = "cannot send broadcast when the network is not healthy"
+	errPayloadSize         = "size of payload %d must be %d"
+	errBroadcastMethodType = "cannot call %s broadcast using %s channel"
+)
+
+// Tags.
+const (
+	symmCMixSendTag              = "SymmBcast"
+	symmetricBroadcastServiceTag = "SymmetricBroadcast"
+)
+
+// MaxSymmetricPayloadSize returns the maximum size for a broadcasted payload.
+func (bc *broadcastClient) maxSymmetricPayload() int {
+	return bc.net.GetMaxMessageLength()
+}
+
+// Broadcast broadcasts a payload over a symmetric channel.
+// broadcast method must be set to Symmetric
+// Network must be healthy to send
+// Requires a payload of size bc.MaxSymmetricPayloadSize()
+func (bc *broadcastClient) Broadcast(payload []byte, cMixParams cmix.CMIXParams) (
+	id.Round, ephemeral.Id, error) {
+	if bc.param.Method != Symmetric {
+		return 0, ephemeral.Id{}, errors.Errorf(errBroadcastMethodType, Symmetric, bc.param.Method)
+	}
+
+	if !bc.net.IsHealthy() {
+		return 0, ephemeral.Id{}, errors.New(errNetworkHealth)
+	}
+
+	if len(payload) != bc.maxSymmetricPayload() {
+		return 0, ephemeral.Id{},
+			errors.Errorf(errPayloadSize, len(payload), bc.maxSymmetricPayload())
+	}
+
+	// Encrypt payload
+	rng := bc.rng.GetStream()
+	encryptedPayload, mac, fp := bc.channel.EncryptSymmetric(payload, rng)
+	rng.Close()
+
+	// Create service
+	service := message.Service{
+		Identifier: bc.channel.ReceptionID.Bytes(),
+		Tag:        symmetricBroadcastServiceTag,
+	}
+
+	if cMixParams.DebugTag == cmix.DefaultDebugTag {
+		cMixParams.DebugTag = symmCMixSendTag
+	}
+
+	return bc.net.Send(
+		bc.channel.ReceptionID, fp, service, encryptedPayload, mac, cMixParams)
+}
diff --git a/broadcast/symmetricClient.go b/broadcast/symmetricClient.go
deleted file mode 100644
index 28d718868a0659f9f2816f7fd2b16a4feb9cb116..0000000000000000000000000000000000000000
--- a/broadcast/symmetricClient.go
+++ /dev/null
@@ -1,143 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2020 xx network SEZC                                           //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file                                                               //
-////////////////////////////////////////////////////////////////////////////////
-
-package broadcast
-
-import (
-	"github.com/pkg/errors"
-	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/cmix"
-	"gitlab.com/elixxir/client/cmix/identity"
-	"gitlab.com/elixxir/client/cmix/message"
-	crypto "gitlab.com/elixxir/crypto/broadcast"
-	"gitlab.com/elixxir/crypto/fastRNG"
-	"gitlab.com/elixxir/primitives/format"
-	"gitlab.com/xx_network/primitives/id"
-	"gitlab.com/xx_network/primitives/id/ephemeral"
-	"time"
-)
-
-// Error messages.
-const (
-	// symmetricClient.Broadcast
-	errNetworkHealth = "cannot send broadcast when the network is not healthy"
-	errPayloadSize   = "size of payload %d must be %d"
-)
-
-// Tags.
-const (
-	cMixSendTag                  = "SymmBcast"
-	symmetricBroadcastServiceTag = "SymmetricBroadcast"
-)
-
-// symmetricClient manages the sending and receiving of symmetric broadcast
-// messages on a given symmetric broadcast channel. Adheres to the Symmetric
-// interface.
-type symmetricClient struct {
-	channel crypto.Symmetric
-	net     Client
-	rng     *fastRNG.StreamGenerator
-}
-
-// Client contains the methods from cmix.Client that are required by
-// symmetricClient.
-type Client interface {
-	GetMaxMessageLength() int
-	Send(recipient *id.ID, fingerprint format.Fingerprint,
-		service message.Service, payload, mac []byte,
-		cMixParams cmix.CMIXParams) (id.Round, ephemeral.Id, error)
-	IsHealthy() bool
-	AddIdentity(id *id.ID, validUntil time.Time, persistent bool)
-	AddService(clientID *id.ID, newService message.Service,
-		response message.Processor)
-	DeleteClientService(clientID *id.ID)
-	RemoveIdentity(id *id.ID)
-}
-
-// NewSymmetricClient generates a new Symmetric for the given channel. It starts
-// listening for new messages on the callback immediately.
-func NewSymmetricClient(channel crypto.Symmetric, listenerCb ListenerFunc,
-	net Client, rng *fastRNG.StreamGenerator) Symmetric {
-	// Add channel's identity
-	net.AddIdentity(channel.ReceptionID, identity.Forever, true)
-
-	// Create new service
-	service := message.Service{
-		Identifier: channel.ReceptionID.Bytes(),
-		Tag:        symmetricBroadcastServiceTag,
-	}
-
-	// Create new message processor
-	p := &processor{
-		s:  &channel,
-		cb: listenerCb,
-	}
-
-	// Add service
-	net.AddService(channel.ReceptionID, service, p)
-
-	jww.INFO.Printf("New symmetric broadcast client created for channel %q (%s)",
-		channel.Name, channel.ReceptionID)
-
-	return &symmetricClient{
-		channel: channel,
-		net:     net,
-		rng:     rng,
-	}
-}
-
-// MaxPayloadSize returns the maximum size for a broadcasted payload.
-func (s *symmetricClient) MaxPayloadSize() int {
-	return s.net.GetMaxMessageLength()
-}
-
-// Get returns the crypto.Symmetric object containing the cryptographic and
-// identifying information about the channel.
-func (s *symmetricClient) Get() crypto.Symmetric {
-	return s.channel
-}
-
-// Broadcast broadcasts the payload to the channel.
-func (s *symmetricClient) Broadcast(payload []byte, cMixParams cmix.CMIXParams) (
-	id.Round, ephemeral.Id, error) {
-	if !s.net.IsHealthy() {
-		return 0, ephemeral.Id{}, errors.New(errNetworkHealth)
-	}
-
-	if len(payload) != s.MaxPayloadSize() {
-		return 0, ephemeral.Id{},
-			errors.Errorf(errPayloadSize, len(payload), s.MaxPayloadSize())
-	}
-
-	// Encrypt payload
-	rng := s.rng.GetStream()
-	encryptedPayload, mac, fp := s.channel.Encrypt(payload, rng)
-	rng.Close()
-
-	// Create service
-	service := message.Service{
-		Identifier: s.channel.ReceptionID.Bytes(),
-		Tag:        symmetricBroadcastServiceTag,
-	}
-
-	if cMixParams.DebugTag == cmix.DefaultDebugTag {
-		cMixParams.DebugTag = cMixSendTag
-	}
-
-	return s.net.Send(
-		s.channel.ReceptionID, fp, service, encryptedPayload, mac, cMixParams)
-}
-
-// Stop unregisters the listener callback and stops the channel's identity
-// from being tracked.
-func (s *symmetricClient) Stop() {
-	// Removes currently tracked identity
-	s.net.RemoveIdentity(s.channel.ReceptionID)
-
-	// Delete all registered services
-	s.net.DeleteClientService(s.channel.ReceptionID)
-}
diff --git a/broadcast/symmetricClient_test.go b/broadcast/symmetric_test.go
similarity index 81%
rename from broadcast/symmetricClient_test.go
rename to broadcast/symmetric_test.go
index 4b6f60ac89fb1b7a06e5ce1a3fa7398720848250..a35ea5ecdca77b9abb5d874b3a28c99be6f08a7a 100644
--- a/broadcast/symmetricClient_test.go
+++ b/broadcast/symmetric_test.go
@@ -17,7 +17,7 @@ import (
 	cMixCrypto "gitlab.com/elixxir/crypto/cmix"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/xx_network/crypto/csprng"
-	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/crypto/signature/rsa"
 	"reflect"
 	"sync"
 	"testing"
@@ -25,7 +25,7 @@ import (
 )
 
 // Tests that symmetricClient adheres to the Symmetric interface.
-var _ Symmetric = (*symmetricClient)(nil)
+var _ Channel = (*broadcastClient)(nil)
 
 // Tests that symmetricClient adheres to the Symmetric interface.
 var _ Client = (cmix.Client)(nil)
@@ -36,18 +36,26 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 	// Initialise objects used by all clients
 	cMixHandler := newMockCmixHandler()
 	rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
-	channel := crypto.Symmetric{
-		ReceptionID: id.NewIdFromString("ReceptionID", id.User, t),
-		Name:        "MyChannel",
-		Description: "This is my channel about stuff.",
-		Salt:        cMixCrypto.NewSalt(csprng.NewSystemRNG(), 32),
-		RsaPubKey:   newRsaPubKey(64, t),
+	cname := "MyChannel"
+	cdesc := "This is my channel about stuff."
+	csalt := cMixCrypto.NewSalt(csprng.NewSystemRNG(), 32)
+	cpubkey := newRsaPubKey(64, t)
+	cid, err := crypto.NewChannelID(cname, cdesc, csalt, rsa.CreatePublicKeyPem(cpubkey))
+	if err != nil {
+		t.Errorf("Failed to create channel ID: %+v", err)
+	}
+	channel := crypto.Channel{
+		ReceptionID: cid,
+		Name:        cname,
+		Description: cdesc,
+		Salt:        csalt,
+		RsaPubKey:   cpubkey,
 	}
 
 	// Set up callbacks, callback channels, and the symmetric clients
 	const n = 5
 	cbChans := make([]chan []byte, n)
-	clients := make([]Symmetric, n)
+	clients := make([]Channel, n)
 	for i := range clients {
 		cbChan := make(chan []byte, 10)
 		cb := func(payload []byte, _ receptionID.EphemeralIdentity,
@@ -55,8 +63,10 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 			cbChan <- payload
 		}
 
-		s := NewSymmetricClient(channel, cb, newMockCmix(cMixHandler), rngGen)
-
+		s, err := NewBroadcastChannel(channel, cb, newMockCmix(cMixHandler), rngGen, Param{Method: Symmetric})
+		if err != nil {
+			t.Errorf("Failed to create broadcast channel: %+v", err)
+		}
 		cbChans[i] = cbChan
 		clients[i] = s
 
@@ -126,7 +136,7 @@ func Test_symmetricClient_Smoke(t *testing.T) {
 	}
 
 	// Broadcast payload
-	_, _, err := clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams())
+	_, _, err = clients[0].Broadcast(payload, cmix.GetDefaultCMIXParams())
 	if err != nil {
 		t.Errorf("Client 0 failed to send broadcast: %+v", err)
 	}
diff --git a/cmd/broadcast.go b/cmd/broadcast.go
new file mode 100644
index 0000000000000000000000000000000000000000..8b9ae2358d5e4b6b51d2dd15bc6b6e22e74e5c05
--- /dev/null
+++ b/cmd/broadcast.go
@@ -0,0 +1,282 @@
+package cmd
+
+import (
+	"fmt"
+	"github.com/spf13/cobra"
+	jww "github.com/spf13/jwalterweatherman"
+	"github.com/spf13/viper"
+	"gitlab.com/elixxir/client/broadcast"
+	"gitlab.com/elixxir/client/cmix"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	crypto "gitlab.com/elixxir/crypto/broadcast"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/utils"
+	"os"
+	"time"
+)
+
+// singleCmd is the single-use subcommand that allows for sending and responding
+// to single-use messages.
+var broadcastCmd = &cobra.Command{
+	Use:   "broadcast",
+	Short: "Send broadcast messages",
+	Args:  cobra.NoArgs,
+	Run: func(cmd *cobra.Command, args []string) {
+		client := initClient()
+
+		// Write user contact to file
+		user := client.GetUser()
+		jww.INFO.Printf("User: %s", user.ReceptionID)
+		jww.INFO.Printf("User Transmission: %s", user.TransmissionID)
+		writeContact(user.GetContact())
+
+		err := client.StartNetworkFollower(5 * time.Second)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to start network follower: %+v", err)
+		}
+
+		// Wait until connected or crash on timeout
+		connected := make(chan bool, 10)
+		client.GetCmix().AddHealthCallback(
+			func(isconnected bool) {
+				connected <- isconnected
+			})
+		waitUntilConnected(connected)
+
+		/* Set up underlying crypto broadcast.Channel */
+		var channel *crypto.Channel
+		var pk *rsa.PrivateKey
+		keyPath := viper.GetString("keyPath")
+		path, err := utils.ExpandPath(viper.GetString("chanPath"))
+		if utils.Exists(path) {
+			// Load symmetric from path
+			cBytes, err := utils.ReadFile(path)
+			if err != nil {
+				jww.FATAL.Panicf("Failed to read channel from file at %s: %+v", path, err)
+			}
+			channel, err = crypto.UnmarshalChannel(cBytes)
+			if err != nil {
+				jww.FATAL.Panicf("Failed to unmarshal channel data %+v: %+v", cBytes, err)
+			}
+		} else {
+			// Load in broadcast channel info
+			name := viper.GetString("name")
+			desc := viper.GetString("description")
+			if name == "" {
+				jww.FATAL.Panicf("Name cannot be empty")
+			} else if desc == "" {
+				jww.FATAL.Panicf("description cannot be empty")
+			}
+
+			var channel *crypto.Channel
+			if viper.GetBool("new") {
+				// Create a new broadcast channel
+				channel, pk, err = crypto.NewChannel(name, desc, client.GetRng().GetStream())
+				if err != nil {
+					jww.FATAL.Panicf("Failed to create new channel: %+v", err)
+				}
+
+				if keyPath != "" {
+					err = utils.WriteFile(path, rsa.CreatePrivateKeyPem(pk), os.ModePerm, os.ModeDir)
+					if err != nil {
+						jww.ERROR.Printf("Failed to write private key to path %s: %+v", path, err)
+					}
+				} else {
+					fmt.Printf("Private key generated for channel: %+v", rsa.CreatePrivateKeyPem(pk))
+				}
+			} else {
+				// Read rest of info from config & build object manually
+				pubKeyBytes := []byte(viper.GetString("rsaPub"))
+				pubKey, err := rsa.LoadPublicKeyFromPem(pubKeyBytes)
+				if err != nil {
+					jww.FATAL.Panicf("Failed to load public key at path: %+v", err)
+				}
+				salt := []byte(viper.GetString("salt"))
+
+				rid, err := crypto.NewChannelID(name, desc, salt, pubKeyBytes)
+				if err != nil {
+					jww.FATAL.Panicf("Failed to generate channel ID: %+v", err)
+				}
+
+				channel = &crypto.Channel{
+					ReceptionID: rid,
+					Name:        name,
+					Description: desc,
+					Salt:        salt,
+					RsaPubKey:   pubKey,
+				}
+
+				// Load key if it's there
+				if keyPath != "" {
+					if ep, err := utils.ExpandPath(keyPath); err == nil {
+						keyBytes, err := utils.ReadFile(ep)
+						if err != nil {
+							jww.ERROR.Printf("Failed to read private key from %s: %+v", ep, err)
+						}
+						pk, err = rsa.LoadPrivateKeyFromPem(keyBytes)
+						if err != nil {
+							jww.ERROR.Printf("Failed to load private key %+v: %+v", keyBytes, err)
+						}
+					} else {
+						jww.ERROR.Printf("Failed to expand private key path: %+v", err)
+					}
+
+				}
+			}
+
+			// Save channel to disk
+			cBytes, err := channel.Marshal()
+			if err != nil {
+				jww.ERROR.Printf("Failed to marshal channel to bytes: %+v", err)
+			}
+			// Write to file if there
+			if path != "" {
+				err = utils.WriteFile(path, cBytes, os.ModePerm, os.ModeDir)
+				if err != nil {
+					jww.ERROR.Printf("Failed to write channel to file %s: %+v", path, err)
+				}
+			} else {
+				fmt.Printf("Channel marshalled: %+v", cBytes)
+			}
+		}
+
+		/* Broadcast client setup */
+
+		// Create receiver callback
+		receiveChan := make(chan []byte, 100)
+		cb := func(payload []byte,
+			receptionID receptionID.EphemeralIdentity, round rounds.Round) {
+			jww.INFO.Printf("Received symmetric message from %s over round %d", receptionID, round.ID)
+			receiveChan <- payload
+		}
+
+		// Select broadcast method
+		var method broadcast.Method
+		symmetric := viper.GetBool("symmetric")
+		asymmetric := viper.GetBool("asymmetric")
+		if symmetric && asymmetric {
+			jww.FATAL.Panicf("Cannot simultaneously broadcast symmetric & asymmetric")
+		}
+		if symmetric {
+			method = broadcast.Symmetric
+		} else if asymmetric {
+			method = broadcast.Asymmetric
+		}
+
+		// Connect to broadcast channel
+		bcl, err := broadcast.NewBroadcastChannel(*channel, cb, client.GetCmix(), client.GetRng(), broadcast.Param{Method: method})
+
+		/* Create properly sized broadcast message */
+		message := viper.GetString("broadcast")
+		fmt.Println(message)
+		var broadcastMessage []byte
+		if message != "" {
+			broadcastMessage, err = broadcast.NewSizedBroadcast(bcl.MaxPayloadSize(), []byte(message))
+			if err != nil {
+				jww.ERROR.Printf("Failed to create sized broadcast: %+v", err)
+			}
+
+		}
+
+		/* Broadcast message to the channel */
+		switch method {
+		case broadcast.Symmetric:
+			rid, eid, err := bcl.Broadcast(broadcastMessage, cmix.GetDefaultCMIXParams())
+			if err != nil {
+				jww.ERROR.Printf("Failed to send symmetric broadcast message: %+v", err)
+			}
+			jww.INFO.Printf("Sent symmetric broadcast message to %s over round %d", eid, rid)
+		case broadcast.Asymmetric:
+			if pk == nil {
+				jww.FATAL.Panicf("CANNOT SEND ASYMMETRIC BROADCAST WITHOUT PRIVATE KEY")
+			}
+			rid, eid, err := bcl.BroadcastAsymmetric(pk, broadcastMessage, cmix.GetDefaultCMIXParams())
+			if err != nil {
+				jww.ERROR.Printf("Failed to send asymmetric broadcast message: %+v", err)
+			}
+			jww.INFO.Printf("Sent asymmetric broadcast message to %s over round %d", eid, rid)
+		default:
+			jww.WARN.Printf("Unknown broadcast type (this should not happen)")
+		}
+
+		/* Receive broadcast messages over the channel */
+		waitSecs := viper.GetUint("waitTimeout")
+		expectedCnt := viper.GetUint("receiveCount")
+		waitTimeout := time.Duration(waitSecs) * time.Second
+		receivedCount := uint(0)
+		done := false
+		for !done && expectedCnt != 0 {
+			timeout := time.NewTimer(waitTimeout)
+			select {
+			case receivedPayload := <-receiveChan:
+				receivedCount++
+				receivedBroadcast, err := broadcast.DecodeSizedBroadcast(receivedPayload)
+				if err != nil {
+					jww.ERROR.Printf("Failed to decode sized broadcast: %+v", err)
+					continue
+				}
+				fmt.Printf("Symmetric broadcast message %d/%d received: %s\n", receivedCount, expectedCnt, string(receivedBroadcast))
+				if receivedCount == expectedCnt {
+					done = true
+				}
+			case <-timeout.C:
+				fmt.Println("Timed out")
+				jww.ERROR.Printf("Timed out on message reception after %s!", waitTimeout)
+				done = true
+			}
+		}
+
+		jww.INFO.Printf("Received %d/%d Messages!", receivedCount, expectedCnt)
+		bcl.Stop()
+		err = client.StopNetworkFollower()
+		if err != nil {
+			jww.WARN.Printf("Failed to cleanly close threads: %+v\n", err)
+		}
+	},
+}
+
+func init() {
+	// Single-use subcommand options
+	broadcastCmd.Flags().StringP("name", "", "",
+		"Symmetric channel name")
+	_ = viper.BindPFlag("name", broadcastCmd.Flags().Lookup("name"))
+
+	broadcastCmd.Flags().StringP("rsaPub", "", "",
+		"Broadcast channel rsa pub key")
+	_ = viper.BindPFlag("rsaPub", broadcastCmd.Flags().Lookup("rsaPub"))
+
+	broadcastCmd.Flags().StringP("salt", "", "",
+		"Broadcast channel salt")
+	_ = viper.BindPFlag("salt", broadcastCmd.Flags().Lookup("salt"))
+
+	broadcastCmd.Flags().StringP("description", "", "",
+		"Broadcast channel description")
+	_ = viper.BindPFlag("description", broadcastCmd.Flags().Lookup("description"))
+
+	broadcastCmd.Flags().StringP("chanPath", "", "",
+		"Broadcast channel output path")
+	_ = viper.BindPFlag("chanPath", broadcastCmd.Flags().Lookup("chanPath"))
+
+	broadcastCmd.Flags().StringP("keyPath", "", "",
+		"Broadcast channel private key output path")
+	_ = viper.BindPFlag("keyPath", broadcastCmd.Flags().Lookup("keyPath"))
+
+	broadcastCmd.Flags().BoolP("new", "", false,
+		"Create new broadcast channel")
+	_ = viper.BindPFlag("new", broadcastCmd.Flags().Lookup("new"))
+
+	broadcastCmd.Flags().StringP("broadcast", "", "",
+		"Message contents for broadcast")
+	_ = viper.BindPFlag("broadcast", broadcastCmd.Flags().Lookup("broadcast"))
+
+	broadcastCmd.Flags().BoolP("symmetric", "", false,
+		"Set broadcast method to symmetric")
+	_ = viper.BindPFlag("symmetric", broadcastCmd.Flags().Lookup("symmetric"))
+
+	broadcastCmd.Flags().BoolP("asymmetric", "", false,
+		"Set broadcast method to asymmetric")
+	_ = viper.BindPFlag("asymmetric", broadcastCmd.Flags().Lookup("asymmetric"))
+
+	rootCmd.AddCommand(broadcastCmd)
+}
diff --git a/cmd/root.go b/cmd/root.go
index cc49169e05fddc183824c9e88b335135dc5c5ef2..aeca80079417004ec2e4a568bd594d2522ba5ec8 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -1071,9 +1071,9 @@ func init() {
 		"Ensure successful message sending by checking for round completion")
 	viper.BindPFlag("verify-sends", rootCmd.Flags().Lookup("verify-sends"))
 
-	rootCmd.Flags().UintP("receiveCount",
+	rootCmd.PersistentFlags().UintP("receiveCount",
 		"", 1, "How many messages we should wait for before quitting")
-	viper.BindPFlag("receiveCount", rootCmd.Flags().Lookup("receiveCount"))
+	viper.BindPFlag("receiveCount", rootCmd.PersistentFlags().Lookup("receiveCount"))
 	rootCmd.PersistentFlags().UintP("waitTimeout", "", 15,
 		"The number of seconds to wait for messages to arrive")
 	viper.BindPFlag("waitTimeout",
diff --git a/cmix/gateway/hostPool.go b/cmix/gateway/hostPool.go
index 25dc7192ed9933dcf323190a526c772a1548e8a3..09f52d5bd30eaae4d768e58eb0ae3a5120aa8cce 100644
--- a/cmix/gateway/hostPool.go
+++ b/cmix/gateway/hostPool.go
@@ -14,6 +14,7 @@ package gateway
 
 import (
 	"encoding/binary"
+	"encoding/json"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/storage"
@@ -108,7 +109,18 @@ type PoolParams struct {
 	ForceConnection bool
 
 	// HostParams is the parameters for the creation of new Host objects.
-	HostParams connect.HostParams
+	//fixme params: have this adhere to json.Marshaler.
+	// This will allow the PoolParams object to have full adherence.
+	HostParams connect.HostParams `json:"-"`
+}
+
+// poolParamsDisk will be the marshal-able and umarshal-able object.
+type poolParamsDisk struct {
+	MaxPoolSize     uint32
+	PoolSize        uint32
+	ProxyAttempts   uint32
+	MaxPings        uint32
+	ForceConnection bool
 }
 
 // DefaultPoolParams returns a default set of PoolParams.
@@ -132,6 +144,54 @@ func DefaultPoolParams() PoolParams {
 	return p
 }
 
+// GetParameters returns the default PoolParams, or
+// override with given parameters, if set.
+func GetParameters(params string) (PoolParams, error) {
+	p := DefaultPoolParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return PoolParams{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (pp PoolParams) MarshalJSON() ([]byte, error) {
+	ppd := poolParamsDisk{
+		MaxPoolSize:     pp.MaxPoolSize,
+		PoolSize:        pp.PoolSize,
+		ProxyAttempts:   pp.ProxyAttempts,
+		MaxPings:        pp.MaxPings,
+		ForceConnection: pp.ForceConnection,
+	}
+
+	return json.Marshal(&ppd)
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (pp *PoolParams) UnmarshalJSON(data []byte) error {
+	ppDisk := poolParamsDisk{}
+	err := json.Unmarshal(data, &ppDisk)
+	if err != nil {
+		return err
+	}
+
+	*pp = PoolParams{
+		MaxPoolSize:     ppDisk.MaxPoolSize,
+		PoolSize:        ppDisk.PoolSize,
+		ProxyAttempts:   ppDisk.ProxyAttempts,
+		MaxPings:        ppDisk.MaxPings,
+		ForceConnection: ppDisk.ForceConnection,
+		// Since this does not adhere to json.Marshaler yet,
+		// file it in manually assuming default values
+		HostParams: connect.GetDefaultHostParams(),
+	}
+
+	return nil
+}
+
 // newHostPool builds and returns a new HostPool object.
 func newHostPool(poolParams PoolParams, rng *fastRNG.StreamGenerator,
 	netDef *ndf.NetworkDefinition, getter HostManager, storage storage.Session,
diff --git a/cmix/identity/receptionID/store/unknownRounds.go b/cmix/identity/receptionID/store/unknownRounds.go
index 022fd252dba2d7dbaaec14a072e5dbac6623ff25..b14c939abdd27e72a284bf37ba71e763b6bd0536 100644
--- a/cmix/identity/receptionID/store/unknownRounds.go
+++ b/cmix/identity/receptionID/store/unknownRounds.go
@@ -24,21 +24,6 @@ const (
 	defaultMaxCheck             = 3
 )
 
-// UnknownRounds tracks data for unknown rounds. Should adhere to UnknownRounds
-// interface.
-type UnknownRounds struct {
-	// Maps an unknown round to how many times the round has been checked
-	rounds map[id.Round]*uint64
-
-	// Configurations of UnknownRounds
-	params UnknownRoundsParams
-
-	// Key Value store to save data to disk
-	kv *versioned.KV
-
-	mux sync.Mutex
-}
-
 // UnknownRoundsParams allows configuration of UnknownRounds parameters.
 type UnknownRoundsParams struct {
 	// MaxChecks is the maximum amount of checks of a round before that round
@@ -49,6 +34,12 @@ type UnknownRoundsParams struct {
 	Stored bool
 }
 
+// unknownRoundsParamsDisk will be the marshal-able and umarshal-able object.
+type unknownRoundsParamsDisk struct {
+	MaxChecks uint64
+	Stored    bool
+}
+
 // DefaultUnknownRoundsParams returns a default set of UnknownRoundsParams.
 func DefaultUnknownRoundsParams() UnknownRoundsParams {
 	return UnknownRoundsParams{
@@ -57,6 +48,60 @@ func DefaultUnknownRoundsParams() UnknownRoundsParams {
 	}
 }
 
+// GetParameters returns the default UnknownRoundsParams,
+// or override with given parameters, if set.
+func GetParameters(params string) (UnknownRoundsParams, error) {
+	p := DefaultUnknownRoundsParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return UnknownRoundsParams{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (urp UnknownRoundsParams) MarshalJSON() ([]byte, error) {
+	urpDisk := unknownRoundsParamsDisk{
+		MaxChecks: urp.MaxChecks,
+		Stored:    urp.Stored,
+	}
+
+	return json.Marshal(&urpDisk)
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (urp *UnknownRoundsParams) UnmarshalJSON(data []byte) error {
+	urpDisk := unknownRoundsParamsDisk{}
+	err := json.Unmarshal(data, &urpDisk)
+	if err != nil {
+		return err
+	}
+
+	*urp = UnknownRoundsParams{
+		MaxChecks: urpDisk.MaxChecks,
+		Stored:    urpDisk.Stored,
+	}
+
+	return nil
+}
+
+// UnknownRounds tracks data for unknown rounds. Should adhere to UnknownRounds
+// interface.
+type UnknownRounds struct {
+	// Maps an unknown round to how many times the round has been checked
+	rounds map[id.Round]*uint64
+
+	// Configurations of UnknownRounds
+	params UnknownRoundsParams
+
+	// Key Value store to save data to disk
+	kv *versioned.KV
+
+	mux sync.Mutex
+}
+
 // NewUnknownRounds builds and returns a new UnknownRounds object.
 func NewUnknownRounds(kv *versioned.KV,
 	params UnknownRoundsParams) *UnknownRounds {
diff --git a/cmix/message/params.go b/cmix/message/params.go
index 9a3a56cd599860416ebe2951048c2c5ac7767987..cd2e6675bff9ad8eb6303b40c32a01f80ba152ea 100644
--- a/cmix/message/params.go
+++ b/cmix/message/params.go
@@ -1,7 +1,18 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
 package message
 
-import "time"
+import (
+	"encoding/json"
+	"time"
+)
 
+// Params contains the parameters for the message package.
 type Params struct {
 	MessageReceptionBuffLen        uint
 	MessageReceptionWorkerPoolSize uint
@@ -10,6 +21,17 @@ type Params struct {
 	RealtimeOnly                   bool
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	MessageReceptionBuffLen        uint
+	MessageReceptionWorkerPoolSize uint
+	MaxChecksInProcessMessage      uint
+	InProcessMessageWait           time.Duration
+	RealtimeOnly                   bool
+}
+
+// GetDefaultParams returns a Params object containing the
+// default parameters.
 func GetDefaultParams() Params {
 	return Params{
 		MessageReceptionBuffLen:        500,
@@ -19,3 +41,49 @@ func GetDefaultParams() Params {
 		RealtimeOnly:                   false,
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		MessageReceptionBuffLen:        p.MessageReceptionBuffLen,
+		MessageReceptionWorkerPoolSize: p.MessageReceptionWorkerPoolSize,
+		MaxChecksInProcessMessage:      p.MaxChecksInProcessMessage,
+		InProcessMessageWait:           p.InProcessMessageWait,
+		RealtimeOnly:                   p.RealtimeOnly,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		MessageReceptionBuffLen:        pDisk.MessageReceptionBuffLen,
+		MessageReceptionWorkerPoolSize: pDisk.MessageReceptionWorkerPoolSize,
+		MaxChecksInProcessMessage:      pDisk.MaxChecksInProcessMessage,
+		InProcessMessageWait:           pDisk.InProcessMessageWait,
+		RealtimeOnly:                   pDisk.RealtimeOnly,
+	}
+
+	return nil
+}
diff --git a/cmix/params.go b/cmix/params.go
index d823632e199e021606a3414bc2403babcc3d17b9..d8aa778b104dadbdfa0e28215e00f0a10f5b6761 100644
--- a/cmix/params.go
+++ b/cmix/params.go
@@ -1,3 +1,10 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
 package cmix
 
 import (
@@ -57,6 +64,26 @@ type Params struct {
 	Historical rounds.Params
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	TrackNetworkPeriod        time.Duration
+	MaxCheckedRounds          uint
+	RegNodesBufferLen         uint
+	NetworkHealthTimeout      time.Duration
+	ParallelNodeRegistrations uint
+	KnownRoundsThreshold      uint
+	FastPolling               bool
+	VerboseRoundTracking      bool
+	RealtimeOnly              bool
+	ReplayRequests            bool
+	Rounds                    rounds.Params
+	Pickup                    pickup.Params
+	Message                   message.Params
+	Historical                rounds.Params
+}
+
+// GetDefaultParams returns a Params object containing the
+// default parameters.
 func GetDefaultParams() Params {
 	n := Params{
 		TrackNetworkPeriod:        100 * time.Millisecond,
@@ -78,18 +105,7 @@ func GetDefaultParams() Params {
 	return n
 }
 
-func (n Params) Marshal() ([]byte, error) {
-	return json.Marshal(n)
-}
-
-func (n Params) SetRealtimeOnlyAll() Params {
-	n.RealtimeOnly = true
-	n.Pickup.RealtimeOnly = true
-	n.Message.RealtimeOnly = true
-	return n
-}
-
-// GetParameters returns the default network parameters, or override with given
+// GetParameters returns the default Params, or override with given
 // parameters, if set.
 func GetParameters(params string) (Params, error) {
 	p := GetDefaultParams()
@@ -102,7 +118,62 @@ func GetParameters(params string) (Params, error) {
 	return p, nil
 }
 
-type NodeMap map[id.ID]bool
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		TrackNetworkPeriod:        p.TrackNetworkPeriod,
+		MaxCheckedRounds:          p.MaxCheckedRounds,
+		RegNodesBufferLen:         p.RegNodesBufferLen,
+		NetworkHealthTimeout:      p.NetworkHealthTimeout,
+		ParallelNodeRegistrations: p.ParallelNodeRegistrations,
+		KnownRoundsThreshold:      p.KnownRoundsThreshold,
+		FastPolling:               p.FastPolling,
+		VerboseRoundTracking:      p.VerboseRoundTracking,
+		RealtimeOnly:              p.RealtimeOnly,
+		ReplayRequests:            p.ReplayRequests,
+		Rounds:                    p.Rounds,
+		Pickup:                    p.Pickup,
+		Message:                   p.Message,
+		Historical:                p.Historical,
+	}
+
+	return json.Marshal(&pDisk)
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		TrackNetworkPeriod:        pDisk.TrackNetworkPeriod,
+		MaxCheckedRounds:          pDisk.MaxCheckedRounds,
+		RegNodesBufferLen:         pDisk.RegNodesBufferLen,
+		NetworkHealthTimeout:      pDisk.NetworkHealthTimeout,
+		ParallelNodeRegistrations: pDisk.ParallelNodeRegistrations,
+		KnownRoundsThreshold:      pDisk.KnownRoundsThreshold,
+		FastPolling:               pDisk.FastPolling,
+		VerboseRoundTracking:      pDisk.VerboseRoundTracking,
+		RealtimeOnly:              pDisk.RealtimeOnly,
+		ReplayRequests:            pDisk.ReplayRequests,
+		Rounds:                    pDisk.Rounds,
+		Pickup:                    pDisk.Pickup,
+		Message:                   pDisk.Message,
+		Historical:                pDisk.Historical,
+	}
+
+	return nil
+}
+
+func (p Params) SetRealtimeOnlyAll() Params {
+	p.RealtimeOnly = true
+	p.Pickup.RealtimeOnly = true
+	p.Message.RealtimeOnly = true
+	return p
+}
 
 const DefaultDebugTag = "External"
 
@@ -137,6 +208,17 @@ type CMIXParams struct {
 	Critical bool
 }
 
+// cMixParamsDisk will be the marshal-able and umarshal-able object.
+type cMixParamsDisk struct {
+	RoundTries       uint
+	Timeout          time.Duration
+	RetryDelay       time.Duration
+	SendTimeout      time.Duration
+	DebugTag         string
+	BlacklistedNodes NodeMap
+	Critical         bool
+}
+
 func GetDefaultCMIXParams() CMIXParams {
 	return CMIXParams{
 		RoundTries:  10,
@@ -163,6 +245,47 @@ func GetCMIXParameters(params string) (CMIXParams, error) {
 	return p, nil
 }
 
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p CMIXParams) MarshalJSON() ([]byte, error) {
+	pDisk := cMixParamsDisk{
+		RoundTries:       p.RoundTries,
+		Timeout:          p.Timeout,
+		RetryDelay:       p.RetryDelay,
+		SendTimeout:      p.SendTimeout,
+		DebugTag:         p.DebugTag,
+		Critical:         p.Critical,
+		BlacklistedNodes: p.BlacklistedNodes,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *CMIXParams) UnmarshalJSON(data []byte) error {
+	pDisk := cMixParamsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = CMIXParams{
+		RoundTries:       pDisk.RoundTries,
+		Timeout:          pDisk.Timeout,
+		RetryDelay:       pDisk.RetryDelay,
+		SendTimeout:      pDisk.SendTimeout,
+		DebugTag:         pDisk.DebugTag,
+		Critical:         pDisk.Critical,
+		BlacklistedNodes: pDisk.BlacklistedNodes,
+	}
+
+	return nil
+}
+
+// NodeMap represents a map of nodes and whether they have been
+// blacklisted. This is designed for use with CMIXParams.BlacklistedNodes
+type NodeMap map[id.ID]bool
+
 // MarshalJSON adheres to the json.Marshaler interface.
 func (nm NodeMap) MarshalJSON() ([]byte, error) {
 	stringMap := make(map[string]bool, len(nm))
diff --git a/cmix/params_test.go b/cmix/params_test.go
index bb19499b3640c5234ece0b9a14d2cd7789649872..90ece9d5f6ff0dbf23a528832a0adc297425818e 100644
--- a/cmix/params_test.go
+++ b/cmix/params_test.go
@@ -8,6 +8,7 @@
 package cmix
 
 import (
+	"bytes"
 	"encoding/json"
 	"gitlab.com/xx_network/primitives/id"
 	"reflect"
@@ -15,6 +16,43 @@ import (
 	"time"
 )
 
+// Tests that no data is lost when marshaling and
+// unmarshaling the Params object.
+func TestParams_MarshalUnmarshal(t *testing.T) {
+	// Construct a set of params
+	p := GetDefaultParams()
+
+	// Marshal the params
+	data, err := json.Marshal(&p)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data))
+
+	// Unmarshal the params object
+	received := Params{}
+	err = json.Unmarshal(data, &received)
+	if err != nil {
+		t.Fatalf("Unmarshal error: %v", err)
+	}
+
+	// Re-marshal this params object
+	data2, err := json.Marshal(received)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data2))
+
+	// Check that they match (it is done this way to avoid
+	// false failures with the reflect.DeepEqual function and
+	// pointers)
+	if !bytes.Equal(data, data2) {
+		t.Fatalf("Data was lost in marshal/unmarshal.")
+	}
+}
+
 func TestCMIXParams_JSON_Marshal_Unmarshal(t *testing.T) {
 	p := CMIXParams{
 		RoundTries:  5,
diff --git a/cmix/pickup/params.go b/cmix/pickup/params.go
index 95200674d0e0e8a791a0236e1a5dc019b4b59225..99ec4cb835557f411d3d88cdf07acc23e40dba14 100644
--- a/cmix/pickup/params.go
+++ b/cmix/pickup/params.go
@@ -1,7 +1,18 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
 package pickup
 
-import "time"
+import (
+	"encoding/json"
+	"time"
+)
 
+// Params contains the parameters for the pickup package.
 type Params struct {
 	// Number of worker threads for retrieving messages from gateways
 	NumMessageRetrievalWorkers uint
@@ -31,6 +42,19 @@ type Params struct {
 	ForceHistoricalRounds bool
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	NumMessageRetrievalWorkers uint
+	LookupRoundsBufferLen      uint
+	MaxHistoricalRoundsRetries uint
+	UncheckRoundPeriod         time.Duration
+	ForceMessagePickupRetry    bool
+	SendTimeout                time.Duration
+	RealtimeOnly               bool
+	ForceHistoricalRounds      bool
+}
+
+// GetDefaultParams returns a default set of Params.
 func GetDefaultParams() Params {
 	return Params{
 		NumMessageRetrievalWorkers: 8,
@@ -42,3 +66,55 @@ func GetDefaultParams() Params {
 		RealtimeOnly:               false,
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		NumMessageRetrievalWorkers: p.NumMessageRetrievalWorkers,
+		LookupRoundsBufferLen:      p.LookupRoundsBufferLen,
+		MaxHistoricalRoundsRetries: p.MaxHistoricalRoundsRetries,
+		UncheckRoundPeriod:         p.UncheckRoundPeriod,
+		ForceMessagePickupRetry:    p.ForceMessagePickupRetry,
+		SendTimeout:                p.SendTimeout,
+		RealtimeOnly:               p.RealtimeOnly,
+		ForceHistoricalRounds:      p.ForceHistoricalRounds,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		NumMessageRetrievalWorkers: pDisk.NumMessageRetrievalWorkers,
+		LookupRoundsBufferLen:      pDisk.LookupRoundsBufferLen,
+		MaxHistoricalRoundsRetries: pDisk.MaxHistoricalRoundsRetries,
+		UncheckRoundPeriod:         pDisk.UncheckRoundPeriod,
+		ForceMessagePickupRetry:    pDisk.ForceMessagePickupRetry,
+		SendTimeout:                pDisk.SendTimeout,
+		RealtimeOnly:               pDisk.RealtimeOnly,
+		ForceHistoricalRounds:      pDisk.ForceHistoricalRounds,
+	}
+
+	return nil
+}
diff --git a/cmix/rounds/params.go b/cmix/rounds/params.go
index 1023f6022acce31a971747c5f31bfebdec724c03..dd9596c2fcf6809010ceb9fbeda609f2ef3b6645 100644
--- a/cmix/rounds/params.go
+++ b/cmix/rounds/params.go
@@ -1,7 +1,18 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
 package rounds
 
-import "time"
+import (
+	"encoding/json"
+	"time"
+)
 
+// Params contains the parameters for the rounds package.
 type Params struct {
 	// MaxHistoricalRounds is the number of historical rounds required to
 	// automatically send a historical rounds query.
@@ -20,6 +31,15 @@ type Params struct {
 	MaxHistoricalRoundsRetries uint
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	MaxHistoricalRounds        uint
+	HistoricalRoundsPeriod     time.Duration
+	HistoricalRoundsBufferLen  uint
+	MaxHistoricalRoundsRetries uint
+}
+
+// GetDefaultParams returns a default set of Params.
 func GetDefaultParams() Params {
 	return Params{
 		MaxHistoricalRounds:        100,
@@ -28,3 +48,47 @@ func GetDefaultParams() Params {
 		MaxHistoricalRoundsRetries: 3,
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (r Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		MaxHistoricalRounds:        r.MaxHistoricalRounds,
+		HistoricalRoundsPeriod:     r.HistoricalRoundsPeriod,
+		HistoricalRoundsBufferLen:  r.HistoricalRoundsBufferLen,
+		MaxHistoricalRoundsRetries: r.MaxHistoricalRoundsRetries,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (r *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*r = Params{
+		MaxHistoricalRounds:        pDisk.MaxHistoricalRounds,
+		HistoricalRoundsPeriod:     pDisk.HistoricalRoundsPeriod,
+		HistoricalRoundsBufferLen:  pDisk.HistoricalRoundsBufferLen,
+		MaxHistoricalRoundsRetries: pDisk.MaxHistoricalRoundsRetries,
+	}
+
+	return nil
+}
diff --git a/connect/connect.go b/connect/connect.go
index e5c544672de6358aac88a5fbe331880c50f74a43..310ef304a868f769068ac1d8d95b82ceb28b2945 100644
--- a/connect/connect.go
+++ b/connect/connect.go
@@ -7,6 +7,7 @@
 package connect
 
 import (
+	"encoding/json"
 	"io"
 	"time"
 
@@ -84,9 +85,9 @@ type Callback func(connection Connection)
 
 // Params for managing Connection objects.
 type Params struct {
-	Auth    auth.Param
+	Auth    auth.Params
 	Rekey   rekey.Params
-	Event   event.Reporter
+	Event   event.Reporter `json:"-"`
 	Timeout time.Duration
 }
 
@@ -100,6 +101,19 @@ func GetDefaultParams() Params {
 	}
 }
 
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
 // Connect performs auth key negotiation with the given recipient,
 // and returns a Connection object for the newly-created partner.Manager
 // This function is to be used sender-side and will block until the
diff --git a/connect/params_test.go b/connect/params_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5501ad55153af983a72df2b0ab4d1e8b64358628
--- /dev/null
+++ b/connect/params_test.go
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                           //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file                                                               //
+////////////////////////////////////////////////////////////////////////////////
+
+package connect
+
+import (
+	"bytes"
+	"encoding/json"
+	"testing"
+)
+
+func TestParams_MarshalUnmarshal(t *testing.T) {
+	// Construct a set of params
+	p := GetDefaultParams()
+
+	// Marshal the params
+	data, err := json.Marshal(&p)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data))
+
+	// Unmarshal the params object
+	received := Params{}
+	err = json.Unmarshal(data, &received)
+	if err != nil {
+		t.Fatalf("Unmarshal error: %v", err)
+	}
+
+	// Re-marshal this params object
+	data2, err := json.Marshal(received)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data2))
+
+	// Check that they match (it is done this way to avoid
+	// false failures with the reflect.DeepEqual function and
+	// pointers)
+	if !bytes.Equal(data, data2) {
+		t.Fatalf("Data was lost in marshal/unmarshal.")
+	}
+}
diff --git a/e2e/params.go b/e2e/params.go
index 23052727ffcc103f62e14c5d41fad2fbcabfe244..2702d490656342e975883177b115f63dbf2df961 100644
--- a/e2e/params.go
+++ b/e2e/params.go
@@ -29,6 +29,17 @@ type Params struct {
 	cmix.CMIXParams
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	ServiceTag       string
+	LastServiceTag   string
+	KeyGetRetryCount uint
+	KeyGeRetryDelay  time.Duration
+	Rekey            bool
+	cmix.CMIXParams
+}
+
+// GetDefaultParams returns a default set of Params.
 func GetDefaultParams() Params {
 	return Params{
 		ServiceTag:     catalog.Silent,
@@ -41,12 +52,9 @@ func GetDefaultParams() Params {
 		CMIXParams: cmix.GetDefaultCMIXParams(),
 	}
 }
-func (e Params) Marshal() ([]byte, error) {
-	return json.Marshal(e)
-}
 
-// GetParameters Obtain default E2E parameters, or override with
-// given parameters if set
+// GetParameters Obtain default Params, or override with
+// given parameters if set.
 func GetParameters(params string) (Params, error) {
 	p := GetDefaultParams()
 	if len(params) > 0 {
@@ -57,3 +65,38 @@ func GetParameters(params string) (Params, error) {
 	}
 	return p, nil
 }
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		ServiceTag:       p.ServiceTag,
+		LastServiceTag:   p.LastServiceTag,
+		KeyGetRetryCount: p.KeyGetRetryCount,
+		KeyGeRetryDelay:  p.KeyGeRetryDelay,
+		Rekey:            p.Rekey,
+		CMIXParams:       p.CMIXParams,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		ServiceTag:       pDisk.ServiceTag,
+		LastServiceTag:   pDisk.LastServiceTag,
+		KeyGetRetryCount: pDisk.KeyGetRetryCount,
+		KeyGeRetryDelay:  pDisk.KeyGeRetryDelay,
+		Rekey:            pDisk.Rekey,
+		CMIXParams:       pDisk.CMIXParams,
+	}
+
+	return nil
+}
diff --git a/e2e/ratchet/partner/session/params.go b/e2e/ratchet/partner/session/params.go
index 8ccd454947ff281471cd77d79fa15ea826efec9d..2782578e9e605d117d2bb872f40822816c0fde2f 100644
--- a/e2e/ratchet/partner/session/params.go
+++ b/e2e/ratchet/partner/session/params.go
@@ -1,6 +1,20 @@
 package session
 
-import "fmt"
+import (
+	"encoding/json"
+	"fmt"
+)
+
+// DEFAULT KEY GENERATION PARAMETERS
+// Hardcoded limits for keys
+// sets the number of keys very high, but with a low rekey threshold. In this case, if the other party is online, you will read
+const (
+	minKeys       uint16  = 1000
+	maxKeys       uint16  = 2000
+	rekeyThrshold float64 = 0.05
+	numReKeys     uint16  = 16
+	rekeyRatio    float64 = 1 / 10
+)
 
 type Params struct {
 	// using the DH as a seed, both sides finalizeKeyNegotation a number
@@ -20,17 +34,16 @@ type Params struct {
 	UnconfirmedRetryRatio float64
 }
 
-// DEFAULT KEY GENERATION PARAMETERS
-// Hardcoded limits for keys
-// sets the number of keys very high, but with a low rekey threshold. In this case, if the other party is online, you will read
-const (
-	minKeys       uint16  = 1000
-	maxKeys       uint16  = 2000
-	rekeyThrshold float64 = 0.05
-	numReKeys     uint16  = 16
-	rekeyRatio    float64 = 1 / 10
-)
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	MinKeys               uint16
+	MaxKeys               uint16
+	RekeyThreshold        float64
+	NumRekeys             uint16
+	UnconfirmedRetryRatio float64
+}
 
+// GetDefaultParams returns a default set of Params.
 func GetDefaultParams() Params {
 	return Params{
 		MinKeys:               minKeys,
@@ -41,6 +54,50 @@ func GetDefaultParams() Params {
 	}
 }
 
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		MinKeys:               p.MinKeys,
+		MaxKeys:               p.MaxKeys,
+		RekeyThreshold:        p.RekeyThreshold,
+		NumRekeys:             p.NumRekeys,
+		UnconfirmedRetryRatio: p.UnconfirmedRetryRatio,
+	}
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		MinKeys:               pDisk.MinKeys,
+		MaxKeys:               pDisk.MaxKeys,
+		RekeyThreshold:        pDisk.RekeyThreshold,
+		NumRekeys:             pDisk.NumRekeys,
+		UnconfirmedRetryRatio: pDisk.UnconfirmedRetryRatio,
+	}
+	return nil
+}
+
 func (p Params) String() string {
 	return fmt.Sprintf("SessionParams{ MinKeys: %d, MaxKeys: %d, NumRekeys: %d }",
 		p.MinKeys, p.MaxKeys, p.NumRekeys)
diff --git a/e2e/rekey/params.go b/e2e/rekey/params.go
index 0611e67e84b4875bae35f29855fbddc0e007fe83..274770c112329cb552a85df55c6abc6d273cf67c 100644
--- a/e2e/rekey/params.go
+++ b/e2e/rekey/params.go
@@ -1,6 +1,7 @@
 package rekey
 
 import (
+	"encoding/json"
 	"gitlab.com/elixxir/client/catalog"
 	"time"
 )
@@ -22,6 +23,17 @@ type Params struct {
 	StoppableName string
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	RoundTimeout  time.Duration
+	TriggerName   string
+	Trigger       catalog.MessageType
+	ConfirmName   string
+	Confirm       catalog.MessageType
+	StoppableName string
+}
+
+// GetDefaultParams returns a default set of Params.
 func GetDefaultParams() Params {
 	return Params{
 		RoundTimeout:  time.Minute,
@@ -33,6 +45,8 @@ func GetDefaultParams() Params {
 	}
 }
 
+// GetDefaultEphemeralParams returns a default set of Params for
+// ephemeral re-keying.
 func GetDefaultEphemeralParams() Params {
 	p := GetDefaultParams()
 	p.TriggerName = keyExchangeTriggerEphemeralName
@@ -42,3 +56,50 @@ func GetDefaultEphemeralParams() Params {
 	p.StoppableName = keyExchangeEphemeralMulti
 	return p
 }
+
+// GetParameters returns the default network parameters, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := GetDefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		RoundTimeout:  p.RoundTimeout,
+		TriggerName:   p.TriggerName,
+		Trigger:       p.Trigger,
+		ConfirmName:   p.ConfirmName,
+		Confirm:       p.Confirm,
+		StoppableName: p.StoppableName,
+	}
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		RoundTimeout:  pDisk.RoundTimeout,
+		TriggerName:   pDisk.TriggerName,
+		Trigger:       pDisk.Trigger,
+		ConfirmName:   pDisk.ConfirmName,
+		Confirm:       pDisk.Confirm,
+		StoppableName: pDisk.StoppableName,
+	}
+
+	return nil
+}
diff --git a/fileTransfer/params.go b/fileTransfer/params.go
index 754bb88db3d45c75f3e47454f45bf4cf6170e830..8e54d5d02c9430224f526008d9138cb35e08e1ce 100644
--- a/fileTransfer/params.go
+++ b/fileTransfer/params.go
@@ -7,7 +7,10 @@
 
 package fileTransfer
 
-import "time"
+import (
+	"encoding/json"
+	"time"
+)
 
 const (
 	defaultMaxThroughput = 150_000 // 150 kB per second
@@ -26,6 +29,12 @@ type Params struct {
 	SendTimeout time.Duration
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	MaxThroughput int
+	SendTimeout   time.Duration
+}
+
 // DefaultParams returns a Params object filled with the default values.
 func DefaultParams() Params {
 	return Params{
@@ -33,3 +42,42 @@ func DefaultParams() Params {
 		SendTimeout:   defaultSendTimeout,
 	}
 }
+
+// GetParameters returns the default network parameters, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := DefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		MaxThroughput: p.MaxThroughput,
+		SendTimeout:   p.SendTimeout,
+	}
+
+	return json.Marshal(&pDisk)
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		MaxThroughput: pDisk.MaxThroughput,
+		SendTimeout:   pDisk.SendTimeout,
+	}
+
+	return nil
+}
diff --git a/fileTransfer2/connect/params.go b/fileTransfer2/connect/params.go
index 3b502637e895a852b8ab11c0118d0806659c073a..93a3a44a1f6a6d001724875bd85ba5fd13374a54 100644
--- a/fileTransfer2/connect/params.go
+++ b/fileTransfer2/connect/params.go
@@ -7,6 +7,10 @@
 
 package connect
 
+import (
+	"encoding/json"
+)
+
 const (
 	defaultNotifyUponCompletion = true
 )
@@ -18,9 +22,47 @@ type Params struct {
 	NotifyUponCompletion bool
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	NotifyUponCompletion bool
+}
+
 // DefaultParams returns a Params object filled with the default values.
 func DefaultParams() Params {
 	return Params{
 		NotifyUponCompletion: defaultNotifyUponCompletion,
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := DefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{NotifyUponCompletion: p.NotifyUponCompletion}
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{NotifyUponCompletion: pDisk.NotifyUponCompletion}
+
+	return nil
+}
diff --git a/fileTransfer2/e2e/params.go b/fileTransfer2/e2e/params.go
index 254e7d3a40777ec48c8ad33c89b95ccacaf5d2d9..819e963f5fd9efc3d058b5a953e87c7aa8874f1f 100644
--- a/fileTransfer2/e2e/params.go
+++ b/fileTransfer2/e2e/params.go
@@ -7,6 +7,8 @@
 
 package e2e
 
+import "encoding/json"
+
 const (
 	defaultNotifyUponCompletion = true
 )
@@ -18,9 +20,47 @@ type Params struct {
 	NotifyUponCompletion bool
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	NotifyUponCompletion bool
+}
+
 // DefaultParams returns a Params object filled with the default values.
 func DefaultParams() Params {
 	return Params{
 		NotifyUponCompletion: defaultNotifyUponCompletion,
 	}
 }
+
+// GetParameters returns the default Params, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := DefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{NotifyUponCompletion: p.NotifyUponCompletion}
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{NotifyUponCompletion: pDisk.NotifyUponCompletion}
+
+	return nil
+}
diff --git a/fileTransfer2/params.go b/fileTransfer2/params.go
index b4f1587bec6584e143b65d70d572cf740921bbb4..4a70046560b0e2793620f8bf29d5c1c62078b6f1 100644
--- a/fileTransfer2/params.go
+++ b/fileTransfer2/params.go
@@ -8,6 +8,7 @@
 package fileTransfer2
 
 import (
+	"encoding/json"
 	"gitlab.com/elixxir/client/cmix"
 	"time"
 )
@@ -32,6 +33,13 @@ type Params struct {
 	Cmix cmix.CMIXParams
 }
 
+// paramsDisk will be the marshal-able and umarshal-able object.
+type paramsDisk struct {
+	MaxThroughput int
+	SendTimeout   time.Duration
+	Cmix          cmix.CMIXParams
+}
+
 // DefaultParams returns a Params object filled with the default values.
 func DefaultParams() Params {
 	return Params{
@@ -40,3 +48,45 @@ func DefaultParams() Params {
 		Cmix:          cmix.GetDefaultCMIXParams(),
 	}
 }
+
+// GetParameters returns the default network parameters, or override with given
+// parameters, if set.
+func GetParameters(params string) (Params, error) {
+	p := DefaultParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return Params{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (p Params) MarshalJSON() ([]byte, error) {
+	pDisk := paramsDisk{
+		MaxThroughput: p.MaxThroughput,
+		SendTimeout:   p.SendTimeout,
+		Cmix:          p.Cmix,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (p *Params) UnmarshalJSON(data []byte) error {
+	pDisk := paramsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*p = Params{
+		MaxThroughput: pDisk.MaxThroughput,
+		SendTimeout:   pDisk.SendTimeout,
+		Cmix:          pDisk.Cmix,
+	}
+
+	return nil
+}
diff --git a/fileTransfer2/params_test.go b/fileTransfer2/params_test.go
index 849db501a81c9639e12890f8337a55ef85165263..8bbeb942b4f1c5f1d70e418ebf1c5f796dd84d4a 100644
--- a/fileTransfer2/params_test.go
+++ b/fileTransfer2/params_test.go
@@ -8,11 +8,51 @@
 package fileTransfer2
 
 import (
+	"bytes"
+	"encoding/json"
 	"gitlab.com/elixxir/client/cmix"
 	"reflect"
 	"testing"
 )
 
+// Tests that no data is lost when marshaling and
+// unmarshaling the Params object.
+func TestParams_MarshalUnmarshal(t *testing.T) {
+	// Construct a set of params
+	p := DefaultParams()
+
+	// Marshal the params
+	data, err := json.Marshal(&p)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data))
+
+	// Unmarshal the params object
+	received := Params{}
+	err = json.Unmarshal(data, &received)
+	if err != nil {
+		t.Fatalf("Unmarshal error: %v", err)
+	}
+
+	// Re-marshal this params object
+	data2, err := json.Marshal(received)
+	if err != nil {
+		t.Fatalf("Marshal error: %v", err)
+	}
+
+	t.Logf("%s", string(data2))
+
+	// Check that they match (it is done this way to avoid
+	// false failures with the reflect.DeepEqual function and
+	// pointers)
+	if !bytes.Equal(data, data2) {
+		t.Fatalf("Data was lost in marshal/unmarshal.")
+	}
+
+}
+
 // Tests that DefaultParams returns a Params object with the expected defaults.
 func TestDefaultParams(t *testing.T) {
 	expected := Params{
diff --git a/go.mod b/go.mod
index 5cc7bdbc98c27ad9aad0f873ef32a516cc24c9f8..45cbd29359501276d3da18b7745794d21cdaaa8c 100644
--- a/go.mod
+++ b/go.mod
@@ -13,11 +13,11 @@ require (
 	github.com/spf13/viper v1.7.1
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f
 	gitlab.com/elixxir/comms v0.0.4-0.20220323190139-9ed75f3a8b2c
-	gitlab.com/elixxir/crypto v0.0.7-0.20220425192911-a23209a58073
+	gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b
 	gitlab.com/elixxir/ekv v0.1.7
 	gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f
 	gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac
-	gitlab.com/xx_network/crypto v0.0.5-0.20220317171841-084640957d71
+	gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce
 	gitlab.com/xx_network/primitives v0.0.4-0.20220324193139-b292d1ae6e7e
 	go.uber.org/ratelimit v0.2.0
 	golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed
diff --git a/go.sum b/go.sum
index c8be2cdbd0727dfdcf41420df6ab683d01cdcf8b..c3aa45ee09d936b71b808d039ce87d0ea1bd0b5d 100644
--- a/go.sum
+++ b/go.sum
@@ -434,6 +434,14 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220425192754-f9f5ca6ad2eb h1:K10bnRhnZS6XFx
 gitlab.com/elixxir/crypto v0.0.7-0.20220425192754-f9f5ca6ad2eb/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4=
 gitlab.com/elixxir/crypto v0.0.7-0.20220425192911-a23209a58073 h1:T0BK30t1F9M8RCdsuMN1bL34fSLNPqjqC+oufnjPh3I=
 gitlab.com/elixxir/crypto v0.0.7-0.20220425192911-a23209a58073/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4=
+gitlab.com/elixxir/crypto v0.0.7-0.20220509151343-6e5a514a65fd h1:3lU8kF5ItUZYIuKHF6qrC3o1yiL6fKdF5p1HJRB9iik=
+gitlab.com/elixxir/crypto v0.0.7-0.20220509151343-6e5a514a65fd/go.mod h1:cJF80ad9YCR+UcOlZNzfDVBAQqGEEhhs3y5taMEvXaE=
+gitlab.com/elixxir/crypto v0.0.7-0.20220510191648-70e5e956d3d5 h1:uzzFrmqx0CnqQ7AInGi6PA8w1mm2032hIpYn2G2SDKA=
+gitlab.com/elixxir/crypto v0.0.7-0.20220510191648-70e5e956d3d5/go.mod h1:cJF80ad9YCR+UcOlZNzfDVBAQqGEEhhs3y5taMEvXaE=
+gitlab.com/elixxir/crypto v0.0.7-0.20220513133141-46faee2d8fca h1:0EINaZCe/0dPbQD2msOj8fwKpZ5lnZ57Y6zUZm85rEo=
+gitlab.com/elixxir/crypto v0.0.7-0.20220513133141-46faee2d8fca/go.mod h1:cJF80ad9YCR+UcOlZNzfDVBAQqGEEhhs3y5taMEvXaE=
+gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b h1:HZlcbi+rTr1MACtLoNUJDV2iTvy7JtkRjWWaPF45bcM=
+gitlab.com/elixxir/crypto v0.0.7-0.20220516144816-71049ce09e4b/go.mod h1:L3duHa+GppnsY8x22/ixrEdQSM7WXa1ORWPS90HZ/JI=
 gitlab.com/elixxir/ekv v0.1.6 h1:M2hUSNhH/ChxDd+s8xBqSEKgoPtmE6hOEBqQ73KbN6A=
 gitlab.com/elixxir/ekv v0.1.6/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
 gitlab.com/elixxir/ekv v0.1.7 h1:OW2z+N4QCqqMFzouAwFTWWMKz0Y/PDhyYReN7gQ5NiQ=
@@ -462,6 +470,10 @@ gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4 h1:95dZDMn/hpL
 gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4/go.mod h1:6apvsoHCQJDjO0J4E3uhR3yO9tTz/Mq5be5rjB3tQPU=
 gitlab.com/xx_network/crypto v0.0.5-0.20220317171841-084640957d71 h1:N2+Jja4xNg66entu6rGvzRcf3Vc785xgiaHeDPYnBvg=
 gitlab.com/xx_network/crypto v0.0.5-0.20220317171841-084640957d71/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
+gitlab.com/xx_network/crypto v0.0.5-0.20220502201458-dabab1ef2982 h1:iUMwO/lIeOEmqNTMPtr9d7H6Y0cGe4DaHhd+ISCts6E=
+gitlab.com/xx_network/crypto v0.0.5-0.20220502201458-dabab1ef2982/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
+gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce h1:zkPtJLJUpoWDYD4z30nmKU8OvnIOnBvSu7e6q6WhY5A=
+gitlab.com/xx_network/crypto v0.0.5-0.20220516143655-14f9153096ce/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
 gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
 gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVkHy+QogOB6F/qc=
diff --git a/single/params.go b/single/params.go
index 10d60a908022f6d7c0e4857133a8e7a7b8444306..8895818449ba626ea69a112226a8afd182cdc5f3 100644
--- a/single/params.go
+++ b/single/params.go
@@ -8,6 +8,7 @@
 package single
 
 import (
+	"encoding/json"
 	"gitlab.com/elixxir/client/cmix"
 	"time"
 )
@@ -32,6 +33,13 @@ type RequestParams struct {
 	CmixParams cmix.CMIXParams
 }
 
+// requestParamsDisk will be the marshal-able and umarshal-able object.
+type requestParamsDisk struct {
+	Timeout             time.Duration
+	MaxResponseMessages uint8
+	CmixParams          cmix.CMIXParams
+}
+
 // GetDefaultRequestParams returns a RequestParams with the default
 // configuration.
 func GetDefaultRequestParams() RequestParams {
@@ -41,3 +49,45 @@ func GetDefaultRequestParams() RequestParams {
 		CmixParams:          cmix.GetDefaultCMIXParams(),
 	}
 }
+
+// GetParameters returns the default network parameters, or override with given
+// parameters, if set.
+func GetParameters(params string) (RequestParams, error) {
+	p := GetDefaultRequestParams()
+	if len(params) > 0 {
+		err := json.Unmarshal([]byte(params), &p)
+		if err != nil {
+			return RequestParams{}, err
+		}
+	}
+	return p, nil
+}
+
+// MarshalJSON adheres to the json.Marshaler interface.
+func (rp RequestParams) MarshalJSON() ([]byte, error) {
+	pDisk := requestParamsDisk{
+		Timeout:             rp.Timeout,
+		MaxResponseMessages: rp.MaxResponseMessages,
+		CmixParams:          rp.CmixParams,
+	}
+
+	return json.Marshal(&pDisk)
+
+}
+
+// UnmarshalJSON adheres to the json.Unmarshaler interface.
+func (rp *RequestParams) UnmarshalJSON(data []byte) error {
+	pDisk := requestParamsDisk{}
+	err := json.Unmarshal(data, &pDisk)
+	if err != nil {
+		return err
+	}
+
+	*rp = RequestParams{
+		Timeout:             pDisk.Timeout,
+		MaxResponseMessages: pDisk.MaxResponseMessages,
+		CmixParams:          pDisk.CmixParams,
+	}
+
+	return nil
+}
diff --git a/single/params_test.go b/single/params_test.go
index 39f56c80c888e1496dffebb2b9f60d8951cd055e..7d8224c6127366af542baecb2e755475311967a0 100644
--- a/single/params_test.go
+++ b/single/params_test.go
@@ -8,11 +8,42 @@
 package single
 
 import (
+	"bytes"
+	"encoding/json"
 	"gitlab.com/elixxir/client/cmix"
 	"reflect"
 	"testing"
 )
 
+// Tests that no data is lost when marshaling and
+// unmarshaling the RequestParams object.
+func TestParams_MarshalUnmarshal(t *testing.T) {
+	p := GetDefaultRequestParams()
+	data, err := json.Marshal(p)
+	if err != nil {
+		t.Fatalf("Marshal error: %+v", err)
+	}
+
+	t.Logf("%s", string(data))
+
+	received := RequestParams{}
+	err = json.Unmarshal(data, &received)
+	if err != nil {
+		t.Fatalf("Unmarshal error: %+v", err)
+	}
+
+	data2, err := json.Marshal(received)
+	if err != nil {
+		t.Fatalf("Marshal error: %+v", err)
+	}
+
+	t.Logf("%s", string(data2))
+
+	if !bytes.Equal(data, data2) {
+		t.Fatalf("Data was lost in marshal/unmarshal.")
+	}
+}
+
 // Tests that GetDefaultRequestParams returns a RequestParams with the expected
 // default values.
 func TestGetDefaultRequestParams(t *testing.T) {