forked from tvdburgt/go-argon2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontext.go
96 lines (83 loc) · 2.46 KB
/
context.go
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package argon2
// #cgo CFLAGS: -I/usr/include
// #include <argon2.h>
// #include "wrapper.h"
import "C"
// Context represents a structure that holds all static configuration values,
// used to parameterize an Argon2 hash function.
type Context struct {
Iterations int // number of iterations (t_cost)
Memory int // memory usage in KiB (m_cost)
Parallelism int // number of parallel threads
HashLen int // desired hash output length
Mode int // ModeArgon2d, ModeArgon2i, or ModeArgon2id
Version int // Version10 or Version13 (aka VersionDefault)
Secret []byte // optional (not used by default)
AssociatedData []byte // optional (not used by default)
Flags int // optional (default is FlagDefault)
}
// NewContext initializes a new Argon2 context with reasonable defaults.
// allows the mode to be set as an optional paramter
func NewContext(mode ...int) *Context {
context := &Context{
Iterations: 3,
Memory: 1 << 12, // 4 MiB
Parallelism: 1,
HashLen: 32,
Mode: ModeArgon2i,
Version: VersionDefault,
}
if len(mode) >= 1 {
context.Mode = mode[0]
}
return context
}
// hash password and salt
func (ctx *Context) hash(password []byte, salt []byte) ([]byte, error) {
if len(password) == 0 {
return nil, ErrPassword
}
if len(salt) == 0 {
return nil, ErrSalt
}
hash := make([]byte, ctx.HashLen)
// optional secret
secret := (*C.uint8_t)(nil)
if len(ctx.Secret) > 0 {
secret = (*C.uint8_t)(&ctx.Secret[0])
}
// optional associated data
associatedData := (*C.uint8_t)(nil)
if len(ctx.AssociatedData) > 0 {
associatedData = (*C.uint8_t)(&ctx.AssociatedData[0])
}
// optional flags
flags := FlagDefault
if ctx.Flags != 0 {
flags = ctx.Flags
}
// ensure version has a default
version := VersionDefault
if ctx.Version != 0 {
version = ctx.Version
}
// wrapper to overcome go pointer passing limitations
result := C.argon2_wrapper(
(*C.uint8_t)(&hash[0]), C.uint32_t(ctx.HashLen),
(*C.uint8_t)(&password[0]), C.uint32_t(len(password)),
(*C.uint8_t)(&salt[0]), C.uint32_t(len(salt)),
secret, C.uint32_t(len(ctx.Secret)),
associatedData, C.uint32_t(len(ctx.AssociatedData)),
C.uint32_t(ctx.Iterations),
C.uint32_t(ctx.Memory),
C.uint32_t(ctx.Parallelism),
C.uint32_t(ctx.Parallelism),
C.uint32_t(version),
nil, nil,
C.uint32_t(flags),
C.argon2_type(ctx.Mode))
if result != C.ARGON2_OK {
return nil, Error(result)
}
return hash, nil
}