@@ -9,12 +9,6 @@ namespace CodeBeam.UltimateAuth.Tests.Unit;
99
1010public class Argon2PasswordHasherTests
1111{
12- private Argon2PasswordHasher CreateHasher ( )
13- {
14- var options = Options . Create ( new Argon2Options ( ) ) ;
15- return new Argon2PasswordHasher ( options ) ;
16- }
17-
1812 [ Fact ]
1913 public void Hash_Should_Return_Valid_PasswordHash ( )
2014 {
@@ -34,9 +28,7 @@ public void Hash_Should_Return_Valid_PasswordHash()
3428 public void Verify_Should_Return_True_For_Correct_Password ( )
3529 {
3630 var hasher = CreateHasher ( ) ;
37-
3831 var hash = hasher . Hash ( "password123" ) ;
39-
4032 var result = hasher . Verify ( hash , "password123" ) ;
4133
4234 result . Should ( ) . BeTrue ( ) ;
@@ -46,9 +38,7 @@ public void Verify_Should_Return_True_For_Correct_Password()
4638 public void Verify_Should_Return_False_For_Wrong_Password ( )
4739 {
4840 var hasher = CreateHasher ( ) ;
49-
5041 var hash = hasher . Hash ( "password123" ) ;
51-
5242 var result = hasher . Verify ( hash , "wrong" ) ;
5343
5444 result . Should ( ) . BeFalse ( ) ;
@@ -58,9 +48,7 @@ public void Verify_Should_Return_False_For_Wrong_Password()
5848 public void Verify_Should_Return_False_For_Invalid_Format ( )
5949 {
6050 var hasher = CreateHasher ( ) ;
61-
6251 var invalid = PasswordHash . Create ( PasswordAlgorithms . Argon2 , "invalid" ) ;
63-
6452 var result = hasher . Verify ( invalid , "password" ) ;
6553
6654 result . Should ( ) . BeFalse ( ) ;
@@ -89,7 +77,6 @@ public void Hash_Should_Produce_Different_Hashes_For_Same_Password()
8977 public void Verify_Should_Use_Embedded_Salt_And_Parameters ( )
9078 {
9179 var hasher = CreateHasher ( ) ;
92-
9380 var hash = hasher . Hash ( "password123" ) ;
9481
9582 var differentOptions = Options . Create ( new Argon2Options
@@ -112,7 +99,6 @@ public void Verify_Should_Use_Embedded_Salt_And_Parameters()
11299 public void NeedsRehash_Should_Return_True_When_Parameters_Changed ( )
113100 {
114101 var hasher = CreateHasher ( ) ;
115-
116102 var hash = hasher . Hash ( "password123" ) ;
117103
118104 var differentOptions = Options . Create ( new Argon2Options
@@ -135,11 +121,185 @@ public void NeedsRehash_Should_Return_True_When_Parameters_Changed()
135121 public void NeedsRehash_Should_Return_False_When_Parameters_Match ( )
136122 {
137123 var hasher = CreateHasher ( ) ;
124+ var hash = hasher . Hash ( "password123" ) ;
125+ var result = hasher . NeedsRehash ( hash ) ;
126+
127+ result . Should ( ) . BeFalse ( ) ;
128+ }
129+
130+ [ Theory ]
131+ [ InlineData ( "" ) ]
132+ [ InlineData ( null ) ]
133+ public void Hash_Should_Throw_When_Password_Is_Null_Or_Empty (
134+ string ? password )
135+ {
136+ var hasher = CreateHasher ( ) ;
137+ var act = ( ) => hasher . Hash ( password ! ) ;
138138
139+ act . Should ( ) . Throw < UAuthValidationException > ( ) ;
140+ }
141+
142+ [ Theory ]
143+ [ InlineData ( "" ) ]
144+ [ InlineData ( " " ) ]
145+ [ InlineData ( " " ) ]
146+ [ InlineData ( null ) ]
147+ public void Verify_Should_Return_False_When_Secret_Is_Invalid (
148+ string ? secret )
149+ {
150+ var hasher = CreateHasher ( ) ;
139151 var hash = hasher . Hash ( "password123" ) ;
152+ var result = hasher . Verify ( hash , secret ! ) ;
140153
141- var result = hasher . NeedsRehash ( hash ) ;
154+ result . Should ( ) . BeFalse ( ) ;
155+ }
156+
157+ [ Fact ]
158+ public void Verify_Should_Return_False_When_Algorithm_Is_Not_Argon2 ( )
159+ {
160+ var hasher = CreateHasher ( ) ;
161+
162+ var hash = PasswordHash . Create ( "different-algorithm" , "3.65536.1.c2FsdA==.aGFzaA==" ) ;
163+
164+ var result = hasher . Verify ( hash , "password123" ) ;
142165
143166 result . Should ( ) . BeFalse ( ) ;
144167 }
168+
169+ [ Theory ]
170+ [ InlineData ( "invalid.65536.1.c2FsdA==.aGFzaA==" ) ]
171+ [ InlineData ( "3.invalid.1.c2FsdA==.aGFzaA==" ) ]
172+ [ InlineData ( "3.65536.invalid.c2FsdA==.aGFzaA==" ) ]
173+ public void Verify_Should_Return_False_When_Parameters_Are_Invalid ( string encoded )
174+ {
175+ var hasher = CreateHasher ( ) ;
176+ var hash = PasswordHash . Create ( PasswordAlgorithms . Argon2 , encoded ) ;
177+ var result = hasher . Verify ( hash , "password123" ) ;
178+
179+ result . Should ( ) . BeFalse ( ) ;
180+ }
181+
182+ [ Theory ]
183+ [ InlineData ( "3.65536.1.NOT_BASE64.aGFzaA==" ) ]
184+ [ InlineData ( "3.65536.1.c2FsdA==.NOT_BASE64" ) ]
185+ public void Verify_Should_Return_False_When_Hash_Contains_Invalid_Base64 (
186+ string encoded )
187+ {
188+ var hasher = CreateHasher ( ) ;
189+ var hash = PasswordHash . Create ( PasswordAlgorithms . Argon2 , encoded ) ;
190+ var result = hasher . Verify ( hash , "password123" ) ;
191+
192+ result . Should ( ) . BeFalse ( ) ;
193+ }
194+
195+ [ Fact ]
196+ public void NeedsRehash_Should_Return_True_When_Algorithm_Is_Not_Argon2 ( )
197+ {
198+ var hasher = CreateHasher ( ) ;
199+ var hash = PasswordHash . Create ( "different-algorithm" , "anything" ) ;
200+
201+ hasher . NeedsRehash ( hash ) . Should ( ) . BeTrue ( ) ;
202+ }
203+
204+ [ Theory ]
205+ [ InlineData ( "invalid" ) ]
206+ [ InlineData ( "1.2.3" ) ]
207+ [ InlineData ( "1.2.3.4" ) ]
208+ [ InlineData ( "1.2.3.4.5.6" ) ]
209+ public void NeedsRehash_Should_Return_True_When_Format_Is_Invalid (
210+ string encoded )
211+ {
212+ var hasher = CreateHasher ( ) ;
213+
214+ var hash = PasswordHash . Create (
215+ PasswordAlgorithms . Argon2 ,
216+ encoded ) ;
217+
218+ hasher . NeedsRehash ( hash )
219+ . Should ( )
220+ . BeTrue ( ) ;
221+ }
222+
223+ [ Theory ]
224+ [ InlineData ( "invalid.65536.1.c2FsdA==.aGFzaA==" ) ]
225+ [ InlineData ( "3.invalid.1.c2FsdA==.aGFzaA==" ) ]
226+ [ InlineData ( "3.65536.invalid.c2FsdA==.aGFzaA==" ) ]
227+ public void NeedsRehash_Should_Return_True_When_Parameters_Are_Invalid (
228+ string encoded )
229+ {
230+ var hasher = CreateHasher ( ) ;
231+
232+ var hash = PasswordHash . Create (
233+ PasswordAlgorithms . Argon2 ,
234+ encoded ) ;
235+
236+ hasher . NeedsRehash ( hash )
237+ . Should ( )
238+ . BeTrue ( ) ;
239+ }
240+
241+ [ Fact ]
242+ public void NeedsRehash_Should_Return_True_When_Iterations_Changed ( )
243+ {
244+ var hasher = CreateHasher ( ) ;
245+ var hash = hasher . Hash ( "password123" ) ;
246+
247+ var differentHasher = CreateHasher ( new Argon2Options
248+ {
249+ Iterations = 4
250+ } ) ;
251+
252+ differentHasher . NeedsRehash ( hash )
253+ . Should ( )
254+ . BeTrue ( ) ;
255+ }
256+
257+ [ Fact ]
258+ public void NeedsRehash_Should_Return_True_When_Memory_Size_Changed ( )
259+ {
260+ var hasher = CreateHasher ( ) ;
261+ var hash = hasher . Hash ( "password123" ) ;
262+
263+ var differentHasher = CreateHasher ( new Argon2Options
264+ {
265+ MemorySizeKb = 32 * 1024
266+ } ) ;
267+
268+ differentHasher . NeedsRehash ( hash )
269+ . Should ( )
270+ . BeTrue ( ) ;
271+ }
272+
273+ [ Fact ]
274+ public void NeedsRehash_Should_Return_True_When_Parallelism_Changed ( )
275+ {
276+ var hasher = CreateHasher ( ) ;
277+ var hash = hasher . Hash ( "password123" ) ;
278+
279+ var differentParallelism =
280+ new Argon2Options ( ) . Parallelism == 1
281+ ? 2
282+ : 1 ;
283+
284+ var differentHasher = CreateHasher ( new Argon2Options
285+ {
286+ Parallelism = differentParallelism
287+ } ) ;
288+
289+ differentHasher . NeedsRehash ( hash )
290+ . Should ( )
291+ . BeTrue ( ) ;
292+ }
293+
294+ private static Argon2PasswordHasher CreateHasher ( )
295+ {
296+ return CreateHasher ( new Argon2Options ( ) ) ;
297+ }
298+
299+ private static Argon2PasswordHasher CreateHasher (
300+ Argon2Options options )
301+ {
302+ return new Argon2PasswordHasher (
303+ Options . Create ( options ) ) ;
304+ }
145305}
0 commit comments