You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

234 line
8.4 KiB

  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. package argon2
  5. import (
  6. "bytes"
  7. "encoding/hex"
  8. "testing"
  9. )
  10. var (
  11. genKatPassword = []byte{
  12. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  13. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  14. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  15. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  16. }
  17. genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}
  18. genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}
  19. genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}
  20. )
  21. func TestArgon2(t *testing.T) {
  22. defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4)
  23. if useSSE4 {
  24. t.Log("SSE4.1 version")
  25. testArgon2i(t)
  26. testArgon2d(t)
  27. testArgon2id(t)
  28. useSSE4 = false
  29. }
  30. t.Log("generic version")
  31. testArgon2i(t)
  32. testArgon2d(t)
  33. testArgon2id(t)
  34. }
  35. func testArgon2d(t *testing.T) {
  36. want := []byte{
  37. 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97,
  38. 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94,
  39. 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1,
  40. 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb,
  41. }
  42. hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
  43. if !bytes.Equal(hash, want) {
  44. t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
  45. }
  46. }
  47. func testArgon2i(t *testing.T) {
  48. want := []byte{
  49. 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa,
  50. 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1,
  51. 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2,
  52. 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8,
  53. }
  54. hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
  55. if !bytes.Equal(hash, want) {
  56. t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
  57. }
  58. }
  59. func testArgon2id(t *testing.T) {
  60. want := []byte{
  61. 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
  62. 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
  63. 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
  64. 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59,
  65. }
  66. hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
  67. if !bytes.Equal(hash, want) {
  68. t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
  69. }
  70. }
  71. func TestVectors(t *testing.T) {
  72. password, salt := []byte("password"), []byte("somesalt")
  73. for i, v := range testVectors {
  74. want, err := hex.DecodeString(v.hash)
  75. if err != nil {
  76. t.Fatalf("Test %d: failed to decode hash: %v", i, err)
  77. }
  78. hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want)))
  79. if !bytes.Equal(hash, want) {
  80. t.Errorf("Test %d - got: %s want: %s", i, hex.EncodeToString(hash), hex.EncodeToString(want))
  81. }
  82. }
  83. }
  84. func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) {
  85. password := []byte("password")
  86. salt := []byte("choosing random salts is hard")
  87. b.ReportAllocs()
  88. for i := 0; i < b.N; i++ {
  89. deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen)
  90. }
  91. }
  92. func BenchmarkArgon2i(b *testing.B) {
  93. b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) })
  94. b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) })
  95. b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) })
  96. b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) })
  97. b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) })
  98. b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) })
  99. }
  100. func BenchmarkArgon2d(b *testing.B) {
  101. b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) })
  102. b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) })
  103. b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) })
  104. b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) })
  105. b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) })
  106. b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) })
  107. }
  108. func BenchmarkArgon2id(b *testing.B) {
  109. b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) })
  110. b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) })
  111. b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) })
  112. b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) })
  113. b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) })
  114. b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) })
  115. }
  116. // Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
  117. var testVectors = []struct {
  118. mode int
  119. time, memory uint32
  120. threads uint8
  121. hash string
  122. }{
  123. {
  124. mode: argon2i, time: 1, memory: 64, threads: 1,
  125. hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37",
  126. },
  127. {
  128. mode: argon2d, time: 1, memory: 64, threads: 1,
  129. hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19",
  130. },
  131. {
  132. mode: argon2id, time: 1, memory: 64, threads: 1,
  133. hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb",
  134. },
  135. {
  136. mode: argon2i, time: 2, memory: 64, threads: 1,
  137. hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64",
  138. },
  139. {
  140. mode: argon2d, time: 2, memory: 64, threads: 1,
  141. hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75",
  142. },
  143. {
  144. mode: argon2id, time: 2, memory: 64, threads: 1,
  145. hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7",
  146. },
  147. {
  148. mode: argon2i, time: 2, memory: 64, threads: 2,
  149. hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f",
  150. },
  151. {
  152. mode: argon2d, time: 2, memory: 64, threads: 2,
  153. hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9",
  154. },
  155. {
  156. mode: argon2id, time: 2, memory: 64, threads: 2,
  157. hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362",
  158. },
  159. {
  160. mode: argon2i, time: 3, memory: 256, threads: 2,
  161. hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6",
  162. },
  163. {
  164. mode: argon2d, time: 3, memory: 256, threads: 2,
  165. hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2",
  166. },
  167. {
  168. mode: argon2id, time: 3, memory: 256, threads: 2,
  169. hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b",
  170. },
  171. {
  172. mode: argon2i, time: 4, memory: 4096, threads: 4,
  173. hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7",
  174. },
  175. {
  176. mode: argon2d, time: 4, memory: 4096, threads: 4,
  177. hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d",
  178. },
  179. {
  180. mode: argon2id, time: 4, memory: 4096, threads: 4,
  181. hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a",
  182. },
  183. {
  184. mode: argon2i, time: 4, memory: 1024, threads: 8,
  185. hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17",
  186. },
  187. {
  188. mode: argon2d, time: 4, memory: 1024, threads: 8,
  189. hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9",
  190. },
  191. {
  192. mode: argon2id, time: 4, memory: 1024, threads: 8,
  193. hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f",
  194. },
  195. {
  196. mode: argon2i, time: 2, memory: 64, threads: 3,
  197. hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6",
  198. },
  199. {
  200. mode: argon2d, time: 2, memory: 64, threads: 3,
  201. hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51",
  202. },
  203. {
  204. mode: argon2id, time: 2, memory: 64, threads: 3,
  205. hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079",
  206. },
  207. {
  208. mode: argon2i, time: 3, memory: 1024, threads: 6,
  209. hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced",
  210. },
  211. {
  212. mode: argon2d, time: 3, memory: 1024, threads: 6,
  213. hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481",
  214. },
  215. {
  216. mode: argon2id, time: 3, memory: 1024, threads: 6,
  217. hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016",
  218. },
  219. }