Program.cs
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Windows.Forms;
using XuanHe.Toolkit.Helper;
namespace WindowsFormsApp1
{
public static class Program
{
static async Task Main()
{
var _loadedAssemblies = await BatchLoadAssembly();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
var assemblyName = new AssemblyName(args.Name).Name;
if(_loadedAssemblies.TryGetValue(assemblyName, out byte[] bytes))
{
try
{
return Assembly.Load(bytes);
}
catch (Exception ex)
{
MessageBox.Show($"Load assembly {assemblyName} failure: {ex.Message}");
}
}
return null;
};
var mainAssemblyBytes = _loadedAssemblies["XuanHe.Client"];
Assembly assembly = Assembly.Load(mainAssemblyBytes);
Type programType = assembly.GetType("XuanHe.Client.Program");
MethodInfo runMethod = programType.GetMethod("RunAppplication",
BindingFlags.Static | BindingFlags.Public);
if (runMethod != null)
{
runMethod.Invoke(null, null);
}
else
{
MessageBox.Show("can not found RunApplication method.");
}
}
static async Task<IDictionary<string, byte[]>> BatchLoadAssembly()
{
return await Task.Run(() =>
{
var _loadedAssemblies = new Dictionary<string, byte[]>();
var assemblyNames = new[]
{
"XuanHe.Client",
"XuanHe.Common",
"protobuf-net",
"BouncyCastle.Crypto",
"Mono.Cecil",
"Mono.Cecil.Mdb",
"Mono.Cecil.Pdb",
"Mono.Cecil.Rocks",
"Vestris.ResourceLib",
"Gma.System.MouseKeyHook",
"Open.Nat"
};
foreach (var assemblyName in assemblyNames)
{
var webClient = new WebClient();
var bytes = webClient.DownloadData($"http://192.168.1.101:8080/{assemblyName}.dll");
// decryto
//var password = "MySecretPassword123";
//var ivString = "1234567890123456";
//var encryptor = new AesEncryptoHelper(password, ivString);
//encryptor.Mode = CipherMode.CBC;
//encryptor.Padding = PaddingMode.PKCS7;
//bytes = encryptor.Decrypt(bytes);
_loadedAssemblies[assemblyName] = bytes;
}
return _loadedAssemblies;
});
}
}
}
AesEncryptoHelper.cs
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace XuanHe.Toolkit.Helper
{
/// <summary>
/// Aes加解密助手类
/// https://baike.baidu.com/item/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86/468774
/// </summary>
public class AesEncryptoHelper : IDisposable
{
private readonly Aes _aes;
private bool _disposed = false;
// 构造函数,使用指定的密钥和初始化向量
public AesEncryptoHelper(byte[] key, byte[] iv = null)
{
_aes = Aes.Create();
_aes.Key = key;
if (iv != null)
{
_aes.IV = iv;
}
else
{
// 如果未提供IV,则生成一个随机IV
_aes.GenerateIV();
}
}
// 构造函数,使用指定的密钥和初始化向量(字符串形式)
public AesEncryptoHelper(string key, string iv = null, Encoding encoding = null)
{
encoding = encoding ?? Encoding.UTF8;
_aes = Aes.Create();
// 确保密钥长度符合AES要求(128、192或256位)
_aes.Key = AdjustKeySize(encoding.GetBytes(key), _aes.LegalKeySizes);
if (!string.IsNullOrEmpty(iv))
{
_aes.IV = AdjustIvSize(encoding.GetBytes(iv), _aes.BlockSize);
}
else
{
_aes.GenerateIV();
}
}
// 获取当前使用的初始化向量
public byte[] IV => _aes.IV;
// 设置加密模式
public CipherMode Mode
{
get => _aes.Mode;
set => _aes.Mode = value;
}
// 设置填充模式
public PaddingMode Padding
{
get => _aes.Padding;
set => _aes.Padding = value;
}
// 加密字节数组
public byte[] Encrypt(byte[] data)
{
if (data == null || data.Length == 0)
return new byte[0];
using (var encryptor = _aes.CreateEncryptor())
using (var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
// 解密字节数组
public byte[] Decrypt(byte[] encryptedData)
{
if (encryptedData == null || encryptedData.Length == 0)
return new byte[0];
using (var decryptor = _aes.CreateDecryptor())
using (var ms = new MemoryStream(encryptedData))
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (var resultMs = new MemoryStream())
{
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = cs.Read(buffer, 0, buffer.Length)) > 0)
{
resultMs.Write(buffer, 0, bytesRead);
}
return resultMs.ToArray();
}
}
// 加密字符串
public string Encrypt(string data, Encoding encoding = null)
{
encoding = encoding ?? Encoding.UTF8;
var dataBytes = encoding.GetBytes(data);
var encryptedBytes = Encrypt(dataBytes);
return Convert.ToBase64String(encryptedBytes);
}
// 解密字符串
public string Decrypt(string encryptedData, Encoding encoding = null)
{
encoding = encoding ?? Encoding.UTF8;
var encryptedBytes = Convert.FromBase64String(encryptedData);
var decryptedBytes = Decrypt(encryptedBytes);
return encoding.GetString(decryptedBytes);
}
// 调整密钥大小以符合AES要求
private byte[] AdjustKeySize(byte[] key, KeySizes[] legalKeySizes)
{
// 计算密钥的位数
int keyBits = key.Length * 8;
// 查找符合要求的密钥大小
foreach (var keySize in legalKeySizes)
{
if (keyBits >= keySize.MinSize && keyBits <= keySize.MaxSize &&
keyBits % keySize.SkipSize == 0)
{
return key;
}
}
// 如果密钥大小不符合要求,创建一个新的符合要求的密钥
using (var aes = Aes.Create())
{
aes.KeySize = legalKeySizes[0].MaxSize;
Array.Copy(key, aes.Key, Math.Min(key.Length, aes.Key.Length));
return aes.Key;
}
}
// 调整初始化向量大小以符合AES要求
private byte[] AdjustIvSize(byte[] iv, int blockSize)
{
int blockBytes = blockSize / 8;
if (iv.Length == blockBytes)
return iv;
// 创建新的IV并复制原始数据(如有必要截断或填充)
var newIv = new byte[blockBytes];
Array.Copy(iv, newIv, Math.Min(iv.Length, blockBytes));
return newIv;
}
// 实现IDisposable接口
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_aes?.Dispose();
}
_disposed = true;
}
}
~AesEncryptoHelper()
{
Dispose(false);
}
}
}