From 7114af9d8c77d3084c3bc9be6288a18efb1afbe3 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 9 May 2025 17:33:01 -0700 Subject: [PATCH] get it testing --- .gitignore | 1 + data/rand.go | 2 ++ data/user.go | 48 +++++++++++++++++++++++++++++++++--------------- go.mod | 6 +++++- go.sum | 5 +++++ schema.sql | 13 +++++++++++++ 6 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f9352ec --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/mcias.db diff --git a/data/rand.go b/data/rand.go index eeb34ae..4b8468e 100644 --- a/data/rand.go +++ b/data/rand.go @@ -1,5 +1,7 @@ package data +import "crypto/rand" + const saltLength = 32 func Salt() ([]byte, error) { diff --git a/data/user.go b/data/user.go index f5d75d6..eec99d2 100644 --- a/data/user.go +++ b/data/user.go @@ -1,35 +1,49 @@ package data +import ( + "crypto/subtle" + "errors" + "fmt" + "time" + + "github.com/oklog/ulid/v2" + "golang.org/x/crypto/scrypt" +) + const ( scryptN = 32768 - scriptR = 8 + scryptR = 8 scryptP = 1 ) type User struct { - ID string - Created int64 - User string + ID string + Created int64 + User string Password []byte - Salt []byte + Salt []byte + Roles []string } type Login struct { - User string `json:"user"` + User string `json:"user"` Password string `json:"password,omitzero"` - Token string `json:"token,omitzero"` + Token string `json:"token,omitzero"` } -func derive(password string, salt []byte) []byte { - return scrypt.Key(login.Password, u.Salt, scryptN, scryptR, scryptN, 32) +func derive(password string, salt []byte) ([]byte, error) { + return scrypt.Key([]byte(password), salt, scryptN, scryptR, scryptN, 32) } func (u *User) Check(login *Login) bool { if u.User != login.User { return false } - - derived := derive(login.Password, u.Salt) + + derived, err := derive(login.Password, u.Salt) + if err != nil { + return false + } if subtle.ConstantTimeCompare(derived, u.Password) != 0 { return false @@ -40,13 +54,13 @@ func (u *User) Check(login *Login) bool { func (u *User) Register(login *Login) error { var err error - + if u.User != "" && u.User != login.User { return errors.New("invalid user") } if u.ID == "" { - u.ID = ulid.Make() + u.ID = ulid.Make().String() } u.User = login.User @@ -55,7 +69,11 @@ func (u *User) Register(login *Login) error { return fmt.Errorf("failed to register user: %w", err) } - u.Password = derive(login.Password, u.Salt) + u.Password, err = derive(login.Password, u.Salt) + if err != nil { + return fmt.Errorf("key derivation failed: %w", err) + } + + u.Created = time.Now().Unix() return nil } - diff --git a/go.mod b/go.mod index 357d992..ce99df2 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module git.wntrmute.dev/kyle/mcias go 1.23.8 -require github.com/mattn/go-sqlite3 v1.14.28 // indirect +require ( + github.com/mattn/go-sqlite3 v1.14.28 // indirect + github.com/oklog/ulid/v2 v2.1.0 // indirect + golang.org/x/crypto v0.38.0 // indirect +) diff --git a/go.sum b/go.sum index 42e5bac..96418fb 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,7 @@ github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= diff --git a/schema.sql b/schema.sql index 17270ae..8ee9a78 100644 --- a/schema.sql +++ b/schema.sql @@ -27,3 +27,16 @@ CREATE TABLE registrations ( id text primary key, code text not null ); + +CREATE TABLE roles ( + id text primary key, + role text not null +); + +CREATE TABLE user_roles ( + id text primary key, + uid text not null, + rid text not null, + FOREIGN KEY(uid) REFERENCES user(id), + FOREIGN KEY(rid) REFERENCES roles(id) +);