diff --git a/bindings/channels.go b/bindings/channels.go index 98e746041e1c88ec29cbf84a2148eb5f46d58614..a38faa188128663cd8ac4972085482c725738b47 100644 --- a/bindings/channels.go +++ b/bindings/channels.go @@ -331,6 +331,15 @@ func LoadChannelsManager(cmixID int, storageTag string, return channelManagerTrackerSingleton.make(m), nil } +// ChannelGeneration contains information about a newly generated channel. It +// contains the public channel info formatted in pretty print and the private +// key for the channel in PEM format. +// +// Example JSON: +// { +// "Channel": "\u003cSpeakeasy-v1:My_Channel,description:Here is information about my channel.,level:Public,secrets:8AS3SczFvAYZftWuj4ZkOM9muFPIwq/0HuVCUJgTK8w=,GpPl1510/G07J4RfdYX9J5plTX3WNLVm+uuGmCwgFeU=,5,1,mRfdUGM6WxWjjCuLzO+2+zc3BQh2zMT2CHD8ZnBwpVI=\u003e", +// "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMDECAQACBgDMIU9LpQIDAQABAgYAvCd9ewECAw0tzQIDD305AgMFu4UCAwd+kQID\nAQxc\n-----END RSA PRIVATE KEY-----" +// } type ChannelGeneration struct { Channel string PrivateKey string @@ -341,24 +350,35 @@ type ChannelGeneration struct { // // It returns a pretty print of the channel and the private key. // -// The name cannot be longer that __ characters. The description cannot be -// longer than __ and can only use ______ characters. -// // Parameters: // - cmixID - The tracked cmix object ID. This can be retrieved using // [Cmix.GetID]. -// - name - The name of the new channel. The name cannot be longer than __ -// characters and must contain only _____ characters. It cannot be changed +// - name - The name of the new channel. The name must be between 3 and 24 +// characters inclusive. It can only include upper and lowercase unicode +// letters, digits 0 through 9, and underscores (_). It cannot be changed // once a channel is created. -// - description - The description of a channel. The description cannot be -// longer than __ characters and must contain only _____ characters. It -// cannot be changed once a channel is created. +// - description - The description of a channel. The description is optional +// but cannot be longer than 144 characters and can include all unicode +// characters. It cannot be changed once a channel is created. +// - privacyLevel - The broadcast.PrivacyLevel of the channel. 0 = public, +// 1 = private, and 2 = secret. Refer to the comment below for more +// information. // // Returns: -// - []byte - ChannelGeneration describes a generated channel. It contains both -// the public channel info and the private key for the channel in PEM format. -// fixme: document json -func GenerateChannel(cmixID int, name, description string) ([]byte, error) { +// - []byte - [ChannelGeneration] describes a generated channel. It contains +// both the public channel info and the private key for the channel in PEM +// format. +// +// The [broadcast.PrivacyLevel] of a channel indicates the level of channel +// information revealed when sharing it via URL. For any channel besides public +// channels, the secret information is encrypted and a password is required to +// share and join a channel. +// - A privacy level of [broadcast.Public] reveals all the information +// including the name, description, privacy level, public key and salt. +// - A privacy level of [broadcast.Private] reveals only the name and +// description. +// - A privacy level of [broadcast.Secret] reveals nothing. +func GenerateChannel(cmixID int, name, description string, privacyLevel int) ([]byte, error) { // Get cmix from singleton so its rng can be used cmix, err := cmixTrackerSingleton.get(cmixID) if err != nil { @@ -367,8 +387,9 @@ func GenerateChannel(cmixID int, name, description string) ([]byte, error) { stream := cmix.api.GetRng().GetStream() defer stream.Close() - c, pk, err := cryptoBroadcast.NewChannel( - name, description, cmix.api.GetCmix().GetMaxMessageLength(), stream) + level := cryptoBroadcast.PrivacyLevel(privacyLevel) + c, pk, err := cryptoBroadcast.NewChannel(name, description, level, + cmix.api.GetCmix().GetMaxMessageLength(), stream) if err != nil { return nil, err } @@ -415,6 +436,14 @@ func makeChannelPrivateKeyStoreKey(channelID *id.ID) string { return channelPrivateKeyStoreKey + "/" + channelID.String() } +// ChannelInfo contains information about a channel. +// +// Example of ChannelInfo JSON: +// { +// "Name": "Test Channel", +// "Description": "This is a test channel", +// "ChannelID": "RRnpRhmvXtW9ugS1nILJ3WfttdctDvC2jeuH43E0g/0D", +// } type ChannelInfo struct { Name string Description string @@ -427,11 +456,10 @@ type ChannelInfo struct { // - prettyPrint - The pretty print of the channel. // // The pretty print will be of the format: -// <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=> +// <Speakeasy-v1:Test Channel,description:This is a test channel,secrets:YxHhRAKy2D4XU2oW5xnW/3yaqOeh8nO+ZSd3nUmiQ3c=,6pXN2H9FXcOj7pjJIZoq6nMi4tGX2s53fWH5ze2dU1g=,493,1,MVjkHlm0JuPxQNAn6WHsPdOw9M/BUF39p7XB/QEkQyc=> // // Returns: -// - []byte - ChannelInfo describes all relevant channel info. -// fixme: document json +// - []byte - JSON of [ChannelInfo], which describes all relevant channel info. func GetChannelInfo(prettyPrint string) ([]byte, error) { _, bytes, err := getChannelInfo(prettyPrint) return bytes, err @@ -462,11 +490,10 @@ func getChannelInfo(prettyPrint string) (*cryptoBroadcast.Channel, []byte, error // another user or generated via GenerateChannel. // // The pretty print will be of the format: -// <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=>" +// <Speakeasy-v1:Test Channel,description:This is a test channel,secrets:YxHhRAKy2D4XU2oW5xnW/3yaqOeh8nO+ZSd3nUmiQ3c=,6pXN2H9FXcOj7pjJIZoq6nMi4tGX2s53fWH5ze2dU1g=,493,1,MVjkHlm0JuPxQNAn6WHsPdOw9M/BUF39p7XB/QEkQyc=> // // Returns: -// - []byte - ChannelInfo describes all relevant channel info. -// fixme: document json +// - []byte - JSON of [ChannelInfo], which describes all relevant channel info. func (cm *ChannelsManager) JoinChannel(channelPretty string) ([]byte, error) { c, info, err := getChannelInfo(channelPretty) if err != nil { @@ -479,6 +506,40 @@ func (cm *ChannelsManager) JoinChannel(channelPretty string) ([]byte, error) { return info, err } +// JoinChannelFromURL joins the given channel from a URL. It will fail if the +// channel has already been joined. A password is required unless it is of the +// privacy level [broadcast.Public], in which case it can be left empty. To get +// the privacy level of a channel URL, use [GetShareUrlType]. +// +// Parameters: +// - url - The channel's share URL. Should be received from another user or +// generated via [GetShareURL]. +// - password - The password needed to decrypt the secret data in the URL. Only +// required for private or secret channels. +// +// Returns: +// - []byte - [ChannelInfo] describes all relevant channel info. +func (cm *ChannelsManager) JoinChannelFromURL(url, password string) ([]byte, error) { + c, err := cryptoBroadcast.DecodeShareURL(url, password) + if err != nil { + return nil, err + } + + info, err := json.Marshal(&ChannelInfo{ + Name: c.Name, + Description: c.Description, + ChannelID: c.ReceptionID.String(), + }) + if err != nil { + return nil, err + } + + // Join the channel using the API + err = cm.api.JoinChannel(c) + + return info, err +} + // GetChannels returns the IDs of all channels that have been joined. // // Returns: @@ -527,6 +588,116 @@ func (cm *ChannelsManager) ReplayChannel(marshalledChanId []byte) error { return cm.api.ReplayChannel(chanId) } +//////////////////////////////////////////////////////////////////////////////// +// Channel Share URL // +//////////////////////////////////////////////////////////////////////////////// + +// ShareURL is returned from ChannelsManager.GetShareURL. It includes the +// channel's share URL and password, if it needs one. +// +// JSON example for a public channel: +// { +// "url": "https://internet.speakeasy.tech/?0Name=My_Channel&Description=Here+is+information+about+my+channel.&2Level=Public&e=3CCvzK8diF%2B6vUZetyZkcyemoiI8uFLGSh%2B%2F9%2Bh5YQE%3D&k=zBakjn1Snay7AMr2CZ%2BCoWCHbe9TrtQqAVftIDi9Fjs%3D&l=5&m=0&p=1&s=Seyvx%2F5%2FOVTj5LClUG42AuLamDnqrbtMOoLymyIpFqY%3D&v=0", +// "password": "" +// } +// +// JSON example for a private channel: +// { +// "url": "https://internet.speakeasy.tech/?0Name=My_Channel&1Description=Here+is+information+about+my+channel.&d=i%2FwBAK6i89YT3LjPYb5%2BMmog5Gjk2unYzYt25y%2BmZH3%2Bo08oUIHHEoC7JYjk50Q2%2BMcSj6fQh%2BW3LBvWv02f1g60PLXZ1H8OS2rqoxBhwHvTpNgXRdUIErbk6q3ljIdjtSqJtWIzAx5no%2F96jaIBsob0U9jDE1jgsU8XNGxDz3TeKcdTOFiUpnh4R%2BALcys%3D&m=1&v=0", +// "password": "easter boaster musket catalyze unproven vendetta plated grinning" +// } +// +// JSON example for a secret channel: +// { +// "url": "https://internet.speakeasy.tech/?d=xRORDN8lt%2BI2SAn%2F21ZpOzj50J3HOV1GkMsPkhtgoYyQUqpPBZhhKpewzuDI%2B3wTQlpANLDMtFVL4J7y2lBpvIz9LQ5%2F6CoRdVkoXbG7uRqv6wscYdwWPYZBARC2cJSyeVad6RbxnoZ65Z0dtEVEff328ri3ZpaMBlP%2BpUH928pcVHibALW7Bw04Rkmh%2FWx6wJGw%2FU0gTHo02UlYFHh4G9CC%2BIU1x13BmEuW6Hyk6Ty9BlHt29QbsQ7uU30RwzQOyg8%3D&m=2&v=0", +// "password": "florist angled valid snarl discharge endearing harbor hazy" +// } +type ShareURL struct { + URL string `json:"url"` + Password string `json:"password"` +} + +// GetShareURL generates a URL that can be used to share this channel with +// others on the given host. +// +// A URL comes in one of three forms based on the privacy level set when +// generating the channel. Each privacy level hides more information than the +// last with the lowest level revealing everything and the highest level +// revealing nothing. For any level above the lowest, a password is returned, +// which will be required when decoding the URL. +// +// The maxUses is the maximum number of times this URL can be used to join a +// channel. If it is set to 0, then it can be shared unlimited times. The max +// uses is set as a URL parameter using the key [broadcast.MaxUsesKey]. Note +// that this number is also encoded in the secret data for private and secret +// URLs, so if the number is changed in the URL, is will be verified when +// calling [ChannelsManager.JoinChannelFromURL]. There is no enforcement for +// public URLs. +// +// Parameters: +// - cmixID - The tracked Cmix object ID. +// - host - The URL to append the channel info to. +// - maxUses - The maximum number of uses the link can be used (0 for +// unlimited). +// - marshalledChanId - A marshalled channel ID ([id.ID]). +// +// Returns: +// - JSON of ShareURL. +func (cm *ChannelsManager) GetShareURL(cmixID int, host string, maxUses int, + marshalledChanId []byte) ([]byte, error) { + + // Unmarshal channel ID + chanId, err := id.Unmarshal(marshalledChanId) + if err != nil { + return nil, err + } + + // Get the channel from the ID + ch, err := cm.api.GetChannel(chanId) + if err != nil { + return nil, err + } + + // Get user from singleton + user, err := cmixTrackerSingleton.get(cmixID) + if err != nil { + return nil, err + } + + // Generate share URL and password + rng := user.api.GetRng().GetStream() + url, password, err := ch.ShareURL(host, maxUses, rng) + rng.Close() + if err != nil { + return nil, err + } + + su := ShareURL{ + URL: url, + Password: password, + } + + return json.Marshal(su) +} + +// GetShareUrlType determines the [broadcast.PrivacyLevel] of the channel URL. +// If the URL is an invalid channel URL, an error is returned. +// +// Parameters: +// - url - The channel share URL. +// +// Returns: +// - An int that corresponds to the [broadcast.PrivacyLevel] as outlined below. +// +// Possible returns: +// 0 = public channel +// 1 = private channel +// 2 = secret channel +func GetShareUrlType(url string) (int, error) { + level, err := cryptoBroadcast.GetShareUrlType(url) + return int(level), err +} + //////////////////////////////////////////////////////////////////////////////// // Channel Sending Methods & Reports // //////////////////////////////////////////////////////////////////////////////// diff --git a/broadcast/rsaToPublic_test.go b/broadcast/rsaToPublic_test.go index 159f9d1016ead09866c8db1bd3f15faedfc94404..9be17453b96db68ca8a735fdcd9234ccd7ad2e3e 100644 --- a/broadcast/rsaToPublic_test.go +++ b/broadcast/rsaToPublic_test.go @@ -59,7 +59,7 @@ func Test_asymmetricClient_Smoke(t *testing.T) { packetPayloadLength := newMockCmix(cMixHandler).GetMaxMessageLength() channel, pk, _ := crypto.NewChannel( - cName, cDesc, packetPayloadLength, rngGen.GetStream()) + cName, cDesc, crypto.Public, packetPayloadLength, rngGen.GetStream()) cid := channel.ReceptionID // Must mutate cMixHandler such that it's processorMap contains a diff --git a/channels/joinedChannel_test.go b/channels/joinedChannel_test.go index e3bee24de606711cc0a0cffcd24e6a6c9b42001d..f020561e040861e540bac72810a4849087d65a0e 100644 --- a/channels/joinedChannel_test.go +++ b/channels/joinedChannel_test.go @@ -51,8 +51,9 @@ func Test_manager_store(t *testing.T) { m := mFace.(*manager) for i := 0; i < 10; i++ { - ch, _, err := newTestChannel("name_"+strconv.Itoa(i), - "description_"+strconv.Itoa(i), m.rng.GetStream()) + ch, _, err := newTestChannel( + "name_"+strconv.Itoa(i), "description_"+strconv.Itoa(i), + m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel %d: %+v", i, err) } @@ -99,8 +100,8 @@ func Test_manager_loadChannels(t *testing.T) { expected := make([]*joinedChannel, 10) for i := range expected { - ch, _, err := newTestChannel("name_"+strconv.Itoa(i), - "description_"+strconv.Itoa(i), m.rng.GetStream()) + ch, _, err := newTestChannel( + "name_"+strconv.Itoa(i), "description_"+strconv.Itoa(i), m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel %d: %+v", i, err) } @@ -168,7 +169,8 @@ func Test_manager_addChannel(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -213,7 +215,8 @@ func Test_manager_addChannel_ChannelAlreadyExistsErr(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -249,7 +252,8 @@ func Test_manager_removeChannel(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -294,7 +298,8 @@ func Test_manager_removeChannel_ChannelDoesNotExistsErr(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -326,7 +331,8 @@ func Test_manager_getChannel(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -367,7 +373,8 @@ func Test_manager_getChannel_ChannelDoesNotExistsErr(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -403,8 +410,8 @@ func Test_manager_getChannels(t *testing.T) { expected := make([]*id.ID, 10) for i := range expected { - ch, _, err := newTestChannel("name_"+strconv.Itoa(i), - "description_"+strconv.Itoa(i), m.rng.GetStream()) + ch, _, err := newTestChannel( + "name_"+strconv.Itoa(i), "description_"+strconv.Itoa(i), m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel %d: %+v", i, err) } @@ -436,7 +443,8 @@ func Test_manager_getChannels(t *testing.T) { func Test_joinedChannel_Store(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) - ch, _, err := newTestChannel("name", "description", rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -479,7 +487,8 @@ func Test_loadJoinedChannel(t *testing.T) { m := mFace.(*manager) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -508,7 +517,8 @@ func Test_loadJoinedChannel(t *testing.T) { func Test_joinedChannel_delete(t *testing.T) { kv := versioned.NewKV(ekv.MakeMemstore()) rng := fastRNG.NewStreamGenerator(1, 1, csprng.NewSystemRNG) - ch, _, err := newTestChannel("name", "description", rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", rng.GetStream(), cryptoBroadcast.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -565,9 +575,11 @@ func Test_makeJoinedChannelKey_Consistency(t *testing.T) { // newTestChannel creates a new cryptoBroadcast.Channel in the same way that // cryptoBroadcast.NewChannel does but with a smaller RSA key and salt to make // tests run quicker. -func newTestChannel(name, description string, rng csprng.Source) ( +func newTestChannel(name, description string, rng csprng.Source, + level cryptoBroadcast.PrivacyLevel) ( *cryptoBroadcast.Channel, rsa.PrivateKey, error) { - c, pk, err := cryptoBroadcast.NewChannelVariableKeyUnsafe(name, description, 1000, 512, rng) + c, pk, err := cryptoBroadcast.NewChannelVariableKeyUnsafe( + name, description, level, 1000, 512, rng) return c, pk, err } diff --git a/channels/manager_test.go b/channels/manager_test.go index 6f07e2013d222e10d8c93bce7beeabbfd59ef8b1..e4213bd7c369143fec41c60895150bf79e0ea3a6 100644 --- a/channels/manager_test.go +++ b/channels/manager_test.go @@ -11,6 +11,7 @@ import ( "fmt" "gitlab.com/elixxir/client/broadcast" "gitlab.com/elixxir/client/storage/versioned" + broadcast2 "gitlab.com/elixxir/crypto/broadcast" cryptoChannel "gitlab.com/elixxir/crypto/channel" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/elixxir/ekv" @@ -51,7 +52,8 @@ func TestManager_JoinChannel(t *testing.T) { m := mFace.(*manager) mem := m.events.model.(*mockEventModel) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), broadcast2.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -94,7 +96,8 @@ func TestManager_LeaveChannel(t *testing.T) { m := mFace.(*manager) mem := m.events.model.(*mockEventModel) - ch, _, err := newTestChannel("name", "description", m.rng.GetStream()) + ch, _, err := newTestChannel( + "name", "description", m.rng.GetStream(), broadcast2.Public) if err != nil { t.Errorf("Failed to create new channel: %+v", err) } @@ -135,9 +138,9 @@ func TestManager_GetChannels(t *testing.T) { chList := make(map[id.ID]interface{}) for i := 0; i < 10; i++ { - name := fmt.Sprintf("testChannel %d", numtests) + name := fmt.Sprintf("testChannel_%d", numtests) s := rng.GetStream() - tc, _, err := newTestChannel(name, "blarg", s) + tc, _, err := newTestChannel(name, "blarg", s, broadcast2.Public) s.Close() if err != nil { t.Fatalf("failed to generate channel %s", name) @@ -172,9 +175,9 @@ func TestManager_GetChannel(t *testing.T) { chList := make([]*id.ID, 0, numtests) for i := 0; i < 10; i++ { - name := fmt.Sprintf("testChannel %d", numtests) + name := fmt.Sprintf("testChannel_%d", numtests) s := rng.GetStream() - tc, _, err := newTestChannel(name, "blarg", s) + tc, _, err := newTestChannel(name, "blarg", s, broadcast2.Public) s.Close() if err != nil { t.Fatalf("failed to generate channel %s", name) diff --git a/channels/send_test.go b/channels/send_test.go index c3c8114c85d69193216c04bf903991f69129917e..6886519a42dbd95431dcb927ada369c46bb7c94a 100644 --- a/channels/send_test.go +++ b/channels/send_test.go @@ -272,8 +272,8 @@ func TestAdminGeneric(t *testing.T) { validUntil := time.Hour rng := &csprng.SystemRNG{} - ch, priv, err := cryptoBroadcast.NewChannel("test", "test", - 1000, rng) + ch, priv, err := cryptoBroadcast.NewChannel( + "test", "test", cryptoBroadcast.Public, 1000, rng) if err != nil { t.Fatalf("Failed to generate channel: %+v", err) } diff --git a/cmd/broadcast.go b/cmd/broadcast.go index 7b0e7c9183ae1311bf7f2478640309723ca824e4..df52c82f13ae29ae780670a9a502d68be86e2142 100644 --- a/cmd/broadcast.go +++ b/cmd/broadcast.go @@ -81,7 +81,8 @@ var broadcastCmd = &cobra.Command{ if viper.GetBool(broadcastNewFlag) { // Create a new broadcast channel - channel, pk, err = crypto.NewChannel(name, desc, user.GetCmix().GetMaxMessageLength(), user.GetRng().GetStream()) + channel, pk, err = crypto.NewChannel(name, desc, crypto.Public, + user.GetCmix().GetMaxMessageLength(), user.GetRng().GetStream()) if err != nil { jww.FATAL.Panicf("Failed to create new channel: %+v", err) } diff --git a/go.mod b/go.mod index cf73253e0921d1501752e9ce93529b4d314d1710..2d20fdda7f3c19fa52b1a216fb741aee99a11ee1 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/stretchr/testify v1.8.0 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f gitlab.com/elixxir/comms v0.0.4-0.20221011183106-8c4450ba3cfb - gitlab.com/elixxir/crypto v0.0.7-0.20221015023742-e1108df47b6b + gitlab.com/elixxir/crypto v0.0.7-0.20221014162002-64ef7c013cc9 gitlab.com/elixxir/ekv v0.2.1 gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 gitlab.com/xx_network/comms v0.0.4-0.20221005205845-b34d538ffd85 @@ -50,6 +50,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.8.2 // indirect + github.com/sethvargo/go-diceware v0.3.0 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/afero v1.9.2 // indirect diff --git a/go.sum b/go.sum index a7a1300530c0d37858b4f22a65cc05b9ac20ef22..9c400a6eed19a70c3b8cb50e12ee6d05adb954d4 100644 --- a/go.sum +++ b/go.sum @@ -547,6 +547,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sethvargo/go-diceware v0.3.0 h1:UVVEfmN/uF50JfWAN7nbY6CiAlp5xeSx+5U0lWKkMCQ= +github.com/sethvargo/go-diceware v0.3.0/go.mod h1:lH5Q/oSPMivseNdhMERAC7Ti5oOPqsaVddU1BcN1CY0= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -634,10 +636,8 @@ gitlab.com/elixxir/comms v0.0.4-0.20221011183106-8c4450ba3cfb/go.mod h1:oRteMH+R gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= gitlab.com/elixxir/crypto v0.0.7-0.20220913220142-ab0771bad0af/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= -gitlab.com/elixxir/crypto v0.0.7-0.20221014161526-ce04e14b9f80 h1:M9imzr2ZrD0GXsR+nfrzLnJ8Y9axj2Pvq8CTDE+IQb4= -gitlab.com/elixxir/crypto v0.0.7-0.20221014161526-ce04e14b9f80/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= -gitlab.com/elixxir/crypto v0.0.7-0.20221015023742-e1108df47b6b h1:gWB95fteva1kMYR/qzdkxMMAs771wIvYd97D9nPy/xI= -gitlab.com/elixxir/crypto v0.0.7-0.20221015023742-e1108df47b6b/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= +gitlab.com/elixxir/crypto v0.0.7-0.20221014162002-64ef7c013cc9 h1:T5zUNYXFtV9Cr/P5fUx1B4lkRi+c2qL0Esgp1/Zpd58= +gitlab.com/elixxir/crypto v0.0.7-0.20221014162002-64ef7c013cc9/go.mod h1:IU//ZTbPrqnaUrPKP9l9cD29c+cJPo3E1yrlbcBaf2w= gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is= gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=