1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package user
import (
"crypto/rand"
"encoding/base64"
"fmt"
"time"
"gitlab.com/alexkavon/newsstand/src/db"
"golang.org/x/crypto/argon2"
)
type User struct {
Id int64
Username string `validate:"required,max=50"`
Secret string `validate:"required,min=8,max=128"`
Email string `validate:"required,email"`
Karma uint64
UpdatedAt time.Time
CreatedAt time.Time
hash string
Db *db.Database
}
func NewUser(d *db.Database) *User {
return &User{
Db: d,
}
}
func (u *User) Insert() error {
err := u.Db.InsertTable(
"users",
[]string{"username", "secret", "email"},
db.DbValues{"username": u.Username, "secret": string(u.hash), "email": u.Email},
)
if err != nil {
return err
}
return nil
}
func (u *User) HashSecret() error {
hashconf := &struct {
memory uint32
iterations uint32
parallelism uint8
keyLength uint32
saltLength uint32
}{64 * 1024, 3, 2, 12, 16}
salt := make([]byte, hashconf.saltLength)
_, err := rand.Read(salt)
if err != nil {
return err
}
hash := argon2.IDKey(
[]byte(u.Secret),
salt,
hashconf.iterations,
hashconf.memory,
hashconf.parallelism,
hashconf.keyLength,
)
b64Salt := base64.RawStdEncoding.EncodeToString(salt)
b64Hash := base64.RawStdEncoding.EncodeToString(hash)
encodedHash := fmt.Sprintf(
"$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
argon2.Version,
hashconf.memory,
hashconf.iterations,
hashconf.parallelism,
b64Salt,
b64Hash,
)
u.hash = encodedHash
return nil
}
|