From 5d51e97c52b1cc05426c5b323d08bbc7beb416c9 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 24 May 2020 18:45:30 -0700 Subject: [PATCH] Updates Argon2 to use Spans/Stackalloc (#140) --- Projects/Argon2/Argon2.cs | 120 ++++++------- Projects/Argon2/Argon2.csproj | 4 +- Projects/Argon2/Argon2.nuspec | 6 +- Projects/Argon2/Argon2Context.cs | 5 +- Projects/Argon2/Argon2Error.cs | 7 +- Projects/Argon2/Argon2Exception.cs | 4 +- Projects/Argon2/Argon2PasswordHasher.cs | 164 ++++-------------- Projects/Argon2/Argon2Type.cs | 2 +- Projects/Argon2/HashMetadata.cs | 2 +- Projects/Argon2/Utility.cs | 13 -- Projects/Server/Server.csproj | 2 +- .../Security/Argon2PasswordProtection.cs | 2 + Projects/UOContent/UOContent.csproj | 2 +- Tools/build-native-libraries.cmd | 10 +- Tools/publish.cmd | 2 +- 15 files changed, 115 insertions(+), 230 deletions(-) delete mode 100644 Projects/Argon2/Utility.cs diff --git a/Projects/Argon2/Argon2.cs b/Projects/Argon2/Argon2.cs index e13789e04..5745dc49e 100644 --- a/Projects/Argon2/Argon2.cs +++ b/Projects/Argon2/Argon2.cs @@ -1,127 +1,111 @@ using System.Runtime.InteropServices; -using System.Text; -namespace Server.Accounting.Security +namespace System.Security.Cryptography { internal interface IArgon2 { public Argon2Error Hash(uint t_cost, uint m_cost, uint parallelism, - byte[] pwd, - byte[] salt, - byte[] hash, - byte[] encoded, + ReadOnlySpan pwd, + ReadOnlySpan salt, + Span hash, + Span encoded, int type, int version); - Argon2Error Verify(byte[] encoded, byte[] pwd, int pwdlen, int type); + Argon2Error Verify(ReadOnlySpan encoded, ReadOnlySpan pwd, int pwdlen, int type); // TODO: Change str to use ReadOnlySpan then convert to pointer later - Argon2Error Decode(Argon2Context ctx, string str, int type); + Argon2Error Decode(Argon2Context ctx, ReadOnlySpan str, int type); } internal static class Argon2 { - internal static readonly IArgon2 Library; + internal static readonly bool IsDarwin = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + internal static readonly bool IsFreeBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); + internal static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - static Argon2() - { - if (RuntimeUtility.IsUnix) - Library = new UnixArgon2(); - else - Library = new WindowsArgon2(); - } + internal static readonly IArgon2 Library = + IsLinux || IsFreeBSD || IsDarwin ? (IArgon2)new UnixArgon2() : new WindowsArgon2(); } internal class WindowsArgon2 : IArgon2 { public Argon2Error Hash(uint t_cost, uint m_cost, uint parallelism, - byte[] pwd, - byte[] salt, - byte[] hash, - byte[] encoded, + ReadOnlySpan pwd, + ReadOnlySpan salt, + Span hash, + Span encoded, int type, int version) => - NativeMethods.crypto_argon2_hash(t_cost, m_cost, parallelism, - pwd, pwd.Length, - salt, salt.Length, - hash, hash.Length, - encoded, encoded.Length, + SafeNativeMethods.crypto_argon2_hash(t_cost, m_cost, parallelism, + in pwd.GetPinnableReference(), pwd.Length, + in salt.GetPinnableReference(), salt.Length, + ref hash.GetPinnableReference(), hash.Length, + ref encoded.GetPinnableReference(), encoded.Length, type, version ); - public Argon2Error Verify(byte[] encoded, byte[] pwd, int pwdlen, int type) => - NativeMethods.crypto_argon2_verify(encoded, pwd, pwdlen, type); + public Argon2Error Verify(ReadOnlySpan encoded, ReadOnlySpan pwd, int pwdlen, int type) => + SafeNativeMethods.crypto_argon2_verify(in encoded.GetPinnableReference(), in pwd.GetPinnableReference(), pwdlen, type); - public Argon2Error Decode(Argon2Context ctx, string str, int type) - { - byte[] bytes = new byte[str.Length]; - Encoding.ASCII.GetBytes(str, bytes); + public Argon2Error Decode(Argon2Context ctx, ReadOnlySpan str, int type) => + SafeNativeMethods.crypto_decode_string(ctx, in str.GetPinnableReference(), type); - // TODO: Use pointers instead - return NativeMethods.crypto_decode_string(ctx, bytes, type); - } - - internal static class NativeMethods + internal static class SafeNativeMethods { [DllImport("argon2.dll", EntryPoint = "crypto_argon2_hash", CallingConvention = CallingConvention.Cdecl)] internal static extern Argon2Error crypto_argon2_hash(uint t_cost, uint m_cost, uint parallelism, - byte[] pwd, int pwdlen, - byte[] salt, int saltlen, - byte[] hash, int hashlen, - byte[] encoded, int encodedlen, + in byte pwd, int pwdlen, + in byte salt, int saltlen, + ref byte hash, int hashlen, + ref byte encoded, int encodedlen, int type, int version ); [DllImport("argon2.dll", EntryPoint = "crypto_argon2_verify", CallingConvention = CallingConvention.Cdecl)] - internal static extern Argon2Error crypto_argon2_verify(byte[] encoded, byte[] pwd, int pwdlen, int type); + internal static extern Argon2Error crypto_argon2_verify(in byte encoded, in byte pwd, int pwdlen, int type); [DllImport("argon2.dll", EntryPoint = "crypto_decode_string", CallingConvention = CallingConvention.Cdecl)] - internal static extern Argon2Error crypto_decode_string(Argon2Context ctx, byte[] str, int type); + internal static extern Argon2Error crypto_decode_string(Argon2Context ctx, in byte str, int type); } } internal class UnixArgon2 : IArgon2 { public Argon2Error Hash(uint t_cost, uint m_cost, uint parallelism, - byte[] pwd, - byte[] salt, - byte[] hash, - byte[] encoded, + ReadOnlySpan pwd, + ReadOnlySpan salt, + Span hash, + Span encoded, int type, int version) => - NativeMethods.crypto_argon2_hash(t_cost, m_cost, parallelism, - pwd, pwd.Length, - salt, salt.Length, - hash, hash.Length, - encoded, encoded.Length, + SafeNativeMethods.crypto_argon2_hash(t_cost, m_cost, parallelism, + in pwd.GetPinnableReference(), pwd.Length, + in salt.GetPinnableReference(), salt.Length, + ref hash.GetPinnableReference(), hash.Length, + ref encoded.GetPinnableReference(), encoded.Length, type, version ); - public Argon2Error Verify(byte[] encoded, byte[] pwd, int pwdlen, int type) => - NativeMethods.crypto_argon2_verify(encoded, pwd, pwdlen, type); + public Argon2Error Verify(ReadOnlySpan encoded, ReadOnlySpan pwd, int pwdlen, int type) => + SafeNativeMethods.crypto_argon2_verify(in encoded.GetPinnableReference(), in pwd.GetPinnableReference(), pwdlen, type); - public Argon2Error Decode(Argon2Context ctx, string str, int type) - { - byte[] bytes = new byte[str.Length]; - Encoding.ASCII.GetBytes(str, bytes); + public Argon2Error Decode(Argon2Context ctx, ReadOnlySpan str, int type) => + SafeNativeMethods.crypto_decode_string(ctx, in str.GetPinnableReference(), type); - // TODO: Use pointers instead - return NativeMethods.crypto_decode_string(ctx, bytes, type); - } - - internal static class NativeMethods + internal static class SafeNativeMethods { [DllImport("libargon2", EntryPoint = "argon2_hash")] internal static extern Argon2Error crypto_argon2_hash(uint t_cost, uint m_cost, uint parallelism, - byte[] pwd, int pwdlen, - byte[] salt, int saltlen, - byte[] hash, int hashlen, - byte[] encoded, int encodedlen, + in byte pwd, int pwdlen, + in byte salt, int saltlen, + ref byte hash, int hashlen, + ref byte encoded, int encodedlen, int type, int version ); [DllImport("libargon2", EntryPoint = "argon2_verify")] - internal static extern Argon2Error crypto_argon2_verify(byte[] encoded, byte[] pwd, int pwdlen, int type); + internal static extern unsafe Argon2Error crypto_argon2_verify(in byte encoded, in byte pwd, int pwdlen, int type); [DllImport("libargon2", EntryPoint = "decode_string")] - internal static extern Argon2Error crypto_decode_string(Argon2Context ctx, byte[] str, int type); + internal static extern unsafe Argon2Error crypto_decode_string(Argon2Context ctx, in byte str, int type); } } } diff --git a/Projects/Argon2/Argon2.csproj b/Projects/Argon2/Argon2.csproj index 6fb0b3db8..ac800bb99 100644 --- a/Projects/Argon2/Argon2.csproj +++ b/Projects/Argon2/Argon2.csproj @@ -1,7 +1,7 @@  win-x64;linux-x64;osx-x64 - 1.1.0 + 1.1.8 Server Argon2.Bindings x64 @@ -12,7 +12,7 @@ false false Debug;Release;Analyze - 1.0.0 + 1.1.8 x64 diff --git a/Projects/Argon2/Argon2.nuspec b/Projects/Argon2/Argon2.nuspec index d4f061905..b28f90859 100644 --- a/Projects/Argon2/Argon2.nuspec +++ b/Projects/Argon2/Argon2.nuspec @@ -1,15 +1,15 @@ - + Argon2.Bindings - 1.0.0 + 1.1.6 Kamron Batman Kamron Batman MIT https://github.com/modernUO/ModernUO false Argon2 C# Bindings for ModernUO - Initial release + Updated to use spans/pointers Copyright 2020 diff --git a/Projects/Argon2/Argon2Context.cs b/Projects/Argon2/Argon2Context.cs index 302e1cca2..25a5b030e 100644 --- a/Projects/Argon2/Argon2Context.cs +++ b/Projects/Argon2/Argon2Context.cs @@ -1,7 +1,6 @@ -using System; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; -namespace Server.Accounting.Security +namespace System.Security.Cryptography { [StructLayout(LayoutKind.Sequential)] internal class Argon2Context diff --git a/Projects/Argon2/Argon2Error.cs b/Projects/Argon2/Argon2Error.cs index 4509170ff..42ebcca6e 100644 --- a/Projects/Argon2/Argon2Error.cs +++ b/Projects/Argon2/Argon2Error.cs @@ -1,4 +1,4 @@ -namespace Server.Accounting.Security +namespace System.Security.Cryptography { /// /// An enumeration of the possible error codes which are returned from Daniel Dinu and @@ -23,6 +23,11 @@ /// SALT_TOO_SHORT = -6, + /// + /// The salt is too big + /// + SALT_TOO_LONG = -7, + /// /// The time cost is less than 1 /// diff --git a/Projects/Argon2/Argon2Exception.cs b/Projects/Argon2/Argon2Exception.cs index f511ead78..c65a414cb 100644 --- a/Projects/Argon2/Argon2Exception.cs +++ b/Projects/Argon2/Argon2Exception.cs @@ -1,6 +1,4 @@ -using System; - -namespace Server.Accounting.Security +namespace System.Security.Cryptography { /// /// An exception class to wrap the errors returned by Daniel Dinu and Dmitry Khovratovich's Argon2 library. diff --git a/Projects/Argon2/Argon2PasswordHasher.cs b/Projects/Argon2/Argon2PasswordHasher.cs index 75f1f2d42..3970207e6 100644 --- a/Projects/Argon2/Argon2PasswordHasher.cs +++ b/Projects/Argon2/Argon2PasswordHasher.cs @@ -1,10 +1,8 @@ -using System; using System.Runtime.InteropServices; -using System.Security.Cryptography; using System.Text; // using System.Text.RegularExpressions; -namespace Server.Accounting.Security +namespace System.Security.Cryptography { /// /// PasswordHasher is a class for creating Argon2 hashes and verifying them. This is a wrapper around @@ -93,39 +91,11 @@ namespace Server.Accounting.Security /// A string representing the password to be hashed. The password is first decoded into bytes using StringEncoding (default: Encoding.UTF8) /// A formatted string representing the hashed password, encoded with the parameters used to perform the hash /// - public string Hash(string password) + public string Hash(ReadOnlySpan password) { - CheckNull("Hash", "password", password); - - return Hash(StringEncoding.GetBytes(password)); - } - - /// - /// Hash the raw password bytes using Argon2 with a cryptographically-secure, random, 16-byte salt. - /// Do not compare two Argon2 hashes directly. Instead, use the Verify or VerifyAndUpdate methods. - /// The raw bytes of the password to be hashed - /// A formatted string representing the hashed password, encoded with the parameters used to perform the hash - /// - public string Hash(byte[] password) - { - CheckNull("Hash", "password", password); - - return Hash(password, GenerateSalt()); - } - - /// - /// Hash the password using Argon2 with the specified salt. - /// Unless you need to specify your own salt for interoperability purposes, prefer the Hash(string password) overload instead. - /// Do not compare two Argon2 hashes directly. Instead, use the Verify or VerifyAndUpdate methods. - /// A string representing the password to be hashed. The password is first decoded into bytes using StringEncoding (default: Encoding.UTF8) - /// A string representing the salt to be used for the hash. The salt must be at least 8 bytes. The salt is first decoded into bytes using StringEncoding (default: Encoding.UTF8) - /// A formatted string representing the hashed password, encoded with the parameters used to perform the hash - /// - public string Hash(string password, string salt) - { - CheckNull("Hash", "password", password, "salt", salt); - - return Hash(StringEncoding.GetBytes(password), StringEncoding.GetBytes(salt)); + Span salt = stackalloc byte[16]; + Rng.GetBytes(salt); + return Hash(password, salt); } /// @@ -136,17 +106,18 @@ namespace Server.Accounting.Security /// The raw salt bytes to be used for the hash. The salt must be at least 8 bytes. /// A formatted string representing the hashed password, encoded with the parameters used to perform the hash /// - public string Hash(byte[] password, byte[] salt) + public string Hash(ReadOnlySpan password, ReadOnlySpan salt) { - CheckNull("Hash", "password", password, "salt", salt); + Span hash = stackalloc byte[(int)HashLength]; + Span encoded = stackalloc byte[(int)(39 + ((HashLength + salt.Length) * 4 + 3) / 3)]; + Span passwordBytes = stackalloc byte[StringEncoding.GetByteCount(password)]; + StringEncoding.GetBytes(password, passwordBytes); - byte[] hash = new byte[HashLength]; - byte[] encoded = new byte[39 + ((HashLength + salt.Length) * 4 + 3) / 3]; var result = Argon2.Library.Hash( TimeCost, MemoryCost, Parallelism, - password, + passwordBytes, salt, hash, encoded, @@ -161,22 +132,7 @@ namespace Server.Accounting.Security while (encoded[firstNonNull] == 0) firstNonNull--; - return Encoding.ASCII.GetString(encoded, 0, firstNonNull + 1); - } - - - /// - /// Hash the password using Argon2 with the specified salt. The HashRaw methods may be used for password-based key derivation. - /// Unless you're using HashRaw for key deriviation or for interoperability purposes, the Hash methods should be used in favor of the HashRaw methods. - /// A string representing the password to be hashed. The password is first decoded into bytes using StringEncoding (default: Encoding.UTF8) - /// A string representing the salt to be used for the hash. The salt must be at least 8 bytes. The salt is first decoded into bytes using StringEncoding (default: Encoding.UTF8) - /// A byte array containing only the resulting hash - /// - public byte[] HashRaw(string password, string salt) - { - CheckNull("HashRaw", "password", password, "salt", salt); - - return HashRaw(StringEncoding.GetBytes(password), StringEncoding.GetBytes(salt)); + return Encoding.ASCII.GetString(encoded.Slice(0, firstNonNull + 1)); } /// @@ -186,15 +142,16 @@ namespace Server.Accounting.Security /// The raw salt bytes to be used for the hash. The salt must be at least 8 bytes. /// A byte array containing only the resulting hash /// - public byte[] HashRaw(byte[] password, byte[] salt) + public void HashRaw(ReadOnlySpan password, ReadOnlySpan salt, Span hash) { - byte[] hash = new byte[(int)HashLength]; + Span passwordBytes = stackalloc byte[StringEncoding.GetByteCount(password)]; + StringEncoding.GetBytes(password, passwordBytes); var result = Argon2.Library.Hash( TimeCost, MemoryCost, Parallelism, - password, + passwordBytes, salt, hash, null, @@ -204,8 +161,6 @@ namespace Server.Accounting.Security if (result != Argon2Error.OK) throw new Argon2Exception("raw hashing", result); - - return hash; } @@ -217,11 +172,13 @@ namespace Server.Accounting.Security /// The password to hash and compare its result to expectedHash. The password is first decoded into bytes using StringEncoding (default: Encoding.UTF8) /// Whether the password results in the expectedHash when hashed /// - public bool Verify(string expectedHash, string password) + public bool Verify(ReadOnlySpan expectedHash, ReadOnlySpan password) { - CheckNull("Verify", "expectedHash", expectedHash, "password", password); - - return Verify(expectedHash, StringEncoding.GetBytes(password)); + Span expectedHashBytes = stackalloc byte[StringEncoding.GetByteCount(expectedHash)]; + StringEncoding.GetBytes(expectedHash, expectedHashBytes); + Span passwordBytes = stackalloc byte[StringEncoding.GetByteCount(password)]; + StringEncoding.GetBytes(password, passwordBytes); + return Verify(expectedHashBytes, passwordBytes); } /// @@ -232,11 +189,9 @@ namespace Server.Accounting.Security /// The raw password bytes to hash and compare its result to expectedHash /// Whether the password results in the expectedHash when hashed /// - public bool Verify(string expectedHash, byte[] password) + public bool Verify(ReadOnlySpan expectedHash, ReadOnlySpan password) { - CheckNull("Verify", "expectedHash", expectedHash, "password", password); - - var result = Argon2.Library.Verify(StringEncoding.GetBytes(expectedHash), password, password.Length, (int)ArgonType); + var result = Argon2.Library.Verify(expectedHash, password, password.Length, (int)ArgonType); if (result == Argon2Error.OK || result == Argon2Error.VERIFY_MISMATCH || result == Argon2Error.DECODING_FAIL) return result == Argon2Error.OK; @@ -244,26 +199,6 @@ namespace Server.Accounting.Security throw new Argon2Exception("verifying", result); } - - - /// - /// Hashes the password and verifies that the password results in the specified hash. (See Verify method) - /// If the password verification is successful, this method checks to see if the memory cost, time cost, and parallelism - /// match the parameters the PasswordHasher object was constructed with. If they do not much, then the password is rehashed - /// using the new parameters and the result is outputted via the newFormattedHash parameter. - /// Hashing the password should result in this hash - /// The password to hash and compare its result to expectedHash. The password is first decoded into bytes using StringEncoding (default: Encoding.UTF8) - /// Whether the cost parameters of expectedHash differ from the PasswordHasher object and if the password was rehashed using th new parameters. This is always false if the password was incorrect. - /// If isUpdated is true, then newFormattedHash is the password hashed with the new cost parameters. If isUpdated is false, then newFormattedHash is expectedHash. - /// Whether the password results in the expectedHash when hashed - /// - public bool VerifyAndUpdate(string expectedHash, string password, out bool isUpdated, out string newFormattedHash) - { - CheckNull("VerifyAndUpdate", "expectedHash", expectedHash, "password", password); - - return VerifyAndUpdate(expectedHash, StringEncoding.GetBytes(password), out isUpdated, out newFormattedHash); - } - /// /// Hashes the password and verifies that the password results in the specified hash. (See Verify method) /// If the password verification is successful, this method checks to see if the memory cost, time cost, and parallelism @@ -275,11 +210,11 @@ namespace Server.Accounting.Security /// If isUpdated is true, then newFormattedHash is the password hashed with the new cost parameters. If isUpdated is false, then newFormattedHash is expectedHash. /// Whether the password results in the expectedHash when hashed /// - public bool VerifyAndUpdate(string expectedHash, byte[] password, out bool isUpdated, out string newFormattedHash) + public bool VerifyAndUpdate(ReadOnlySpan expectedHash, ReadOnlySpan password, out bool isUpdated, out string newFormattedHash) { - CheckNull("VerifyAndUpdate", "expectedHash", expectedHash, "password", password); + bool verified = Verify(expectedHash, password); - if (Verify(expectedHash, password)) + if (verified) { var hashMetadata = ExtractMetadata(expectedHash); @@ -288,44 +223,22 @@ namespace Server.Accounting.Security isUpdated = true; byte[] salt = hashMetadata.Salt; newFormattedHash = Hash(password, salt); + return true; } - else - { - isUpdated = false; - newFormattedHash = expectedHash; - } - - return true; } isUpdated = false; - newFormattedHash = expectedHash; - return false; + newFormattedHash = expectedHash.ToString(); + return verified; } - - /// - /// Generate salt using a Cryptographically-Secure Pseudo-Random Number Generator - /// The number of bytes of salt to generate (default: 16) - /// A array of randomly-generated bytes - /// - public static byte[] GenerateSalt(uint byteLength = 16) - { - var salt = new byte[byteLength]; - Rng.GetBytes(salt); - return salt; - } - - /// /// Extracts the memory cost, time cost, etc. used to generate the Argon2 hash. /// An encoded Argon2 hash created by the Hash method /// The hash metadata or null if the formattedHash was not a valid encoded Argon2 hash /// - public static HashMetadata ExtractMetadata(string formattedHash) + public static HashMetadata ExtractMetadata(ReadOnlySpan formattedHash) { - CheckNull("ExtractMetadata", "formattedHash", formattedHash); - var context = new Argon2Context { Out = Marshal.AllocHGlobal(formattedHash.Length), // ensure the space to hold the hash is long enough @@ -347,7 +260,12 @@ namespace Server.Accounting.Security try { var type = formattedHash.StartsWith("$argon2i") ? Argon2Type.Argon2i : Argon2Type.Argon2d; - var result = Argon2.Library.Decode(context, $"{formattedHash}\0", (int)type); + formattedHash = $"{formattedHash.ToString()}\0"; + + Span bytes = stackalloc byte[formattedHash.Length]; + Encoding.ASCII.GetBytes(formattedHash, bytes); + + var result = Argon2.Library.Decode(context, bytes, (int)type); if (result != Argon2Error.OK) return null; @@ -376,13 +294,5 @@ namespace Server.Accounting.Security Marshal.FreeHGlobal(context.AssocData); } } - - - private static void CheckNull(string methodName, params object[] arguments) - { - for (var i = 0; i < arguments.Length; i += 2) - if (arguments[i + 1] == null) - throw new ArgumentNullException(arguments[i].ToString(), string.Format("Argument {0} to method PasswordHasher.{1} is null", arguments[i], methodName)); - } } } diff --git a/Projects/Argon2/Argon2Type.cs b/Projects/Argon2/Argon2Type.cs index dd24c27a5..3195a90f9 100644 --- a/Projects/Argon2/Argon2Type.cs +++ b/Projects/Argon2/Argon2Type.cs @@ -1,4 +1,4 @@ -namespace Server.Accounting.Security +namespace System.Security.Cryptography { /// /// The type of Argon2 hashing algorithm to use. diff --git a/Projects/Argon2/HashMetadata.cs b/Projects/Argon2/HashMetadata.cs index ba1758515..4ff264952 100644 --- a/Projects/Argon2/HashMetadata.cs +++ b/Projects/Argon2/HashMetadata.cs @@ -1,6 +1,6 @@ using System; -namespace Server.Accounting.Security +namespace System.Security.Cryptography { /// /// HashMetadata represents the information stored in the encoded Argon2 format diff --git a/Projects/Argon2/Utility.cs b/Projects/Argon2/Utility.cs deleted file mode 100644 index b450eb6da..000000000 --- a/Projects/Argon2/Utility.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Server -{ - internal static class RuntimeUtility - { - internal static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - internal static readonly bool IsDarwin = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); - internal static readonly bool IsFreeBSD = RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD); - internal static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || IsFreeBSD; - internal static readonly bool IsUnix = IsDarwin || IsFreeBSD || IsLinux; - } -} diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index 47482c0be..7326a34cc 100644 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -79,7 +79,7 @@ - + diff --git a/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs b/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs index c6fef378b..2b99b0cd3 100644 --- a/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs @@ -19,6 +19,8 @@ * along with this program. If not, see . * *************************************************************************/ +using System.Security.Cryptography; + namespace Server.Accounting.Security { public class Argon2PasswordProtection : IPasswordProtection diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj index c7c689fa7..3469a23dd 100644 --- a/Projects/UOContent/UOContent.csproj +++ b/Projects/UOContent/UOContent.csproj @@ -80,7 +80,7 @@ - + diff --git a/Tools/build-native-libraries.cmd b/Tools/build-native-libraries.cmd index a359777b8..8423b9ae9 100755 --- a/Tools/build-native-libraries.cmd +++ b/Tools/build-native-libraries.cmd @@ -7,13 +7,13 @@ if [[ -z $2 ]] then c="-c Release" else - c=-c $2 + c="-c $2" fi dotnet build ${c} Projects/Argon2/Argon2.csproj -dotnet pack -o packages Projects/Argon2/Argon2.csproj +dotnet pack ${c} -o packages Projects/Argon2/Argon2.csproj dotnet build ${c} Projects/ZLib/ZLib.csproj -dotnet pack -o packages Projects/ZLib/ZLib.csproj +dotnet pack ${c} -o packages Projects/ZLib/ZLib.csproj exit $? :CMDSCRIPT @@ -24,6 +24,6 @@ IF "%~1" == "" ( ) dotnet build %c% Projects\Argon2\Argon2.csproj -dotnet pack -o packages Projects\Argon2\Argon2.csproj +dotnet pack %c% -o packages Projects\Argon2\Argon2.csproj dotnet build %c% Projects\ZLib\ZLib.csproj -dotnet pack -o packages Projects\ZLib\ZLib.csproj +dotnet pack %c% -o packages Projects\ZLib\ZLib.csproj diff --git a/Tools/publish.cmd b/Tools/publish.cmd index c37b11f20..aac2e782c 100755 --- a/Tools/publish.cmd +++ b/Tools/publish.cmd @@ -7,7 +7,7 @@ if [[ -z $2 ]] then c="-c Release" else - c=-c $2 + c="-c $2" fi Tools/build-native-libraries.cmd $2