From 5cfc066ee23c78e598aa64dd414a9e9dee44e092 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Fri, 19 Aug 2022 13:42:16 -0700
Subject: [PATCH 01/11] Add validateUsername endpoint to UD

---
 cmd/root.go                 | 14 ++++++--
 go.mod                      |  7 ++--
 go.sum                      | 21 +++++++++++
 io/factRegistration.go      |  2 +-
 io/manager.go               | 19 ++++++++--
 io/manager_test.go          |  2 +-
 io/validateUsername.go      | 65 +++++++++++++++++++++++++++++++++
 io/validateUsername_test.go | 71 +++++++++++++++++++++++++++++++++++++
 8 files changed, 192 insertions(+), 9 deletions(-)
 create mode 100644 io/validateUsername.go
 create mode 100644 io/validateUsername_test.go

diff --git a/cmd/root.go b/cmd/root.go
index 17789be..72251d7 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -9,12 +9,15 @@ import (
 	"gitlab.com/elixxir/client/storage/user"
 	"gitlab.com/elixxir/client/xxdk"
 	"gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/elixxir/user-discovery-bot/banned"
 	"gitlab.com/elixxir/user-discovery-bot/cmix"
 	"gitlab.com/elixxir/user-discovery-bot/io"
 	"gitlab.com/elixxir/user-discovery-bot/storage"
 	"gitlab.com/elixxir/user-discovery-bot/twilio"
 	"gitlab.com/xx_network/comms/connect"
+	"gitlab.com/xx_network/crypto/csprng"
+	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/crypto/tls"
 	"gitlab.com/xx_network/primitives/id"
 	"gitlab.com/xx_network/primitives/ndf"
@@ -61,6 +64,11 @@ var rootCmd = &cobra.Command{
 			twilioManager = twilio.NewManager(p.Twilio, storage)
 		}
 
+		privKey, err := rsa.LoadPrivateKeyFromPem(p.Key)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to load RSA private key: %v", err)
+		}
+
 		cert, err := tls.LoadCertificate(string(p.PermCert))
 		if err != nil {
 			jww.FATAL.Fatalf("Failed to load permissioning cert to pem: %+v", err)
@@ -74,9 +82,11 @@ var rootCmd = &cobra.Command{
 
 		jww.WARN.Printf("Skipping scheduling signature verification set to %v ", viper.GetBool("skipVerification"))
 
+		rngStreamGen := fastRNG.NewStreamGenerator(12, 1024, csprng.NewSystemRNG)
+
 		// Set up manager with the ability to contact permissioning
-		manager := io.NewManager(p.IO, &id.UDB, permCert, twilioManager,
-			bannedManager, storage, viper.GetBool("skipVerification"))
+		manager := io.NewManager(p.IO, &id.UDB, privKey, permCert, twilioManager,
+			bannedManager, storage, rngStreamGen, viper.GetBool("skipVerification"))
 		hostParams := connect.GetDefaultHostParams()
 		hostParams.AuthEnabled = false
 		permHost, err := manager.Comms.AddHost(&id.Permissioning,
diff --git a/go.mod b/go.mod
index 1f72b4b..84a676e 100644
--- a/go.mod
+++ b/go.mod
@@ -10,8 +10,8 @@ require (
 	github.com/spf13/viper v1.11.0
 	github.com/ttacon/libphonenumber v1.2.1
 	gitlab.com/elixxir/client v1.5.1-0.20220725172207-3ef87e8c794c
-	gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326
-	gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea
+	gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4
+	gitlab.com/elixxir/crypto v0.0.7-0.20220818194137-973a70947df4
 	gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f
 	gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd
 	gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81
@@ -42,6 +42,7 @@ require (
 	github.com/magiconair/properties v1.8.6 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/multiformats/go-multihash v0.2.1 // indirect
 	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
 	github.com/pelletier/go-toml v1.9.4 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect
@@ -57,7 +58,7 @@ require (
 	gitlab.com/elixxir/ekv v0.1.7 // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	go.uber.org/ratelimit v0.2.0 // indirect
-	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
+	golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
 	golang.org/x/net v0.0.0-20220420153159-1850ba15e1be // indirect
 	golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
 	golang.org/x/text v0.3.7 // indirect
diff --git a/go.sum b/go.sum
index ce9bd87..5e00f72 100644
--- a/go.sum
+++ b/go.sum
@@ -343,6 +343,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -385,6 +387,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
 github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
+github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -404,6 +407,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
+github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
+github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
@@ -470,6 +477,7 @@ github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUr
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
 github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
@@ -550,11 +558,21 @@ gitlab.com/elixxir/client v1.5.1-0.20220725172207-3ef87e8c794c h1:7HQy9zhD1O8Xh/
 gitlab.com/elixxir/client v1.5.1-0.20220725172207-3ef87e8c794c/go.mod h1:dRCeFJrIj5zuxSfcnsAYOCodyPrKVparJUREBIWKRcw=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 h1:Zid8oNHtbOqF6ebrcGIccvIMabFNGh9dzY1b7mgIcF0=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
+gitlab.com/elixxir/comms v0.0.4-0.20220819171953-093a8c76fe23 h1:4Se+dRpcOBpDj4QNvJy3qpLVAMk2GJcgf8aMdbN/67U=
+gitlab.com/elixxir/comms v0.0.4-0.20220819171953-093a8c76fe23/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
+gitlab.com/elixxir/comms v0.0.4-0.20220819173923-2f9c1fb232aa h1:yYHUkGaafdIEcP/TUkhIi4Kh9/8yOGxPCKOse7FBg9Y=
+gitlab.com/elixxir/comms v0.0.4-0.20220819173923-2f9c1fb232aa/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
+gitlab.com/elixxir/comms v0.0.4-0.20220819183658-b42c691e54e4 h1:SQ+RGR8mPBlef8G0hp0Z5RsqWjRhtTYEGhL+EcurIFw=
+gitlab.com/elixxir/comms v0.0.4-0.20220819183658-b42c691e54e4/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
+gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4 h1:CgI8Xb9lXxeJaMs88cksR2wc30WBR6BVlq2alY1QklY=
+gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
 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.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10=
 gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea h1:+FjwbKl6X9TDT7qd7gG5N5PSbziPWP3NgjK5ci1b7/8=
 gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea/go.mod h1:Oy+VWQ2Sa0Ybata3oTV+Yc46hkaDwAsuIMW0wJ01z2M=
+gitlab.com/elixxir/crypto v0.0.7-0.20220818194137-973a70947df4 h1:vM8o0qogeCuTwkupzmSBSO4kyEMtOJ5hWPrxgRb3CnU=
+gitlab.com/elixxir/crypto v0.0.7-0.20220818194137-973a70947df4/go.mod h1:0gH41Kb/a9Akdv+2+vMJVdx+REVwR8CZXTr2+BrgeeA=
 gitlab.com/elixxir/ekv v0.1.7 h1:OW2z+N4QCqqMFzouAwFTWWMKz0Y/PDhyYReN7gQ5NiQ=
 gitlab.com/elixxir/ekv v0.1.7/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
@@ -641,6 +659,8 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y
 golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1130,6 +1150,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/io/factRegistration.go b/io/factRegistration.go
index 36eddba..8a204d0 100644
--- a/io/factRegistration.go
+++ b/io/factRegistration.go
@@ -13,7 +13,7 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
-var (
+const (
 	invalidFactRegisterRequestError = "Unable to parse required fields in FactRegisterRequest."
 	factExistsError                 = "Cannot register fact that already exists."
 	noUserError                     = "User associated with fact not registered: %s"
diff --git a/io/manager.go b/io/manager.go
index 7fcbbdc..502e935 100644
--- a/io/manager.go
+++ b/io/manager.go
@@ -13,6 +13,7 @@ import (
 	"fmt"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/comms/udb"
+	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/elixxir/user-discovery-bot/banned"
 	"gitlab.com/elixxir/user-discovery-bot/interfaces/params"
 	"gitlab.com/elixxir/user-discovery-bot/storage"
@@ -25,24 +26,32 @@ import (
 // Manager is the main UserDiscovery instance object.
 type Manager struct {
 	Comms                  *udb.Comms
+	rng                    *fastRNG.StreamGenerator
 	PermissioningPublicKey *rsa.PublicKey
 	Storage                *storage.Storage
 	Twilio                 *twilio.Manager
 	Banned                 *banned.Manager
+	rsaPrivateKey          *rsa.PrivateKey
 	skipVerification       bool
 }
 
 // NewManager creates a new UserDiscovery Manager given a set of Params.
-func NewManager(p params.IO, id *id.ID, permissioningCert *rsa.PublicKey,
+func NewManager(p params.IO, id *id.ID, rsaPrivateKey *rsa.PrivateKey,
+	permissioningCert *rsa.PublicKey,
 	twilio *twilio.Manager, banned *banned.Manager,
-	storage *storage.Storage, skipVerification bool) *Manager {
+	storage *storage.Storage, rng *fastRNG.StreamGenerator,
+	skipVerification bool) *Manager {
+
 	m := &Manager{
 		Storage:                storage,
 		PermissioningPublicKey: permissioningCert,
 		Twilio:                 twilio,
 		Banned:                 banned,
 		skipVerification:       skipVerification,
+		rsaPrivateKey:          rsaPrivateKey,
+		rng:                    rng,
 	}
+
 	m.Comms = udb.StartServer(id, fmt.Sprintf("0.0.0.0:%s", p.Port),
 		newImplementation(m), p.Cert, p.Key)
 	return m
@@ -74,5 +83,11 @@ func newImplementation(m *Manager) *udb.Implementation {
 		return removeFact(msg, m.Storage)
 	}
 
+	impl.Functions.ValidateUsername = func(request *pb.UsernameValidationRequest) (*pb.UsernameValidation, error) {
+		stream := m.rng.GetStream()
+		defer stream.Close()
+		return validateUsername(request, m.Storage, m.rsaPrivateKey, stream)
+	}
+
 	return impl
 }
diff --git a/io/manager_test.go b/io/manager_test.go
index 7e00a6d..8f20c46 100644
--- a/io/manager_test.go
+++ b/io/manager_test.go
@@ -23,7 +23,7 @@ func TestNewManager(t *testing.T) {
 		t.Fatalf("Failed to construct ban manager: %v", err)
 	}
 
-	m := NewManager(p, id.NewIdFromString("zezima", id.User, t), nil, tm, bannedManager, store, false)
+	m := NewManager(p, id.NewIdFromString("zezima", id.User, t), nil, nil, tm, bannedManager, store, nil, false)
 	if m == nil || reflect.TypeOf(m) != reflect.TypeOf(&Manager{}) {
 		t.Errorf("Did not receive a manager")
 	}
diff --git a/io/validateUsername.go b/io/validateUsername.go
new file mode 100644
index 0000000..1a05461
--- /dev/null
+++ b/io/validateUsername.go
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package io
+
+import (
+	"github.com/pkg/errors"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/partnerships/crust"
+	"gitlab.com/elixxir/user-discovery-bot/storage"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"io"
+)
+
+const (
+	usernameNotAssociatedWithUser = "username %s is not associated with user ID %s"
+)
+
+// ValidateUsername validates that a user owns a username by signing the contents of the
+// mixmessages.UsernameValidationRequest.
+func validateUsername(request *pb.UsernameValidationRequest,
+	store *storage.Storage, privKey *rsa.PrivateKey, rng io.Reader) (*pb.UsernameValidation, error) {
+	// Return an error if the request is invalid
+	if request == nil || request.Username == "" || request.ReceptionPublicKeyPem == nil {
+		return &pb.UsernameValidation{}, errors.New("Unable to parse required " +
+			"fields in registration message")
+	}
+
+	// Marshal user ID
+	userID, err := id.Unmarshal(request.UserId)
+	if err != nil {
+		return &pb.UsernameValidation{}, errors.WithMessage(err, invalidUserIdError)
+	}
+
+	// Return an error if the user is not registered
+	user, err := store.GetUser(request.UserId)
+	if err != nil {
+		return &pb.UsernameValidation{}, errors.WithMessage(err, getUserFailureError)
+	} else if user == nil {
+		return &pb.UsernameValidation{}, errors.Errorf(noUserError,
+			userID)
+	}
+
+	// Check that the username in storage matches the username in the request message
+	// before validating
+	if user.Username != request.Username {
+		return &pb.UsernameValidation{}, errors.Errorf(usernameNotAssociatedWithUser,
+			request.Username, userID)
+	}
+
+	// Create a signature verifying the user owns their username
+	verificationSignature, err := crust.SignVerification(rng, privKey,
+		request.Username, request.ReceptionPublicKeyPem)
+	if err != nil {
+		return nil, errors.Errorf("Failed to create verification signature: %v", err)
+	}
+
+	// Return signature to user
+	return &pb.UsernameValidation{Signature: verificationSignature}, nil
+}
diff --git a/io/validateUsername_test.go b/io/validateUsername_test.go
new file mode 100644
index 0000000..6e6aea5
--- /dev/null
+++ b/io/validateUsername_test.go
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright © 2020 xx network SEZC                                          //
+//                                                                           //
+// Use of this source code is governed by a license that can be found in the //
+// LICENSE file                                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+package io
+
+import (
+	"crypto/rand"
+	pb "gitlab.com/elixxir/comms/mixmessages"
+	"gitlab.com/elixxir/crypto/partnerships/crust"
+	"gitlab.com/elixxir/user-discovery-bot/banned"
+	"gitlab.com/elixxir/user-discovery-bot/storage"
+	"gitlab.com/xx_network/primitives/ndf"
+	"testing"
+	"time"
+)
+
+func TestValidateUsername(t *testing.T) {
+	// Initialize fields needed for testing
+	clientId, rsaPrivKey := initClientFields(t)
+	store := storage.NewTestDB(t)
+	ndfObj, _ := ndf.Unmarshal(getNDF())
+	cert, err := loadPermissioningPubKey(ndfObj.Registration.TlsCertificate)
+	if err != nil {
+		t.Errorf(err.Error())
+	}
+
+	// Register user first -------------------------------------------------------------------------
+	testTime, err := time.Parse(time.RFC3339,
+		"2012-12-21T22:08:41+00:00")
+	if err != nil {
+		t.Fatalf("Could not parse precanned time: %v", err.Error())
+	}
+	registerMsg, err := buildUserRegistrationMessage(clientId, rsaPrivKey, testTime, t)
+	if err != nil {
+		t.Fatalf("Failed to build registration message: %+v", err)
+	}
+
+	bannedManager, err := banned.NewManager("", "")
+	if err != nil {
+		t.Fatalf("Failed to construct ban manager: %v", err)
+	}
+
+	_, err = registerUser(registerMsg, cert, store, bannedManager, false)
+	if err != nil {
+		t.Errorf("Failed happy path: %v", err)
+	}
+
+	// Test Validate username ----------------------------------------------------------------------
+	username := registerMsg.Frs.Fact.Fact
+	pubKeyPem := []byte(registerMsg.RSAPublicPem)
+	validationRequest := &pb.UsernameValidationRequest{
+		Username:              username,
+		ReceptionPublicKeyPem: pubKeyPem,
+		UserId:                registerMsg.UID,
+	}
+	
+	validationResponse, err := validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
+	if err != nil {
+		t.Fatalf("Failed to validate username: %+v", err)
+	}
+
+	err = crust.VerifyVerificationSignature(rsaPrivKey.GetPublic(), username, pubKeyPem, validationResponse.Signature)
+	if err != nil {
+		t.Fatalf("validateUsername did not return a valid signature!")
+	}
+
+}
-- 
GitLab


From c7cf597b029084ed22ee358b7f99147aa6a1f41b Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Fri, 19 Aug 2022 15:54:22 -0700
Subject: [PATCH 02/11] Fix pipeline

---
 go.mod                      |  6 ++---
 go.sum                      |  6 +++++
 io/validateUsername_test.go | 54 +++++++++++++++++++++++++++++++++++--
 3 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/go.mod b/go.mod
index 84a676e..3a680e1 100644
--- a/go.mod
+++ b/go.mod
@@ -10,11 +10,11 @@ require (
 	github.com/spf13/viper v1.11.0
 	github.com/ttacon/libphonenumber v1.2.1
 	gitlab.com/elixxir/client v1.5.1-0.20220725172207-3ef87e8c794c
-	gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4
+	gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1
 	gitlab.com/elixxir/crypto v0.0.7-0.20220818194137-973a70947df4
-	gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f
+	gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326
 	gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd
-	gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81
+	gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e
 	gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e
 	gorm.io/driver/postgres v1.1.2
 	gorm.io/gorm v1.21.15
diff --git a/go.sum b/go.sum
index 5e00f72..efc91ec 100644
--- a/go.sum
+++ b/go.sum
@@ -566,6 +566,8 @@ gitlab.com/elixxir/comms v0.0.4-0.20220819183658-b42c691e54e4 h1:SQ+RGR8mPBlef8G
 gitlab.com/elixxir/comms v0.0.4-0.20220819183658-b42c691e54e4/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
 gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4 h1:CgI8Xb9lXxeJaMs88cksR2wc30WBR6BVlq2alY1QklY=
 gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
+gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1 h1:KZ8wKOenvQaYNKo+4jdVhy3YJ7Xa3obiPxGziGJWUb4=
+gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
 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.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10=
@@ -583,6 +585,8 @@ gitlab.com/elixxir/primitives v0.0.3-0.20220222212109-d412a6e46623/go.mod h1:MtF
 gitlab.com/elixxir/primitives v0.0.3-0.20220323183834-b98f255361b8/go.mod h1:MtFIyJUQn9P7djzVlBpEYkPNnnWFTjZvw89swoXY+QM=
 gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f h1:CTf2+ewHWYrzp5Ar3RwNvHePfTHyFniJTVjFW4zqoaE=
 gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA=
+gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326 h1:NrgEawIlebJXvIJXvw0wJOGMfOogb1HlcqbpucYteJY=
+gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA=
 gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
 gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac h1:+ykw0JqLH/qMprPEKazGHNH8gUoHGA78EIr4ienxnw4=
 gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac/go.mod h1:isHnwem0v4rTcwwHP455FhVlFyPcHkHiVz+N3s/uCSI=
@@ -594,6 +598,8 @@ gitlab.com/xx_network/crypto v0.0.5-0.20220222212031-750f7e8a01f4/go.mod h1:6apv
 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.20220606200528-3f886fe49e81 h1:9HK48ZEGFKLm3HBcE/FdQitllJRYPPS0zeaiRL+MBhI=
 gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81/go.mod h1:/SJf+R75E+QepdTLh0H1/udsovxx2Q5ru34q1v0umKk=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e h1:k+M0zo9eyL2mGaduggdQnwxzOIqOIBV9WIt1QCq92sA=
+gitlab.com/xx_network/crypto v0.0.5-0.20220729193517-1e5e96f39f6e/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/io/validateUsername_test.go b/io/validateUsername_test.go
index 6e6aea5..afae5f9 100644
--- a/io/validateUsername_test.go
+++ b/io/validateUsername_test.go
@@ -18,6 +18,7 @@ import (
 	"time"
 )
 
+// Happy path.
 func TestValidateUsername(t *testing.T) {
 	// Initialize fields needed for testing
 	clientId, rsaPrivKey := initClientFields(t)
@@ -57,15 +58,64 @@ func TestValidateUsername(t *testing.T) {
 		ReceptionPublicKeyPem: pubKeyPem,
 		UserId:                registerMsg.UID,
 	}
-	
+
 	validationResponse, err := validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
 	if err != nil {
 		t.Fatalf("Failed to validate username: %+v", err)
 	}
 
-	err = crust.VerifyVerificationSignature(rsaPrivKey.GetPublic(), username, pubKeyPem, validationResponse.Signature)
+	err = crust.VerifyVerificationSignature(rsaPrivKey.GetPublic(),
+		username, pubKeyPem, validationResponse.Signature)
 	if err != nil {
 		t.Fatalf("validateUsername did not return a valid signature!")
 	}
 
 }
+
+// Error path: Try to validate a username that does not belong to the user.
+func TestValidateUsername_UsernameMismatch(t *testing.T) {
+	// Initialize fields needed for testing
+	clientId, rsaPrivKey := initClientFields(t)
+	store := storage.NewTestDB(t)
+	ndfObj, _ := ndf.Unmarshal(getNDF())
+	cert, err := loadPermissioningPubKey(ndfObj.Registration.TlsCertificate)
+	if err != nil {
+		t.Errorf(err.Error())
+	}
+
+	// Register user first -------------------------------------------------------------------------
+	testTime, err := time.Parse(time.RFC3339,
+		"2012-12-21T22:08:41+00:00")
+	if err != nil {
+		t.Fatalf("Could not parse precanned time: %v", err.Error())
+	}
+	registerMsg, err := buildUserRegistrationMessage(clientId, rsaPrivKey, testTime, t)
+	if err != nil {
+		t.Fatalf("Failed to build registration message: %+v", err)
+	}
+
+	bannedManager, err := banned.NewManager("", "")
+	if err != nil {
+		t.Fatalf("Failed to construct ban manager: %v", err)
+	}
+
+	_, err = registerUser(registerMsg, cert, store, bannedManager, false)
+	if err != nil {
+		t.Errorf("Failed happy path: %v", err)
+	}
+
+	// Test Validate username ----------------------------------------------------------------------
+	pubKeyPem := []byte(registerMsg.RSAPublicPem)
+	validationRequest := &pb.UsernameValidationRequest{
+		Username:              "admin",
+		ReceptionPublicKeyPem: pubKeyPem,
+		UserId:                registerMsg.UID,
+	}
+
+	// Send a validation request using a username that does not belong to this user
+	_, err = validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
+	if err != nil { // This should return an error
+		t.Fatalf("Failed to validate username: %+v", err)
+	}
+
+}
-- 
GitLab


From 7be649181ae6cd5c6ee4a46938c127c018a5d610 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Wed, 24 Aug 2022 15:22:46 -0700
Subject: [PATCH 03/11] Fix deps

---
 go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 3a680e1..675412a 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,6 @@ require (
 	github.com/spf13/viper v1.11.0
 	github.com/ttacon/libphonenumber v1.2.1
 	gitlab.com/elixxir/client v1.5.1-0.20220725172207-3ef87e8c794c
-	gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1
 	gitlab.com/elixxir/crypto v0.0.7-0.20220818194137-973a70947df4
 	gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326
 	gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd
@@ -55,6 +54,7 @@ require (
 	github.com/tyler-smith/go-bip39 v1.1.0 // indirect
 	github.com/zeebo/blake3 v0.1.1 // indirect
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
+	gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1 // indirect
 	gitlab.com/elixxir/ekv v0.1.7 // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	go.uber.org/ratelimit v0.2.0 // indirect
-- 
GitLab


From 186f9ab7f0ee931e3f9a288a0d8591ec51c5294b Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Wed, 24 Aug 2022 15:33:45 -0700
Subject: [PATCH 04/11] Fix test

---
 io/validateUsername_test.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/io/validateUsername_test.go b/io/validateUsername_test.go
index afae5f9..b8a466e 100644
--- a/io/validateUsername_test.go
+++ b/io/validateUsername_test.go
@@ -114,8 +114,8 @@ func TestValidateUsername_UsernameMismatch(t *testing.T) {
 
 	// Send a validation request using a username that does not belong to this user
 	_, err = validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
-	if err != nil { // This should return an error
-		t.Fatalf("Failed to validate username: %+v", err)
+	if err == nil { // This should return an error
+		t.Fatalf("Should not be able to validate username that is not ours")
 	}
 
 }
-- 
GitLab


From 45fb49c589fa0856e95ead29e187d691bf8c0329 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Fri, 26 Aug 2022 10:06:30 -0700
Subject: [PATCH 05/11] Remove pub key field from UsernameValidationRequest

---
 go.mod                 | 2 +-
 go.sum                 | 2 ++
 io/validateUsername.go | 4 ++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index 675412a..839a324 100644
--- a/go.mod
+++ b/go.mod
@@ -54,7 +54,7 @@ require (
 	github.com/tyler-smith/go-bip39 v1.1.0 // indirect
 	github.com/zeebo/blake3 v0.1.1 // indirect
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
-	gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1 // indirect
+	gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5 // indirect
 	gitlab.com/elixxir/ekv v0.1.7 // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	go.uber.org/ratelimit v0.2.0 // indirect
diff --git a/go.sum b/go.sum
index efc91ec..afac314 100644
--- a/go.sum
+++ b/go.sum
@@ -568,6 +568,8 @@ gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4 h1:CgI8Xb9lXxeJaMs
 gitlab.com/elixxir/comms v0.0.4-0.20220819183938-d6cd8aca6de4/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
 gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1 h1:KZ8wKOenvQaYNKo+4jdVhy3YJ7Xa3obiPxGziGJWUb4=
 gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
+gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5 h1:iFNhvChvfRN9g29HvdngQ9R613H++WS7B/XgfJJRVzs=
+gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
 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.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10=
diff --git a/io/validateUsername.go b/io/validateUsername.go
index 1a05461..92211db 100644
--- a/io/validateUsername.go
+++ b/io/validateUsername.go
@@ -26,7 +26,7 @@ const (
 func validateUsername(request *pb.UsernameValidationRequest,
 	store *storage.Storage, privKey *rsa.PrivateKey, rng io.Reader) (*pb.UsernameValidation, error) {
 	// Return an error if the request is invalid
-	if request == nil || request.Username == "" || request.ReceptionPublicKeyPem == nil {
+	if request == nil || request.Username == "" {
 		return &pb.UsernameValidation{}, errors.New("Unable to parse required " +
 			"fields in registration message")
 	}
@@ -55,7 +55,7 @@ func validateUsername(request *pb.UsernameValidationRequest,
 
 	// Create a signature verifying the user owns their username
 	verificationSignature, err := crust.SignVerification(rng, privKey,
-		request.Username, request.ReceptionPublicKeyPem)
+		request.Username, []byte(user.RsaPub))
 	if err != nil {
 		return nil, errors.Errorf("Failed to create verification signature: %v", err)
 	}
-- 
GitLab


From aada551c2db01e432503eb66acbec840c33e8473 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Fri, 26 Aug 2022 11:29:01 -0700
Subject: [PATCH 06/11] Have UD returned signed info

---
 go.mod                      |  2 +-
 go.sum                      |  4 ++++
 io/validateUsername.go      | 11 ++---------
 io/validateUsername_test.go | 18 +-----------------
 4 files changed, 8 insertions(+), 27 deletions(-)

diff --git a/go.mod b/go.mod
index 839a324..ba22491 100644
--- a/go.mod
+++ b/go.mod
@@ -54,7 +54,7 @@ require (
 	github.com/tyler-smith/go-bip39 v1.1.0 // indirect
 	github.com/zeebo/blake3 v0.1.1 // indirect
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
-	gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5 // indirect
+	gitlab.com/elixxir/comms v0.0.4-0.20220826182001-60e297d65b6c // indirect
 	gitlab.com/elixxir/ekv v0.1.7 // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	go.uber.org/ratelimit v0.2.0 // indirect
diff --git a/go.sum b/go.sum
index afac314..b9086be 100644
--- a/go.sum
+++ b/go.sum
@@ -570,6 +570,10 @@ gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1 h1:KZ8wKOenvQaYNKo
 gitlab.com/elixxir/comms v0.0.4-0.20220819220424-f2328c8b26b1/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
 gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5 h1:iFNhvChvfRN9g29HvdngQ9R613H++WS7B/XgfJJRVzs=
 gitlab.com/elixxir/comms v0.0.4-0.20220826165747-4821117053d5/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
+gitlab.com/elixxir/comms v0.0.4-0.20220826181555-87e3c7821fa0 h1:i71gTlUC6y83cKMIN9ttA4NK8mzawaWdOqVHmVjShtA=
+gitlab.com/elixxir/comms v0.0.4-0.20220826181555-87e3c7821fa0/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
+gitlab.com/elixxir/comms v0.0.4-0.20220826182001-60e297d65b6c h1:yZwll9fm84J7AfULhekk3F/e/Ubhf1OOyJdvSPuUASU=
+gitlab.com/elixxir/comms v0.0.4-0.20220826182001-60e297d65b6c/go.mod h1:j6so9oYAj2YRjOOu11gFBldtxy4ez/oPkYfqM2J1q1k=
 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.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10=
diff --git a/io/validateUsername.go b/io/validateUsername.go
index 92211db..b82522e 100644
--- a/io/validateUsername.go
+++ b/io/validateUsername.go
@@ -26,7 +26,7 @@ const (
 func validateUsername(request *pb.UsernameValidationRequest,
 	store *storage.Storage, privKey *rsa.PrivateKey, rng io.Reader) (*pb.UsernameValidation, error) {
 	// Return an error if the request is invalid
-	if request == nil || request.Username == "" {
+	if request == nil || request.UserId == nil {
 		return &pb.UsernameValidation{}, errors.New("Unable to parse required " +
 			"fields in registration message")
 	}
@@ -46,16 +46,9 @@ func validateUsername(request *pb.UsernameValidationRequest,
 			userID)
 	}
 
-	// Check that the username in storage matches the username in the request message
-	// before validating
-	if user.Username != request.Username {
-		return &pb.UsernameValidation{}, errors.Errorf(usernameNotAssociatedWithUser,
-			request.Username, userID)
-	}
-
 	// Create a signature verifying the user owns their username
 	verificationSignature, err := crust.SignVerification(rng, privKey,
-		request.Username, []byte(user.RsaPub))
+		user.Username, []byte(user.RsaPub))
 	if err != nil {
 		return nil, errors.Errorf("Failed to create verification signature: %v", err)
 	}
diff --git a/io/validateUsername_test.go b/io/validateUsername_test.go
index b8a466e..a43ae52 100644
--- a/io/validateUsername_test.go
+++ b/io/validateUsername_test.go
@@ -54,9 +54,7 @@ func TestValidateUsername(t *testing.T) {
 	username := registerMsg.Frs.Fact.Fact
 	pubKeyPem := []byte(registerMsg.RSAPublicPem)
 	validationRequest := &pb.UsernameValidationRequest{
-		Username:              username,
-		ReceptionPublicKeyPem: pubKeyPem,
-		UserId:                registerMsg.UID,
+		UserId: registerMsg.UID,
 	}
 
 	validationResponse, err := validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
@@ -104,18 +102,4 @@ func TestValidateUsername_UsernameMismatch(t *testing.T) {
 		t.Errorf("Failed happy path: %v", err)
 	}
 
-	// Test Validate username ----------------------------------------------------------------------
-	pubKeyPem := []byte(registerMsg.RSAPublicPem)
-	validationRequest := &pb.UsernameValidationRequest{
-		Username:              "admin",
-		ReceptionPublicKeyPem: pubKeyPem,
-		UserId:                registerMsg.UID,
-	}
-
-	// Send a validation request using a username that does not belong to this user
-	_, err = validateUsername(validationRequest, store, rsaPrivKey, rand.Reader)
-	if err == nil { // This should return an error
-		t.Fatalf("Should not be able to validate username that is not ours")
-	}
-
 }
-- 
GitLab


From 51e92da5325391fe9b5625e4a1b0ca94446ed847 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Mon, 29 Aug 2022 12:27:20 -0700
Subject: [PATCH 07/11] Export fields in manager object

---
 io/manager.go | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/io/manager.go b/io/manager.go
index 502e935..9e12386 100644
--- a/io/manager.go
+++ b/io/manager.go
@@ -26,12 +26,12 @@ import (
 // Manager is the main UserDiscovery instance object.
 type Manager struct {
 	Comms                  *udb.Comms
-	rng                    *fastRNG.StreamGenerator
+	Rng                    *fastRNG.StreamGenerator
 	PermissioningPublicKey *rsa.PublicKey
 	Storage                *storage.Storage
 	Twilio                 *twilio.Manager
 	Banned                 *banned.Manager
-	rsaPrivateKey          *rsa.PrivateKey
+	RsaPrivateKey          *rsa.PrivateKey
 	skipVerification       bool
 }
 
@@ -48,8 +48,8 @@ func NewManager(p params.IO, id *id.ID, rsaPrivateKey *rsa.PrivateKey,
 		Twilio:                 twilio,
 		Banned:                 banned,
 		skipVerification:       skipVerification,
-		rsaPrivateKey:          rsaPrivateKey,
-		rng:                    rng,
+		RsaPrivateKey:          rsaPrivateKey,
+		Rng:                    rng,
 	}
 
 	m.Comms = udb.StartServer(id, fmt.Sprintf("0.0.0.0:%s", p.Port),
@@ -84,9 +84,9 @@ func newImplementation(m *Manager) *udb.Implementation {
 	}
 
 	impl.Functions.ValidateUsername = func(request *pb.UsernameValidationRequest) (*pb.UsernameValidation, error) {
-		stream := m.rng.GetStream()
+		stream := m.Rng.GetStream()
 		defer stream.Close()
-		return validateUsername(request, m.Storage, m.rsaPrivateKey, stream)
+		return validateUsername(request, m.Storage, m.RsaPrivateKey, stream)
 	}
 
 	return impl
-- 
GitLab


From 8d6986eb670426723836bade58d67558bb066d24 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Wed, 9 Nov 2022 11:58:48 -0800
Subject: [PATCH 08/11] Fix build issues from pulling release

---
 io/validateUsername.go | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/io/validateUsername.go b/io/validateUsername.go
index b82522e..4599cd6 100644
--- a/io/validateUsername.go
+++ b/io/validateUsername.go
@@ -21,36 +21,47 @@ const (
 	usernameNotAssociatedWithUser = "username %s is not associated with user ID %s"
 )
 
-// ValidateUsername validates that a user owns a username by signing the contents of the
-// mixmessages.UsernameValidationRequest.
+// ValidateUsername validates that a user owns a username by signing the
+// contents of the mixmessages.UsernameValidationRequest.
 func validateUsername(request *pb.UsernameValidationRequest,
-	store *storage.Storage, privKey *rsa.PrivateKey, rng io.Reader) (*pb.UsernameValidation, error) {
+	store *storage.Storage, privKey *rsa.PrivateKey,
+	rng io.Reader) (*pb.UsernameValidation, error) {
 	// Return an error if the request is invalid
 	if request == nil || request.UserId == nil {
-		return &pb.UsernameValidation{}, errors.New("Unable to parse required " +
-			"fields in registration message")
+		return &pb.UsernameValidation{}, errors.New("Unable to parse " +
+			"required fields in registration message")
 	}
 
 	// Marshal user ID
 	userID, err := id.Unmarshal(request.UserId)
 	if err != nil {
-		return &pb.UsernameValidation{}, errors.WithMessage(err, invalidUserIdError)
+		return &pb.UsernameValidation{},
+			errors.WithMessage(err, invalidUserIdError)
 	}
 
 	// Return an error if the user is not registered
 	user, err := store.GetUser(request.UserId)
 	if err != nil {
-		return &pb.UsernameValidation{}, errors.WithMessage(err, getUserFailureError)
+		return &pb.UsernameValidation{},
+			errors.WithMessage(err, getUserFailureError)
 	} else if user == nil {
 		return &pb.UsernameValidation{}, errors.Errorf(noUserError,
 			userID)
 	}
 
+	// Parse the client's public key
+	clientPubKey, err := rsa.LoadPublicKeyFromPem([]byte(user.RsaPub))
+	if err != nil {
+		return &pb.UsernameValidation{},
+			errors.New("Could not parse key from storage")
+	}
+
 	// Create a signature verifying the user owns their username
 	verificationSignature, err := crust.SignVerification(rng, privKey,
-		user.Username, []byte(user.RsaPub))
+		user.Username, clientPubKey)
 	if err != nil {
-		return nil, errors.Errorf("Failed to create verification signature: %v", err)
+		return nil, errors.Errorf("Failed to create verification signature: %v",
+			err)
 	}
 
 	// Return signature to user
-- 
GitLab


From e4d89e47ffe273af4a5116a6b53b594c7b04e270 Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Wed, 9 Nov 2022 12:15:25 -0800
Subject: [PATCH 09/11] Fix tests

---
 io/validateUsername_test.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/io/validateUsername_test.go b/io/validateUsername_test.go
index a43ae52..252ad13 100644
--- a/io/validateUsername_test.go
+++ b/io/validateUsername_test.go
@@ -13,6 +13,7 @@ import (
 	"gitlab.com/elixxir/crypto/partnerships/crust"
 	"gitlab.com/elixxir/user-discovery-bot/banned"
 	"gitlab.com/elixxir/user-discovery-bot/storage"
+	"gitlab.com/xx_network/crypto/signature/rsa"
 	"gitlab.com/xx_network/primitives/ndf"
 	"testing"
 	"time"
@@ -62,8 +63,10 @@ func TestValidateUsername(t *testing.T) {
 		t.Fatalf("Failed to validate username: %+v", err)
 	}
 
+	clientPubKey, _ := rsa.LoadPublicKeyFromPem(pubKeyPem)
+
 	err = crust.VerifyVerificationSignature(rsaPrivKey.GetPublic(),
-		username, pubKeyPem, validationResponse.Signature)
+		crust.HashUsername(username), clientPubKey, validationResponse.Signature)
 	if err != nil {
 		t.Fatalf("validateUsername did not return a valid signature!")
 	}
-- 
GitLab


From 268de962ab853354edeb922f2c2cf0f3bcf5fb6a Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Thu, 10 Nov 2022 13:13:36 -0800
Subject: [PATCH 10/11] Return user's public key in pb.UsernameValidation

---
 io/validateUsername.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/io/validateUsername.go b/io/validateUsername.go
index 4599cd6..6e3706f 100644
--- a/io/validateUsername.go
+++ b/io/validateUsername.go
@@ -65,5 +65,8 @@ func validateUsername(request *pb.UsernameValidationRequest,
 	}
 
 	// Return signature to user
-	return &pb.UsernameValidation{Signature: verificationSignature}, nil
+	return &pb.UsernameValidation{
+		Signature:             verificationSignature,
+		ReceptionPublicKeyPem: []byte(user.RsaPub),
+	}, nil
 }
-- 
GitLab


From 7cf8a14a986d33da31b16e9b569c21231b7ae57f Mon Sep 17 00:00:00 2001
From: joshemb <josh@elixxir.io>
Date: Thu, 10 Nov 2022 13:26:45 -0800
Subject: [PATCH 11/11] Return username to user in pb.UsernameValidation

---
 io/validateUsername.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/io/validateUsername.go b/io/validateUsername.go
index 6e3706f..926f655 100644
--- a/io/validateUsername.go
+++ b/io/validateUsername.go
@@ -66,6 +66,7 @@ func validateUsername(request *pb.UsernameValidationRequest,
 
 	// Return signature to user
 	return &pb.UsernameValidation{
+		Username:              user.Username,
 		Signature:             verificationSignature,
 		ReceptionPublicKeyPem: []byte(user.RsaPub),
 	}, nil
-- 
GitLab