feat: Adds .NET 10 / C# 14 support. (#2258)

### Summary
* Adds .NET 10 support
* Bumps to C# 14
This commit is contained in:
Kamron Batman 2025-11-11 11:26:34 -08:00 • committed by GitHub
parent fbf8497c59
commit 3a3f5ee518
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 124 additions and 154 deletions

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2023 - ModernUO Development Team *
* Copyright 2019-2025 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PBKDF2PasswordProtection.cs *
* *
@ -18,42 +18,43 @@ using System.Buffers.Binary;
using System.Security.Cryptography;
using Server.Text;
namespace Server.Accounting.Security
namespace Server.Accounting.Security;
public class PBKDF2PasswordProtection : IPasswordProtection
{
public class PBKDF2PasswordProtection : IPasswordProtection
private const ushort m_MinIterations = 1024;
private const ushort m_MaxIterations = 1536;
private const int m_SaltSize = 8;
private const int m_HashSize = 32;
private const int m_OutputSize = 2 + m_SaltSize + m_HashSize;
public static readonly IPasswordProtection Instance = new PBKDF2PasswordProtection();
public string EncryptPassword(string plainPassword)
{
private const ushort m_MinIterations = 1024;
private const ushort m_MaxIterations = 1536;
private const int m_SaltSize = 8;
private const int m_HashSize = 32;
private const int m_OutputSize = 2 + m_SaltSize + m_HashSize;
public static readonly IPasswordProtection Instance = new PBKDF2PasswordProtection();
Span<byte> output = stackalloc byte[m_OutputSize];
var iterations = Utility.RandomMinMax(m_MinIterations, m_MaxIterations);
BinaryPrimitives.WriteUInt16LittleEndian(output[..2], (ushort)iterations);
public string EncryptPassword(string plainPassword)
{
Span<byte> output = stackalloc byte[m_OutputSize];
var iterations = Utility.RandomMinMax(m_MinIterations, m_MaxIterations);
BinaryPrimitives.WriteUInt16LittleEndian(output[..2], (ushort)iterations);
var salt = output.Slice(2, m_SaltSize);
RandomNumberGenerator.Fill(salt);
var rfc2898 = new Rfc2898DeriveBytes(plainPassword, m_SaltSize, iterations, HashAlgorithmName.SHA256);
rfc2898.Salt.CopyTo(output.Slice(2, m_SaltSize));
rfc2898.GetBytes(m_HashSize).CopyTo(output[(m_SaltSize + 2)..]);
var hash = output.Slice(2 + m_SaltSize, m_HashSize);
Rfc2898DeriveBytes.Pbkdf2(plainPassword, salt, hash, iterations, HashAlgorithmName.SHA256);
return output.ToHexString();
}
return output.ToHexString();
}
public bool ValidatePassword(string encryptedPassword, string plainPassword)
{
Span<byte> encryptedBytes = stackalloc byte[m_OutputSize];
encryptedPassword.GetBytes(encryptedBytes);
public bool ValidatePassword(string encryptedPassword, string plainPassword)
{
Span<byte> encryptedBytes = stackalloc byte[m_OutputSize];
encryptedPassword.GetBytes(encryptedBytes);
var iterations = BinaryPrimitives.ReadUInt16LittleEndian(encryptedBytes[..2]);
var salt = encryptedBytes.Slice(2, m_SaltSize);
var iterations = BinaryPrimitives.ReadUInt16LittleEndian(encryptedBytes[..2]);
var salt = encryptedBytes.Slice(2, m_SaltSize);
ReadOnlySpan<byte> hash =
new Rfc2898DeriveBytes(plainPassword, salt.ToArray(), iterations, HashAlgorithmName.SHA256).GetBytes(m_HashSize);
Span<byte> hash = stackalloc byte[m_HashSize];
Rfc2898DeriveBytes.Pbkdf2(plainPassword, salt, hash, iterations, HashAlgorithmName.SHA256);
return hash.SequenceEqual(encryptedBytes[(m_SaltSize + 2)..]);
}
return hash.SequenceEqual(encryptedBytes[(m_SaltSize + 2)..]);
}
}