feat: Updates to .NET 6 (#843)

* Fixes an issue with moving directories across volumes
* Removes usages of WebClient
* Removes usages of Cryptographic Providers

Note: Even though .NET 6 introduces Xoshiro RNG, there is no way to control the seed. I'll do some reconciliation of Xoshiro so it functions closer to the built in one. For the most part, it has parity though.
Benchmarks show there is nothing odd about the implementations, they are within 1ns of each other.
This commit is contained in:
Kamron Batman 2021-11-13 13:38:01 -08:00 • committed by GitHub
parent a4d9a3bdc2
commit c31bf20d0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 192 additions and 231 deletions

View file

@ -55,9 +55,9 @@ namespace Server.Accounting.Security
{
var passwordProtection = algorithm switch
{
PasswordProtectionAlgorithm.MD5 => MD5PasswordProtection.Instance,
PasswordProtectionAlgorithm.SHA1 => SHA1PasswordProtection.Instance,
PasswordProtectionAlgorithm.SHA2 => SHA2PasswordProtection.Instance,
PasswordProtectionAlgorithm.MD5 => HashAlgorithmPasswordProtection.MD5Instance,
PasswordProtectionAlgorithm.SHA1 => HashAlgorithmPasswordProtection.SHA1Instance,
PasswordProtectionAlgorithm.SHA2 => HashAlgorithmPasswordProtection.SHA2Instance,
PasswordProtectionAlgorithm.PBKDF2 => PBKDF2PasswordProtection.Instance,
PasswordProtectionAlgorithm.Argon2 => Argon2PasswordProtection.Instance,
PasswordProtectionAlgorithm.None => throw new Exception("Do not use PasswordProtectionAlgorithm.None"),

View file

@ -1,8 +1,8 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2021 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MD5PasswordProtection.cs *
* File: HashAlgorithmPasswordProtection.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@ -19,17 +19,19 @@ using Server.Text;
namespace Server.Accounting.Security
{
public class MD5PasswordProtection : IPasswordProtection
public class HashAlgorithmPasswordProtection : IPasswordProtection
{
public static IPasswordProtection Instance = new MD5PasswordProtection();
#pragma warning disable CA5351
private readonly MD5CryptoServiceProvider m_MD5HashProvider = new();
#pragma warning restore CA5351
public static IPasswordProtection MD5Instance = new HashAlgorithmPasswordProtection(MD5.Create());
public static IPasswordProtection SHA1Instance = new HashAlgorithmPasswordProtection(SHA1.Create());
public static IPasswordProtection SHA2Instance = new HashAlgorithmPasswordProtection(SHA512.Create());
private readonly HashAlgorithm _hashAlgorithm;
public HashAlgorithmPasswordProtection(HashAlgorithm hashAlgorithm) => _hashAlgorithm = hashAlgorithm;
public string EncryptPassword(string plainPassword)
{
byte[] bytes = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)).GetBytesAscii();
return m_MD5HashProvider.ComputeHash(bytes).ToHexString();
return _hashAlgorithm.ComputeHash(bytes).ToHexString();
}
public bool ValidatePassword(string encryptedPassword, string plainPassword) =>

View file

@ -1,38 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SHA1PasswordProtection.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Security.Cryptography;
using Server.Text;
namespace Server.Accounting.Security
{
public class SHA1PasswordProtection : IPasswordProtection
{
public static IPasswordProtection Instance = new SHA1PasswordProtection();
#pragma warning disable CA5350
private readonly SHA1CryptoServiceProvider m_SHA1HashProvider = new();
#pragma warning restore CA5350
public string EncryptPassword(string plainPassword)
{
byte[] bytes = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)).GetBytesAscii();
return m_SHA1HashProvider.ComputeHash(bytes).ToHexString();
}
public bool ValidatePassword(string encryptedPassword, string plainPassword) =>
EncryptPassword(plainPassword) == encryptedPassword;
}
}

View file

@ -1,36 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SHA2PasswordProtection.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Security.Cryptography;
using Server.Text;
namespace Server.Accounting.Security
{
public class SHA2PasswordProtection : IPasswordProtection
{
public static IPasswordProtection Instance = new SHA2PasswordProtection();
private readonly SHA512CryptoServiceProvider m_SHA2HashProvider = new();
public string EncryptPassword(string plainPassword)
{
byte[] bytes = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)).GetBytesAscii();
return m_SHA2HashProvider.ComputeHash(bytes).ToHexString();
}
public bool ValidatePassword(string encryptedPassword, string plainPassword) =>
EncryptPassword(plainPassword) == encryptedPassword;
}
}

View file

@ -5,6 +5,10 @@ using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Server.Buffers;
namespace Server.Compression
@ -53,13 +57,18 @@ namespace Server.Compression
var tempDir = PathUtility.EnsureRandomPath(Path.GetTempPath());
var libarchiveFile = Path.Combine(tempDir, "libarchive.zip");
using WebClient wc = new WebClient();
wc.DownloadFile (new Uri(_libArchiveWindowsUrl), libarchiveFile);
// This isn't called often so we don't need to optimize
using (HttpClient hc = new HttpClient())
{
var result = hc.Send(new HttpRequestMessage(HttpMethod.Get, new Uri(_libArchiveWindowsUrl)));
using var stream = result.Content.ReadAsStream();
using FileStream fs = new FileStream(libarchiveFile, FileMode.Create, FileAccess.Write, FileShare.None);
stream.CopyTo(fs);
}
ZipFile.ExtractToDirectory(libarchiveFile, tempDir);
var libArchivePath = Path.Combine(tempDir, "libarchive");
Directory.Move(Path.Combine(libArchivePath, "bin"), "bsdtar");
Directory.Delete(libArchivePath, true);
PathUtility.MoveDirectory(Path.Combine(libArchivePath, "bin"), Path.Combine(Core.BaseDirectory, "bsdtar"));
File.Delete(libarchiveFile);
return Path.Combine(Core.BaseDirectory, "bsdtar/bsdtar.exe");

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

View file

@ -43,7 +43,7 @@ namespace Server
}
};
var file = Core.FindDataFile("prof.txt");
var file = Core.FindDataFile("prof.txt", false);
if (!File.Exists(file))
{
var parent = Path.Combine(Core.BaseDirectory, "Data/Professions");

View file

@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Server.Logging;
@ -165,12 +167,16 @@ namespace Server.Misc
Utility.IPMatch("169.254.*", ip) ||
Utility.IPMatch("100.64-127.*", ip));
private const string _ipifyUrl = "https://api.ipify.org";
private static IPAddress FindPublicAddress()
{
try
{
using WebClient wc = new WebClient();
return IPAddress.Parse(wc.DownloadString("https://api.ipify.org"));
// This isn't called often so we don't need to optimize
using HttpClient hc = new HttpClient();
var ipAddress = hc.GetStringAsync(_ipifyUrl).Result;
return IPAddress.Parse(ipAddress);
}
catch
{

View file

@ -25,7 +25,6 @@ namespace Server.Mobiles
{
return Utility.Random(6) switch
{
0 => 0,
1 => Utility.RandomBlueHue(),
2 => Utility.RandomGreenHue(),
3 => Utility.RandomRedHue(),

View file

@ -39,7 +39,7 @@
<IncludeInPackage>false</IncludeInPackage>
</ProjectReference>
<PackageReference Include="MailKit" Version="2.15.0" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="6.0.0" />
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.1.0" />
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
<PackageReference Include="Argon2.Bindings" Version="1.9.1" />

View file

@ -97,7 +97,7 @@ namespace Server.Saves
Directory.CreateDirectory(AutomaticBackupPath);
var backupPath = Path.Combine(AutomaticBackupPath, Utility.GetTimeStamp());
Directory.Move(args.OldSavePath, backupPath);
PathUtility.MoveDirectory(args.OldSavePath, backupPath);
logger.Information($"Created backup at {backupPath}");
@ -150,7 +150,7 @@ namespace Server.Saves
Directory.Delete(savePath, true);
var dirInfo = new DirectoryInfo(folder);
logger.Information($"Restoring backup {dirInfo.Name}");
Directory.Move(folder, savePath);
PathUtility.MoveDirectory(folder, savePath);
break;
}