From 8cb5f668004eb76440a61275a6ff44d7761b3a46 Mon Sep 17 00:00:00 2001 From: Michael Gray Date: Sun, 17 May 2020 18:08:06 -0700 Subject: [PATCH 1/2] Added .vs directory to .gitignore. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5aeb8a5..1fc9b0a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ nuget.exe #*.sln #*.csproj #*.kproj -*.lock.json \ No newline at end of file +*.lock.json +*.vs From f7f2c225b04fcfacbb9d833e2e44b108062b4533 Mon Sep 17 00:00:00 2001 From: Michael Gray <58085604+michaeljgray-sfdc@users.noreply.github.com> Date: Sun, 17 May 2020 18:27:05 -0700 Subject: [PATCH 2/2] Added static encoding method to allow for stateless encoding directly from header parameters. Exposed the SaltLength as a public static readonly field to allow for callers to prepare a correctly sized buffer for the salt; it's not const anymore to ensure callers don't need to recompile all dependencies. Optimization added for salt buffer when using the default or constructor-specified salt generator. --- src/Scrypt/ScryptEncoder.cs | 51 +++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/Scrypt/ScryptEncoder.cs b/src/Scrypt/ScryptEncoder.cs index aea0094..22fae1e 100644 --- a/src/Scrypt/ScryptEncoder.cs +++ b/src/Scrypt/ScryptEncoder.cs @@ -41,7 +41,8 @@ public class ScryptEncoder /// /// Size of salt in bytes. /// - private const int SaltLength = 32; + public static readonly int SaltLength = 32; + private const int DefaultIterationCount = 16384; private const int DefaultBlockSize = 8; private const int DefaultThreadCount = 1; @@ -49,10 +50,13 @@ public class ScryptEncoder private readonly int _iterationCount; private readonly int _blockSize; private readonly int _threadCount; + private readonly byte[] _salt; private readonly RandomNumberGenerator _saltGenerator; #endregion + + #region Constructors /// @@ -94,6 +98,7 @@ public ScryptEncoder(int iterationCount, int blockSize, int threadCount, RandomN _iterationCount = iterationCount; _blockSize = blockSize; _threadCount = threadCount; + _salt = new byte[SaltLength]; _saltGenerator = saltGenerator; } @@ -147,11 +152,9 @@ public string Encode(string password) throw new ArgumentNullException("password"); } - var saltBytes = new byte[SaltLength]; + _saltGenerator.GetBytes(_salt); - _saltGenerator.GetBytes(saltBytes); - - return EncodeV2(password, saltBytes, _iterationCount, _blockSize, _threadCount); + return EncodeV2(password, _salt, _iterationCount, _blockSize, _threadCount); } /// @@ -196,6 +199,44 @@ public bool IsValid(string hashedPassword) return true; } + /// + /// Hashes a password using the scrypt scheme. + /// + public static string Encode(int iterationCount, int blockSize, int threadCount, byte[] salt, string password) + { + if (iterationCount < 1) + { + throw new ArgumentOutOfRangeException("iterationCount", "IterationCount must be equal or greater than 1."); + } + + if (blockSize < 1) + { + throw new ArgumentOutOfRangeException("blockSize", "BlockSize must be equal or greater than 1."); + } + + if (threadCount < 1) + { + throw new ArgumentOutOfRangeException("threadCount", "ThreadCount must be equal or greater than 1."); + } + + if (salt == null) + { + throw new ArgumentNullException("salt"); + } + + if (salt.Length != SaltLength) + { + throw new ArgumentOutOfRangeException("salt", String.Format("Salt length must be equal to {0} bytes.", SaltLength)); + } + + if (string.IsNullOrEmpty(password)) + { + throw new ArgumentNullException("password"); + } + + return EncodeV2(password, salt, iterationCount, blockSize, threadCount); + } + /// /// Hash a password using the scrypt scheme. ///