Skip to content

Commit 8eefd66

Browse files
committed
Updated dependencies and tests. Added xml docs and symbols
1 parent d720309 commit 8eefd66

File tree

5 files changed

+114
-21
lines changed

5 files changed

+114
-21
lines changed

src/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.csproj

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<AssemblyName>ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher</AssemblyName>
66
<PackageId>ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher</PackageId>
7-
<PackageVersion>1.1.0</PackageVersion>
87
<Authors>Scott Brady</Authors>
98
<Description>ASP.NET Core Identity IPasswordHasher implementation using Scrypt</Description>
109
<Copyright>Copyright (c) 2017 Scott Brady</Copyright>
1110
<PackageTags>aspnetcore;identity;scrypt;password;hashing;hash;security</PackageTags>
1211
<PackageIconUrl>https://www.scottbrady91.com/img/logos/scottbrady91.png</PackageIconUrl>
1312
<PackageProjectUrl>https://github.com/scottbrady91/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher</PackageProjectUrl>
1413
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
14+
<IncludeSymbols>true</IncludeSymbols>
15+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
16+
<Version>1.3.0</Version>
1517
<PackageReleaseNotes>Updated ASP.NET Identity dependencies. Made methods virtual.</PackageReleaseNotes>
1618
</PropertyGroup>
1719

1820
<ItemGroup>
19-
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="2.0.0" />
2021
<PackageReference Include="Scrypt.NET" Version="1.3.0" />
22+
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="2.1.0" />
23+
<PackageReference Include="SecurityCodeScan" Version="3.5.4" PrivateAssets="all" />
2124
</ItemGroup>
2225

2326
</Project>

src/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher/ScryptPasswordHasher.cs

+27-3
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,51 @@
55

66
namespace ScottBrady91.AspNetCore.Identity
77
{
8+
/// <summary>
9+
/// ASP.NET Core Identity password hasher using the scrypt password hashing algorithm.
10+
/// </summary>
11+
/// <typeparam name="TUser">your ASP.NET Core Identity user type (e.g. IdentityUser). User is not used by this implementation</typeparam>
812
public class ScryptPasswordHasher<TUser> : IPasswordHasher<TUser> where TUser : class
913
{
1014
private readonly ScryptPasswordHasherOptions options;
1115

16+
/// <summary>
17+
/// Creates a new ScryptPasswordHasher.
18+
/// </summary>
19+
/// <param name="optionsAccessor">optional ScryptPasswordHasherOptions</param>
1220
public ScryptPasswordHasher(IOptions<ScryptPasswordHasherOptions> optionsAccessor = null)
1321
{
1422
options = optionsAccessor?.Value ?? new ScryptPasswordHasherOptions();
1523
}
1624

25+
/// <summary>
26+
/// Hashes a password using scrypt.
27+
/// </summary>
28+
/// <param name="user">not used for this implementation</param>
29+
/// <param name="password">plaintext password</param>
30+
/// <returns>hashed password</returns>
31+
/// <exception cref="ArgumentNullException">missing plaintext password</exception>
1732
public virtual string HashPassword(TUser user, string password)
1833
{
19-
if (password == null) throw new ArgumentNullException(nameof(password));
34+
if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException(nameof(password));
2035

2136
var encoder = new ScryptEncoder(options.IterationCount, options.BlockSize, options.ThreadCount);
2237
return encoder.Encode(password);
2338
}
2439

40+
/// <summary>
41+
/// Verifies a plaintext password against a stored hash.
42+
/// </summary>
43+
/// <param name="user">not used for this implementation</param>
44+
/// <param name="hashedPassword">the stored, hashed password</param>
45+
/// <param name="providedPassword">the plaintext password to verify against the stored hash</param>
46+
/// <returns>If the password matches the stored password</returns>
47+
/// <exception cref="ArgumentNullException">missing plaintext password or hashed password</exception>
48+
2549
public virtual PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
2650
{
27-
if (hashedPassword == null) throw new ArgumentNullException(nameof(hashedPassword));
28-
if (providedPassword == null) throw new ArgumentNullException(nameof(providedPassword));
51+
if (string.IsNullOrWhiteSpace(hashedPassword)) throw new ArgumentNullException(nameof(hashedPassword));
52+
if (string.IsNullOrWhiteSpace(providedPassword)) throw new ArgumentNullException(nameof(providedPassword));
2953

3054
var encoder = new ScryptEncoder();
3155
var isValid = encoder.Compare(providedPassword, hashedPassword);

src/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher/ScryptPasswordHasherOptions.cs

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
namespace ScottBrady91.AspNetCore.Identity
22
{
3+
/// <summary>
4+
/// Options for ScryptPasswordHasher.
5+
/// </summary>
36
public class ScryptPasswordHasherOptions
47
{
58
public int IterationCount { get; set; } = 16384;

test/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.Tests/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.Tests.csproj

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1;netcoreapp2.2;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="FluentAssertions" Version="5.6.0" />
8+
<PackageReference Include="FluentAssertions" Version="5.10.3" />
9+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
910
<PackageReference Include="xunit" Version="2.4.1" />
10-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
11+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
1112
<PrivateAssets>all</PrivateAssets>
12-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
1314
</PackageReference>
1415
</ItemGroup>
1516

17+
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
18+
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="2.1.6" />
19+
</ItemGroup>
20+
21+
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
22+
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="3.1.12" />
23+
</ItemGroup>
24+
25+
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
26+
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="5.0.1" />
27+
</ItemGroup>
28+
1629
<ItemGroup>
1730
<ProjectReference Include="..\..\src\ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher\ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.csproj" />
1831
</ItemGroup>

test/ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.Tests/ScryptPasswordHasherTests.cs

+62-12
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,46 @@ namespace ScottBrady91.AspNetCore.Identity.ScryptPasswordHasher.Tests
99
{
1010
public class ScryptPasswordHasherTests
1111
{
12+
private ScryptPasswordHasherOptions options = new ScryptPasswordHasherOptions();
13+
14+
private ScryptPasswordHasher<string> CreateSut() =>
15+
new ScryptPasswordHasher<string>(
16+
options != null ? new OptionsWrapper<ScryptPasswordHasherOptions>(options) : null);
17+
18+
[Theory]
19+
[InlineData(null)]
20+
[InlineData("")]
21+
[InlineData(" ")]
22+
public void HashPassword_WhenPasswordIsNullOrWhitespace_ExpectArgumentNullException(string password)
23+
{
24+
var sut = CreateSut();
25+
Assert.Throws<ArgumentNullException>(() => sut.HashPassword(null, password));
26+
}
27+
1228
[Fact]
1329
public void HashPassword_WithDefaultSettings_ExpectVerifiableHash()
1430
{
1531
var password = Guid.NewGuid().ToString();
1632

17-
var hasher = new ScryptPasswordHasher<string>();
18-
var hashedPassword = hasher.HashPassword("", password);
33+
var sut = CreateSut();
34+
var hashedPassword = sut.HashPassword("", password);
1935

2036
var encoder = new ScryptEncoder();
2137
encoder.Compare(password, hashedPassword).Should().BeTrue();
2238
}
2339

40+
[Fact]
41+
public void HashPassword_WhenCalledMultipleTimesWithSamePlaintext_ExpectDifferentHash()
42+
{
43+
var password = Guid.NewGuid().ToString();
44+
45+
var sut = CreateSut();
46+
var hashedPassword1 = sut.HashPassword("", password);
47+
var hashedPassword2 = sut.HashPassword("", password);
48+
49+
hashedPassword1.Should().NotBe(hashedPassword2);
50+
}
51+
2452
[Fact]
2553
public void HashPassword_WithCustomSettings_ExpectVerifiableHash()
2654
{
@@ -31,14 +59,36 @@ public void HashPassword_WithCustomSettings_ExpectVerifiableHash()
3159

3260
var password = Guid.NewGuid().ToString();
3361

34-
var hasher = new ScryptPasswordHasher<string>(
35-
new OptionsWrapper<ScryptPasswordHasherOptions>(
36-
new ScryptPasswordHasherOptions {IterationCount = iterationCount, BlockSize = blockSize, ThreadCount = threadCount}));
37-
var hashedPassword = hasher.HashPassword("", password);
62+
options.IterationCount = iterationCount;
63+
options.BlockSize = blockSize;
64+
options.ThreadCount = threadCount;
65+
var sut = CreateSut();
66+
67+
var hashedPassword = sut.HashPassword("", password);
3868

3969
var encoder = new ScryptEncoder();
4070
encoder.Compare(password, hashedPassword).Should().BeTrue();
4171
}
72+
73+
[Theory]
74+
[InlineData(null)]
75+
[InlineData("")]
76+
[InlineData(" ")]
77+
public void VerifyHashedPassword_WhenHashedPasswordIsNullOrWhitespace_ExpectArgumentNullException(string hashedPassword)
78+
{
79+
var sut = CreateSut();
80+
Assert.Throws<ArgumentNullException>(() => sut.VerifyHashedPassword(null, hashedPassword, Guid.NewGuid().ToString()));
81+
}
82+
83+
[Theory]
84+
[InlineData(null)]
85+
[InlineData("")]
86+
[InlineData(" ")]
87+
public void VerifyHashedPassword_WhenPasswordIsNullOrWhitespace_ExpectArgumentNullException(string password)
88+
{
89+
var sut = CreateSut();
90+
Assert.Throws<ArgumentNullException>(() => sut.VerifyHashedPassword(null, Guid.NewGuid().ToString(), password));
91+
}
4292

4393
[Fact]
4494
public void VerifyHashedPassword_WithDefaultSettings_ExpectSuccess()
@@ -47,9 +97,9 @@ public void VerifyHashedPassword_WithDefaultSettings_ExpectSuccess()
4797
var encoder = new ScryptEncoder();
4898
var hashedPassword = encoder.Encode(password);
4999

50-
var hasher = new ScryptPasswordHasher<string>();
100+
var sut = CreateSut();
51101

52-
hasher.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Success);
102+
sut.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Success);
53103
}
54104

55105
[Fact]
@@ -64,9 +114,9 @@ public void VerifyHashedPassword_WithCustomSettings_ExpectSuccess()
64114
var encoder = new ScryptEncoder(iterationCount, blockSize, threadCount);
65115
var hashedPassword = encoder.Encode(password);
66116

67-
var hasher = new ScryptPasswordHasher<string>();
117+
var sut = CreateSut();
68118

69-
hasher.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Success);
119+
sut.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Success);
70120
}
71121

72122
[Fact]
@@ -76,9 +126,9 @@ public void VerifyHashedPassword_WhenSuppliedPasswordDoesNotMatch_ExpectFailure(
76126
var encoder = new ScryptEncoder();
77127
var hashedPassword = encoder.Encode(Guid.NewGuid().ToString());
78128

79-
var hasher = new ScryptPasswordHasher<string>();
129+
var sut = CreateSut();
80130

81-
hasher.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Failed);
131+
sut.VerifyHashedPassword("", hashedPassword, password).Should().Be(PasswordVerificationResult.Failed);
82132
}
83133
}
84134
}

0 commit comments

Comments
 (0)