-
Notifications
You must be signed in to change notification settings - Fork 0
/
opts.go
222 lines (181 loc) · 6.82 KB
/
opts.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package argon2
import (
"fmt"
"github.com/go-crypt/crypt/algorithm"
)
// Opt describes the functional option pattern for the argon2.Hasher.
type Opt func(h *Hasher) (err error)
// WithVariant is used to configure the argon2.Variant of the resulting argon2.Digest.
// Default is argon2.VariantID.
func WithVariant(variant Variant) Opt {
return func(h *Hasher) (err error) {
switch variant {
case VariantNone, VariantI, VariantID, VariantD:
h.variant = variant
return nil
default:
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf("%w: variant '%d' is invalid", algorithm.ErrParameterInvalid, variant))
}
}
}
// WithVariantName uses the variant name or identifier to configure the argon2.Variant of the resulting argon2.Digest.
// Default is argon2.VariantID.
func WithVariantName(identifier string) Opt {
return func(h *Hasher) (err error) {
if identifier == "" {
return nil
}
variant := NewVariant(identifier)
if variant == VariantNone {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf("%w: variant identifier '%s' is invalid", algorithm.ErrParameterInvalid, identifier))
}
h.variant = variant
return nil
}
}
// WithVariantI satisfies the argon2.Opt type and sets the variant as argon2.VariantI.
func WithVariantI() Opt {
return func(h *Hasher) error {
h.variant = VariantI
return nil
}
}
// WithVariantID satisfies the argon2.Opt type and sets the variant as argon2.VariantID.
func WithVariantID() Opt {
return func(h *Hasher) error {
h.variant = VariantID
return nil
}
}
// WithVariantD satisfies the argon2.Opt type and sets the variant as argon2.VariantD.
func WithVariantD() Opt {
return func(h *Hasher) error {
h.variant = VariantD
return nil
}
}
// WithP satisfies the argon2.Opt type for the argon2.Hasher and sets input 'p' known as the degree of parallelism.
//
// Degree of parallelism p determines how many independent (but synchronizing) computational chains (lanes) can be run.
// It MUST be an integer value from 1 to 2^(24)-1.
//
// Minimum is 1, Maximum is 16777215. Default is 4.
//
// RFC9106 section 3.1 "Argon2 Inputs and Outputs" https://www.rfc-editor.org/rfc/rfc9106.html#name-argon2-inputs-and-outputs.
func WithP(p int) Opt {
return func(h *Hasher) (err error) {
if p < ParallelismMin || p > ParallelismMax {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "parallelism", ParallelismMin, "", ParallelismMax, p))
}
h.p = p
return nil
}
}
// WithParallelism is an alias for WithP.
func WithParallelism(p int) Opt {
return WithP(p)
}
// WithM satisfies the argon2.Opt type for the argon2.Hasher and sets input 'm' known as the memory size.
//
// Memory size m MUST be an integer number of kibibytes from 8*p to 2^(32)-1. The actual number of blocks is m', which
// is m rounded down to the nearest multiple of 4*p.
//
// Minimum is 8, Maximum is 4294967295. Default is 2097152.
//
// RFC9106 section 3.1 "Argon2 Inputs and Outputs" https://www.rfc-editor.org/rfc/rfc9106.html#name-argon2-inputs-and-outputs.
func WithM(m uint32) Opt {
return func(h *Hasher) (err error) {
if m < MemoryMin || m > MemoryMax {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "memory", MemoryMin, "", MemoryMax, m))
}
h.m = m
return nil
}
}
// WithMemoryInKiB is an alias for WithM.
func WithMemoryInKiB(m uint32) Opt {
return WithM(m)
}
// WithT satisfies the argon2.Opt type for the argon2.Hasher and sets input 't' known as the number of passes.
//
// Number of passes t (used to tune the running time independently of the memory size) MUST be an integer number from 1 to 2^(32)-1.
//
// Minimum is 1, Maximum is 2147483647. Default is 1.
//
// RFC9106 section 3.1 "Argon2 Inputs and Outputs" https://www.rfc-editor.org/rfc/rfc9106.html#name-argon2-inputs-and-outputs.
func WithT(t int) Opt {
return func(h *Hasher) (err error) {
if t < IterationsMin || t > IterationsMax {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "t", IterationsMin, "", IterationsMax, t))
}
h.t = t
return nil
}
}
// WithIterations is an alias for WithT.
func WithIterations(t int) Opt {
return WithT(t)
}
// WithK satisfies the argon2.Opt type for the argon2.Hasher and sets input 'T' known as the tag length.
//
// Tag length T MUST be an integer number of bytes from 4 to 2^(32)-1. The Argon2 output, or "tag", is a string T bytes long.
//
// Minimum is 4, Maximum is 2147483647. Default is 32.
//
// RFC9106 section 3.1 "Argon2 Inputs and Outputs" https://www.rfc-editor.org/rfc/rfc9106.html#name-argon2-inputs-and-outputs.
func WithK(k int) Opt {
return func(h *Hasher) (err error) {
if k < KeyLengthMin || k > KeyLengthMax {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "k", KeyLengthMin, "", KeyLengthMax, k))
}
h.k = k
return nil
}
}
// WithTagLength is an alias for WithK.
func WithTagLength(k int) Opt {
return WithK(k)
}
// WithKeyLength is an alias for WithK.
func WithKeyLength(k int) Opt {
return WithK(k)
}
// WithS satisfies the argon2.Opt type for the argon2.Hasher and sets the length of input 'S' known as the salt length.
//
// Nonce S, which is a salt for password hashing applications. It MUST have a length not greater than 2^(32)-1 bytes.
// 16 bytes is RECOMMENDED for password hashing. The salt SHOULD be unique for each password.
//
// Minimum is 1, Maximum is 2147483647. Default is 16.
//
// RFC9106 section 3.1 "Argon2 Inputs and Outputs" https://www.rfc-editor.org/rfc/rfc9106.html#name-argon2-inputs-and-outputs.
func WithS(s int) Opt {
return func(h *Hasher) (err error) {
if s < SaltLengthMin || s > SaltLengthMax {
return fmt.Errorf(algorithm.ErrFmtHasherValidation, AlgName, fmt.Errorf(algorithm.ErrFmtInvalidIntParameter, algorithm.ErrParameterInvalid, "s", SaltLengthMin, "", SaltLengthMax, s))
}
h.s = s
return nil
}
}
// WithSaltLength is an alias for WithS.
func WithSaltLength(s int) Opt {
return WithS(s)
}
// WithProfileRFC9106Recommended is the recommended standard RFC9106 profile.
//
// RFC9106 section 4.0 "Parameter Choice" https://www.rfc-editor.org/rfc/rfc9106.html#name-parameter-choice
func WithProfileRFC9106Recommended() Opt {
return func(h *Hasher) (err error) {
ProfileRFC9106Recommended.Hasher().Merge(h)
return nil
}
}
// WithProfileRFC9106LowMemory is the recommended low memory RFC9106 profile.
//
// RFC9106 section 4.0 "Parameter Choice" https://www.rfc-editor.org/rfc/rfc9106.html#name-parameter-choice
func WithProfileRFC9106LowMemory() Opt {
return func(h *Hasher) (err error) {
ProfileRFC9106LowMemory.Hasher().Merge(h)
return nil
}
}