summaryrefslogtreecommitdiff
path: root/srv/src/chat/user.go
diff options
context:
space:
mode:
Diffstat (limited to 'srv/src/chat/user.go')
-rw-r--r--srv/src/chat/user.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/srv/src/chat/user.go b/srv/src/chat/user.go
new file mode 100644
index 0000000..3f5ab95
--- /dev/null
+++ b/srv/src/chat/user.go
@@ -0,0 +1,68 @@
+package chat
+
+import (
+ "encoding/hex"
+ "fmt"
+ "sync"
+
+ "golang.org/x/crypto/argon2"
+)
+
+// UserID uniquely identifies an individual user who has posted a message in a
+// Room.
+type UserID struct {
+
+ // Name will be the user's chosen display name.
+ Name string `json:"name"`
+
+ // Hash will be a hex string generated from a secret only the user knows.
+ Hash string `json:"id"`
+}
+
+// UserIDCalculator is used to calculate UserIDs.
+type UserIDCalculator struct {
+
+ // Secret is used when calculating UserID Hash salts.
+ Secret []byte
+
+ // TimeCost, MemoryCost, and Threads are used as inputs to the Argon2id
+ // algorithm which is used to generate the Hash.
+ TimeCost, MemoryCost uint32
+ Threads uint8
+
+ // HashLen specifies the number of bytes the Hash should be.
+ HashLen uint32
+
+ // Lock, if set, forces concurrent Calculate calls to occur sequentially.
+ Lock *sync.Mutex
+}
+
+// NewUserIDCalculator returns a UserIDCalculator with sane defaults.
+func NewUserIDCalculator(secret []byte) *UserIDCalculator {
+ return &UserIDCalculator{
+ Secret: secret,
+ TimeCost: 15,
+ MemoryCost: 128 * 1024,
+ Threads: 2,
+ HashLen: 16,
+ Lock: new(sync.Mutex),
+ }
+}
+
+// Calculate accepts a name and password and returns the calculated UserID.
+func (c *UserIDCalculator) Calculate(name, password string) UserID {
+
+ input := fmt.Sprintf("%q:%q", name, password)
+
+ hashB := argon2.IDKey(
+ []byte(input),
+ c.Secret, // salt
+ c.TimeCost, c.MemoryCost, c.Threads,
+ c.HashLen,
+ )
+
+ return UserID{
+ Name: name,
+ Hash: hex.EncodeToString(hashB),
+ }
+}