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  }