storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/argon2/argon2_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package argon2 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 "testing" 11 ) 12 13 var ( 14 genKatPassword = []byte{ 15 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 16 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 17 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 18 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 19 } 20 genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} 21 genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03} 22 genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04} 23 ) 24 25 func TestArgon2(t *testing.T) { 26 defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4) 27 28 if useSSE4 { 29 t.Log("SSE4.1 version") 30 testArgon2i(t) 31 testArgon2d(t) 32 testArgon2id(t) 33 useSSE4 = false 34 } 35 t.Log("generic version") 36 testArgon2i(t) 37 testArgon2d(t) 38 testArgon2id(t) 39 } 40 41 func testArgon2d(t *testing.T) { 42 want := []byte{ 43 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, 44 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, 45 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, 46 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb, 47 } 48 hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) 49 if !bytes.Equal(hash, want) { 50 t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) 51 } 52 } 53 54 func testArgon2i(t *testing.T) { 55 want := []byte{ 56 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa, 57 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1, 58 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2, 59 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8, 60 } 61 hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) 62 if !bytes.Equal(hash, want) { 63 t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) 64 } 65 } 66 67 func testArgon2id(t *testing.T) { 68 want := []byte{ 69 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c, 70 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9, 71 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e, 72 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59, 73 } 74 hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) 75 if !bytes.Equal(hash, want) { 76 t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) 77 } 78 } 79 80 func TestVectorsIDKey(t *testing.T) { 81 password, salt := []byte("password"), []byte("somesalt") 82 for _, v := range testVectors { 83 v := v 84 t.Run("", func(t *testing.T) { 85 var fn func(password, salt, secret, data []byte, keyLen uint32) []byte 86 switch v.mode { 87 case argon2id: 88 fn = NewIDKey(v.time, v.memory, v.threads) 89 default: 90 t.Skip() 91 } 92 want, err := hex.DecodeString(v.hash) 93 if err != nil { 94 t.Fatalf("failed to decode hash: %v", err) 95 } 96 hash := fn(password, salt, nil, nil, uint32(len(want))) 97 if !bytes.Equal(hash, want) { 98 t.Errorf("got: %s want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) 99 } 100 }) 101 } 102 103 } 104 105 func TestVectors(t *testing.T) { 106 password, salt := []byte("password"), []byte("somesalt") 107 for _, v := range testVectors { 108 v := v 109 t.Run("", func(t *testing.T) { 110 want, err := hex.DecodeString(v.hash) 111 if err != nil { 112 t.Fatalf("failed to decode hash: %v", err) 113 } 114 hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want))) 115 if !bytes.Equal(hash, want) { 116 t.Errorf("got: %s want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) 117 } 118 }) 119 } 120 } 121 122 func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) { 123 password := []byte("password") 124 salt := []byte("choosing random salts is hard") 125 b.ReportAllocs() 126 for i := 0; i < b.N; i++ { 127 deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen) 128 } 129 } 130 131 func BenchmarkArgon2i(b *testing.B) { 132 b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) }) 133 b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) }) 134 b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) }) 135 b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) }) 136 b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) }) 137 b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) }) 138 } 139 140 func BenchmarkArgon2d(b *testing.B) { 141 b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) }) 142 b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) }) 143 b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) }) 144 b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) }) 145 b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) }) 146 b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) }) 147 } 148 149 func BenchmarkArgon2id(b *testing.B) { 150 b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) }) 151 b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) }) 152 b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) }) 153 b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) }) 154 b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) }) 155 b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) }) 156 } 157 158 func benchmarkArgon2idNew(time, memory uint32, threads uint8, keyLen uint32, b *testing.B) { 159 f := NewIDKey(time, memory, threads) 160 password := []byte("password") 161 salt := []byte("choosing random salts is hard") 162 b.ReportAllocs() 163 for i := 0; i < b.N; i++ { 164 _ = f(password, salt, nil, nil, keyLen) 165 } 166 } 167 168 func BenchmarkArgon2idNew(b *testing.B) { 169 b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2idNew(3, 32*1024, 1, 32, b) }) 170 b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2idNew(4, 32*1024, 1, 32, b) }) 171 b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2idNew(5, 32*1024, 1, 32, b) }) 172 b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2idNew(3, 64*1024, 4, 32, b) }) 173 b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2idNew(4, 64*1024, 4, 32, b) }) 174 b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2idNew(5, 64*1024, 4, 32, b) }) 175 } 176 177 // Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf 178 var testVectors = []struct { 179 mode int 180 time, memory uint32 181 threads uint8 182 hash string 183 }{ 184 { 185 mode: argon2i, time: 1, memory: 64, threads: 1, 186 hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37", 187 }, 188 { 189 mode: argon2d, time: 1, memory: 64, threads: 1, 190 hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19", 191 }, 192 { 193 mode: argon2id, time: 1, memory: 64, threads: 1, 194 hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb", 195 }, 196 { 197 mode: argon2i, time: 2, memory: 64, threads: 1, 198 hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64", 199 }, 200 { 201 mode: argon2d, time: 2, memory: 64, threads: 1, 202 hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75", 203 }, 204 { 205 mode: argon2id, time: 2, memory: 64, threads: 1, 206 hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7", 207 }, 208 { 209 mode: argon2i, time: 2, memory: 64, threads: 2, 210 hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f", 211 }, 212 { 213 mode: argon2d, time: 2, memory: 64, threads: 2, 214 hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9", 215 }, 216 { 217 mode: argon2id, time: 2, memory: 64, threads: 2, 218 hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362", 219 }, 220 { 221 mode: argon2i, time: 3, memory: 256, threads: 2, 222 hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6", 223 }, 224 { 225 mode: argon2d, time: 3, memory: 256, threads: 2, 226 hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2", 227 }, 228 { 229 mode: argon2id, time: 3, memory: 256, threads: 2, 230 hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b", 231 }, 232 { 233 mode: argon2i, time: 4, memory: 4096, threads: 4, 234 hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7", 235 }, 236 { 237 mode: argon2d, time: 4, memory: 4096, threads: 4, 238 hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d", 239 }, 240 { 241 mode: argon2id, time: 4, memory: 4096, threads: 4, 242 hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a", 243 }, 244 { 245 mode: argon2i, time: 4, memory: 1024, threads: 8, 246 hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17", 247 }, 248 { 249 mode: argon2d, time: 4, memory: 1024, threads: 8, 250 hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9", 251 }, 252 { 253 mode: argon2id, time: 4, memory: 1024, threads: 8, 254 hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f", 255 }, 256 { 257 mode: argon2i, time: 2, memory: 64, threads: 3, 258 hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6", 259 }, 260 { 261 mode: argon2d, time: 2, memory: 64, threads: 3, 262 hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51", 263 }, 264 { 265 mode: argon2id, time: 2, memory: 64, threads: 3, 266 hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079", 267 }, 268 { 269 mode: argon2i, time: 3, memory: 1024, threads: 6, 270 hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced", 271 }, 272 { 273 mode: argon2d, time: 3, memory: 1024, threads: 6, 274 hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481", 275 }, 276 { 277 mode: argon2id, time: 3, memory: 1024, threads: 6, 278 hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016", 279 }, 280 }