Hash stored admin codes

This commit is contained in:
Brandon Dyck 2021-03-03 21:22:09 -07:00
parent b7c7c2bf23
commit 0c37286522
3 changed files with 37 additions and 6 deletions

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.15
require ( require (
crawshaw.io/sqlite v0.3.2 crawshaw.io/sqlite v0.3.2
github.com/matryer/is v1.4.0 github.com/matryer/is v1.4.0
github.com/matthewhartstonge/argon2 v0.1.4
github.com/rickb777/date v1.14.0 github.com/rickb777/date v1.14.0
gitlab.codemonkeysoftware.net/b/hatmill v0.0.6 gitlab.codemonkeysoftware.net/b/hatmill v0.0.6
) )

4
go.sum
View File

@ -21,6 +21,8 @@ github.com/leanovate/gopter v0.2.4 h1:U4YLBggDFhJdqQsG4Na2zX7joVTky9vHaj/AGEwSuX
github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8= github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/matthewhartstonge/argon2 v0.1.4 h1:XalXB/BERpIZbOHV/31FYFFQxsl6GTrTq2N10rwfNGc=
github.com/matthewhartstonge/argon2 v0.1.4/go.mod h1:ZOSVMa24Ro9NpCjIobiwO49tymOSJ8ZaUmbcdrbrhYQ=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -36,6 +38,8 @@ github.com/rickb777/plural v1.2.1/go.mod h1:j058+3M5QQFgcZZ2oKIOekcygoZUL8gKW5yR
gitlab.codemonkeysoftware.net/b/hatmill v0.0.6 h1:5Vs30ORHoujCYRvtbIwrusGBQgPzbKv011xKrTFa5ng= gitlab.codemonkeysoftware.net/b/hatmill v0.0.6 h1:5Vs30ORHoujCYRvtbIwrusGBQgPzbKv011xKrTFa5ng=
gitlab.codemonkeysoftware.net/b/hatmill v0.0.6/go.mod h1:T19ms3BmsEzy5YTS4icMO1oLC53xWhOP9MFeBv4NcFQ= gitlab.codemonkeysoftware.net/b/hatmill v0.0.6/go.mod h1:T19ms3BmsEzy5YTS4icMO1oLC53xWhOP9MFeBv4NcFQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=

View File

@ -9,6 +9,7 @@ import (
"crawshaw.io/sqlite" "crawshaw.io/sqlite"
"crawshaw.io/sqlite/sqlitex" "crawshaw.io/sqlite/sqlitex"
"github.com/matthewhartstonge/argon2"
"github.com/rickb777/date" "github.com/rickb777/date"
) )
@ -23,6 +24,21 @@ func (u UnauthorizedError) Error() string {
return fmt.Sprintf("unauthorized: EventID = %s, AdminCode = %s", u.EventID, u.AdminCode) return fmt.Sprintf("unauthorized: EventID = %s, AdminCode = %s", u.EventID, u.AdminCode)
} }
func hash(password string) (string, error) {
hashed, err := (&argon2.Config{
HashLength: 32,
// We don't need a salt because our random passwords are not
// susceptible to dictionary attacks.
SaltLength: 0,
TimeCost: 3,
MemoryCost: 64 * 1024,
Parallelism: 4,
Mode: argon2.ModeArgon2id,
Version: argon2.Version13,
}).HashEncoded([]byte(password))
return string(hashed), err
}
type GenString func(length int) (string, error) type GenString func(length int) (string, error)
type Store struct { type Store struct {
@ -82,7 +98,7 @@ func (s *Store) Close() error {
const schema = ` const schema = `
CREATE TABLE event ( CREATE TABLE event (
id TEXT NOT NULL PRIMARY KEY, id TEXT NOT NULL PRIMARY KEY,
admin_code TEXT NOT NULL, admin_code_hash TEXT NOT NULL,
name TEXT NOT NULL, name TEXT NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
earliest_date DATE NOT NULL, earliest_date DATE NOT NULL,
@ -157,12 +173,17 @@ func (s *Store) CreateEvent(ctx context.Context, cmd CreateEventCommand) (result
return return
} }
adminCodeHash, err := hash(adminCode)
if err != nil {
return
}
const query = ` const query = `
INSERT INTO event(id, admin_code, name, description, earliest_date, latest_date) INSERT INTO event(id, admin_code_hash, name, description, earliest_date, latest_date)
VALUES (?, ?, ?, ?, ?, ?);` VALUES (?, ?, ?, ?, ?, ?);`
err = sqlitex.Exec(conn, query, nil, err = sqlitex.Exec(conn, query, nil,
id, id,
adminCode, adminCodeHash,
cmd.Name, cmd.Name,
cmd.Description, cmd.Description,
cmd.Earliest.Format(dbDateLayout), cmd.Earliest.Format(dbDateLayout),
@ -186,16 +207,21 @@ func (s *Store) AuthorizeEventAdmin(ctx context.Context, query CheckEventAdminCo
conn := s.pool.Get(ctx) conn := s.pool.Get(ctx)
defer s.pool.Put(conn) defer s.pool.Put(conn)
adminCodeHash, err := hash(query.AdminCode)
if err != nil {
return err
}
const dbQuery = ` const dbQuery = `
SELECT 1 SELECT 1
FROM event FROM event
WHERE id = ? AND admin_code = ?;` WHERE id = ? AND admin_code_hash = ?;`
var doesMatch bool var doesMatch bool
err := sqlitex.Exec(conn, dbQuery, err = sqlitex.Exec(conn, dbQuery,
func(stmt *sqlite.Stmt) error { func(stmt *sqlite.Stmt) error {
doesMatch = true doesMatch = true
return nil return nil
}, query.EventID, query.AdminCode) }, query.EventID, adminCodeHash)
if err != nil { if err != nil {
return err return err
} }