1
2
3
4
5 package s2k
6
7 import (
8 "bytes"
9 "crypto"
10 "crypto/rand"
11 "crypto/sha1"
12 _ "crypto/sha256"
13 _ "crypto/sha512"
14 "encoding/hex"
15 "testing"
16
17 _ "golang.org/x/crypto/ripemd160"
18 _ "golang.org/x/crypto/sha3"
19 )
20
21 var saltedTests = []struct {
22 in, out string
23 }{
24 {"hello", "10295ac1"},
25 {"world", "ac587a5e"},
26 {"foo", "4dda8077"},
27 {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
28 {"x", "f1d3f289"},
29 {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
30 }
31
32 func TestSalted(t *testing.T) {
33 h := sha1.New()
34 salt := [4]byte{1, 2, 3, 4}
35
36 for i, test := range saltedTests {
37 expected, _ := hex.DecodeString(test.out)
38 out := make([]byte, len(expected))
39 Salted(out, h, []byte(test.in), salt[:])
40 if !bytes.Equal(expected, out) {
41 t.Errorf("#%d, got: %x want: %x", i, out, expected)
42 }
43 }
44 }
45
46 var argon2EncodeTest = []struct {
47 in uint32
48 out uint8
49 }{
50 {64*1024, 16},
51 {64*1024+1, 17},
52 {2147483647, 31},
53 {2147483649, 31},
54 {1, 3},
55 }
56
57 func TestArgon2EncodeTest(t *testing.T) {
58
59 for i, tests := range argon2EncodeTest {
60 conf := &Argon2Config {
61 Memory: tests.in,
62 DegreeOfParallelism: 1,
63 }
64 out := conf.EncodedMemory()
65 if out != tests.out {
66 t.Errorf("#%d, got: %x want: %x", i, out, tests.out)
67 }
68 }
69 }
70
71
72 var iteratedTests = []struct {
73 in, out string
74 }{
75 {"hello", "83126105"},
76 {"world", "6fa317f9"},
77 {"foo", "8fbc35b9"},
78 {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
79 {"x", "5a684dfe"},
80 {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
81 }
82
83 func TestIterated(t *testing.T) {
84 h := sha1.New()
85 salt := [4]byte{4, 3, 2, 1}
86
87 for i, test := range iteratedTests {
88 expected, _ := hex.DecodeString(test.out)
89 out := make([]byte, len(expected))
90 Iterated(out, h, []byte(test.in), salt[:], 31)
91 if !bytes.Equal(expected, out) {
92 t.Errorf("#%d, got: %x want: %x", i, out, expected)
93 }
94 }
95 }
96
97 var argonTestSalt = "12345678"
98 var argon2DeriveTests = []struct {
99 in, out string
100 }{
101 {"hello", "bf69293d2961bbbebe4c64c745cf44d4"},
102 {"world", "dc1bb06234b61c9542d8cf73e2e279d3"},
103 {"foo", "7f6baa1c21f0e7eec16cf8fde866775d"},
104 {"bar", "2826332c8e62d0cf97cc08f243c5cc9135654bf3a8e46d6a4b4637e42eda2fa0"},
105 {"x", "89e5b79435132b98bbcad321532ae7e09f87ac96deca272d6012d367e6350b7d"},
106 {"xxxxxxxxxxxxxxxxxxxxxxx", "de0f978013283457e29f0682e0078ad654e7c21bc72886c914c012e56fd5dc91"},
107 }
108
109 func TestArgon2Derive(t *testing.T) {
110 salt := []byte(argonTestSalt)
111
112 for i, test := range argon2DeriveTests {
113 expected, _ := hex.DecodeString(test.out)
114 out := make([]byte, len(expected))
115 Argon2(out, []byte(test.in), salt[:], 3, 4, 16)
116 if !bytes.Equal(expected, out) {
117 t.Errorf("#%d, got: %x want: %x", i, out, expected)
118 }
119 }
120 }
121
122 var parseTests = []struct {
123 spec, in, out string
124 dummyKey bool
125 params Params
126 }{
127
128 {"0002", "hello", "aaf4c61d", false,
129 Params{SimpleS2K, 0x02, [16]byte{}, 0, 0, 0, 0}},
130
131 {"01020102030405060708", "hello", "f4f7d67e", false,
132 Params{SaltedS2K, 0x02, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, 0, 0, 0}},
133
134 {"03020102030405060708f1", "hello", "f2a57b7c", false,
135 Params{IteratedSaltedS2K, 0x02, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0xf1, 0, 0, 0}},
136
137 {"0401020304050607080102030405060708030410", "hello", "dabc018a", false,
138 Params{Argon2S2K, 0x00, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0, 0x03, 0x04, 0x10}},
139
140 {"6502474e5501", "", "", true,
141 Params{GnuS2K, 0x02, [16]byte{}, 0, 0, 0, 0}},
142 }
143
144 func TestParseIntoParams(t *testing.T) {
145 for i, test := range parseTests {
146 spec, _ := hex.DecodeString(test.spec)
147 buf := bytes.NewBuffer(spec)
148 params, err := ParseIntoParams(buf)
149 if err != nil {
150 t.Errorf("%d: ParseIntoParams returned error: %s", i, err)
151 continue
152 }
153
154 if test.params.mode != params.mode || test.params.hashId != params.hashId || test.params.countByte != params.countByte ||
155 !bytes.Equal(test.params.salt(), params.salt()) {
156 t.Errorf("%d: Wrong config, got: %+v want: %+v", i, params, test.params)
157 }
158
159 if params.Dummy() != test.dummyKey {
160 t.Errorf("%d: Got GNU dummy %v, expected %v", i, params.Dummy(), test.dummyKey)
161 }
162
163 if !test.dummyKey {
164 expectedHash, _ := hex.DecodeString(test.out)
165 out := make([]byte, len(expectedHash))
166
167 f, err := params.Function()
168 if err != nil {
169 t.Errorf("%d: params.Function() returned error: %s", i, err)
170 continue
171 }
172 f(out, []byte(test.in))
173 if !bytes.Equal(out, expectedHash) {
174 t.Errorf("%d: Wrong output got: %x want: %x", i, out, expectedHash)
175 }
176 }
177
178 var reserialized bytes.Buffer
179 err = params.Serialize(&reserialized)
180 if err != nil {
181 t.Errorf("%d: params.Serialize() returned error: %s", i, err)
182 continue
183 }
184 if !bytes.Equal(reserialized.Bytes(), spec) {
185 t.Errorf("%d: Wrong reserialized got: %x want: %x", i, reserialized.Bytes(), spec)
186 }
187 if testing.Short() {
188 break
189 }
190 }
191 }
192
193 func TestSerializeSaltedOK(t *testing.T) {
194 hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
195 crypto.SHA3_512}
196 for _, h := range hashes {
197 params := testSerializeConfigOK(t, &Config{S2KMode: SaltedS2K, Hash: h, PassphraseIsHighEntropy: true})
198
199 if params.mode != SaltedS2K {
200 t.Fatalf("Wrong mode, expected %d got %d", SaltedS2K, params.mode)
201 }
202 }
203 }
204
205 func TestSerializeSaltedLowEntropy(t *testing.T) {
206 hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
207 crypto.SHA3_512}
208 for _, h := range hashes {
209 params := testSerializeConfigOK(t, &Config{S2KMode: SaltedS2K, Hash: h})
210
211 if params.mode != IteratedSaltedS2K {
212 t.Fatalf("Wrong mode, expected %d got %d", IteratedSaltedS2K, params.mode)
213 }
214
215 if params.countByte != 224 {
216 t.Fatalf("Wrong count byte, expected %d got %d", 224, params.countByte)
217 }
218 }
219 }
220
221 func TestSerializeSaltedIteratedOK(t *testing.T) {
222 hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
223 crypto.SHA3_512}
224
225 testCounts := [][]int{{-1, 96}, {0, 224}, {1024, 96}, {65536, 96}, {4063232, 191}, {65011712, 255}}
226 for _, h := range hashes {
227 for _, c := range testCounts {
228 params := testSerializeConfigOK(t, &Config{Hash: h, S2KCount: c[0]})
229
230 if params.mode != IteratedSaltedS2K {
231 t.Fatalf("Wrong mode, expected %d got %d", IteratedSaltedS2K, params.mode)
232 }
233
234 if int(params.countByte) != c[1] {
235 t.Fatalf("Wrong count byte, expected %d got %d", c[1], params.countByte)
236 }
237 }
238 }
239 }
240
241 func TestSerializeOKArgon(t *testing.T) {
242 config := &Config{
243 S2KMode: Argon2S2K,
244 Argon2Config: &Argon2Config{NumberOfPasses: 3, DegreeOfParallelism: 4, Memory: 64*1024},
245 }
246
247 params := testSerializeConfigOK(t, config)
248
249 if params.mode != Argon2S2K {
250 t.Fatalf("Wrong mode, expected %d got %d", Argon2S2K, params.mode)
251 }
252 }
253
254 func testSerializeConfigOK(t *testing.T, c *Config) *Params {
255 buf := bytes.NewBuffer(nil)
256 key := make([]byte, 16)
257 passphrase := []byte("testing")
258 err := Serialize(buf, key, rand.Reader, passphrase, c)
259 if err != nil {
260 t.Fatalf("failed to serialize with config %+v: %s", c, err)
261 }
262
263 f, err := Parse(bytes.NewBuffer(buf.Bytes()))
264 if err != nil {
265 t.Fatalf("failed to reparse: %s", err)
266 }
267 key2 := make([]byte, len(key))
268 f(key2, passphrase)
269 if !bytes.Equal(key2, key) {
270 t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
271 }
272
273 params, err := ParseIntoParams(bytes.NewBuffer(buf.Bytes()))
274 if err != nil {
275 t.Fatalf("failed to parse params: %s", err)
276 }
277
278 return params
279 }
280
View as plain text