This commit is contained in:
owenchen committed 2026-08-19 14:11:17 +08:00
commit f05d2d215f
678 files changed
+73865

No files matched your search

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace CloudBuilder.Core.Utility
{
public class DataTableConvertor
{
/// <summary>
/// DataTable转对象
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static List<T> ConvertToList<T>(DataTable dt) where T : new()
{
// 定义集合
var list = new List<T>();
if (dt == null || 0 == dt.Rows.Count)
{
return list;
}
// 获得此模型的可写公共属性
IEnumerable<PropertyInfo> propertys = typeof(T).GetProperties().Where(u => u.CanWrite);
list = ConvertToEntity<T>(dt, propertys);
return list;
}
private static List<T> ConvertToEntity<T>(DataTable dt, IEnumerable<PropertyInfo> propertys) where T : new()
{
var list = new List<T>();
//遍历DataTable中所有的数据行
foreach (DataRow dr in dt.Rows)
{
if (dr.RowState == DataRowState.Deleted) continue;
var entity = new T();
//遍历该对象的所有属性
foreach (PropertyInfo p in propertys)
{
//将属性名称赋值给临时变量
string tmpName = p.Name;
//检查DataTable是否包含此列(列名==对象的属性名)
if (!dt.Columns.Contains(tmpName)) continue;
//取值
object value = dr[tmpName];
//如果非空,则赋给对象的属性
if (value != DBNull.Value)
{
p.SetValue(entity, value, null);
}
}
//对象添加到泛型集合中
list.Add(entity);
}
return list;
}
/// <summary>
/// 对象转DataTable
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public static DataTable ToDataTable<T>(IList<T> list)
{
return ToDataTable<T>(list, false);
}
public static DataTable ToDataTable<T>(IList<T> list, bool blankOption)
{
Type elementType = typeof(T);
var t = new DataTable();
elementType.GetProperties().ToList().ForEach(propInfo => t.Columns.Add(propInfo.Name, Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType));
if (blankOption)
{
var row = t.NewRow();
t.Rows.Add(row);
}
foreach (T item in list)
{
var row = t.NewRow();
elementType.GetProperties().ToList().ForEach(propInfo => row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value);
t.Rows.Add(row);
}
return t;
}
public static DataTable ToDataTable<T>(T[] list)
{
Type elementType = typeof(T);
var t = new DataTable();
elementType.GetProperties().ToList().ForEach(propInfo => t.Columns.Add(propInfo.Name, Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType));
foreach (T item in list)
{
var row = t.NewRow();
elementType.GetProperties().ToList().ForEach(propInfo => row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value);
t.Rows.Add(row);
}
return t;
}
}
}
@@ -0,0 +1,20 @@
using System.Xml.Serialization;
namespace CloudBuilder.Util
{
public class DeserializeHelper<T>
{
public static T Deserialize(string xml)
{
StringReader textReader = new StringReader(xml);
XmlSerializer serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(textReader);
}
public static string LoadXml(string filePath)
{
if (!File.Exists(filePath)) return null;
return File.ReadAllText(Path.Combine(filePath));
}
}
}
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Web;
namespace System
{
public static class EncryptHelper
{
/// <summary>
/// AES秘钥(强烈要求.json自定义取出)
/// </summary>
private const string AesKey = "OwenItc-*&$%RTj3";
/// <summary>
/// AES偏移向量(强烈要求.json自定义取出)
/// </summary>
private const string AesIV = "*&^KJ8a-Tj3*&$%R";
public static string AesEncrypt(string toEncryptString)
{
return AesEncrypt(toEncryptString, AesKey, AesIV);
}
/// <summary>
/// AES加密
/// </summary>
/// <param name="toEncryptString">待加密的明文</param>
/// <returns></returns>
public static string AesEncrypt(this string toEncryptString, string aesKey, string aesIV)
{
var rijndaelCipher = new RijndaelManaged
{
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
KeySize = 128,
BlockSize = 128
};
var toEncryptBytes = Encoding.UTF8.GetBytes(toEncryptString);
var keyBytes = Encoding.UTF8.GetBytes(aesKey);
var ivBytes = Encoding.UTF8.GetBytes(aesIV);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = ivBytes;
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] cipherBytes = transform.TransformFinalBlock(toEncryptBytes, 0, toEncryptBytes.Length);
return Convert.ToBase64String(cipherBytes);
}
public static string AesDecrpt(string toDecrpt)
{
return AesDecrpt(toDecrpt, AesKey, AesIV);
}
/// <summary>
/// AES解密
/// </summary>
/// <param name="toDecrpt"></param>
/// <returns></returns>
public static string AesDecrpt(this string toDecrpt, string aesKey, string aesIV)
{
var key = Encoding.UTF8.GetBytes(aesKey);
var encryptedData = Convert.FromBase64String(toDecrpt);
var iv = Encoding.UTF8.GetBytes(aesIV);
var rDel = new RijndaelManaged
{
Key = key,
IV = iv,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
var cTransform = rDel.CreateDecryptor();
var resultArray = cTransform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(resultArray);
}
public static string UrlEncode(string toEncryptString)
{
if (string.IsNullOrEmpty(toEncryptString)) return null;
return HttpUtility.UrlEncode(AesEncrypt(toEncryptString), Encoding.UTF8);
}
public static string UrlDecode(string toEncryptString)
{
if (string.IsNullOrEmpty(toEncryptString)) return null;
return AesDecrpt(toEncryptString);
}
public static string Decode(string toEncryptString)
{
if (string.IsNullOrEmpty(toEncryptString)) return null;
return AesDecrpt(HttpUtility.UrlDecode(toEncryptString, Encoding.UTF8));
}
public static string GetMd5(this string source)
{
if (string.IsNullOrEmpty(source)) return null;
MD5 md = MD5.Create();
byte[] bytes = md.ComputeHash(System.Text.Encoding.UTF8.GetBytes(source));
string dec = null;
foreach (byte b in bytes)
{
dec += b.ToString("x2");
}
return dec;
}
}
}
@@ -0,0 +1,58 @@
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using System.Text;
/// <summary>
/// 文件日志写入封装类,自动按日期分文件、超大小自动切割
/// </summary>
public class FileLog
{
private readonly IConfiguration _configuration;
private readonly object _lockObj = new object(); // 独立锁,不依赖外部this
public FileLog(IConfiguration configuration)
{
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
/// <summary>
/// 写入日志内容到文件
/// </summary>
/// <param name="log">日志文本</param>
public void WriteToFile(string log)
{
try
{
// 读取配置,转换最大文件字节数
int maxMb = _configuration.GetValue<int>("Logging:MaxFileSizeMB");
long maxFileSizeBytes = (long)maxMb * 1024 * 1024;
string today = DateTime.Now.ToString("yyyyMMdd");
string basePath = _configuration["Logging:LogFileDirectory"];
Directory.CreateDirectory(basePath);
string baseFileName = $"log-{today}";
string ext = ".log";
string finalPath = Path.Combine(basePath, $"{baseFileName}{ext}");
int index = 1;
// 文件超限则递增后缀切割
while (File.Exists(finalPath) && new FileInfo(finalPath).Length >= maxFileSizeBytes)
{
finalPath = Path.Combine(basePath, $"{baseFileName}-{index}{ext}");
index++;
}
// 线程安全写入
lock (_lockObj)
{
File.AppendAllText(finalPath, log + Environment.NewLine, Encoding.UTF8);
}
}
catch
{
// 原逻辑吞掉所有异常,如需日志可自行增加内部异常输出
}
}
}
@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace System
{
/// <summary>
/// 对象属性值复制
/// </summary>
public class ObjectCopyHelper
{
/// <summary>
/// 属性映射(静态对象,无需重复建立属性映射关系,提高效率)
/// </summary>
public static Dictionary<string, List<string>> MapDic = new Dictionary<string, List<string>>();
/// <summary>
/// S复制到D(创建对象D)
/// </summary>
/// <typeparam name="D">输出对象类型</typeparam>
/// <typeparam name="S">输入对象类型</typeparam>
/// <param name="s">输入对象</param>
/// <returns></returns>
public static D Copy<S, D>(S s)
where D : class, new()
where S : class, new()
{
if (s == null)
{
return default(D);
}
//使用无参数构造函数,创建指定泛型类型参数所指定类型的实例
D d = Activator.CreateInstance<D>();
return Copy<S, D>(s, d);
}
/// <summary>
/// S复制到D(对象D已存在)
/// </summary>
/// <typeparam name="D">输出对象类型</typeparam>
/// <typeparam name="S">输入对象类型</typeparam>
/// <param name="s">输入对象</param>
/// <param name="d">输出对象</param>
/// <returns></returns>
public static D Copy<S, D>(S s, D d)
where D : class, new()
where S : class, new()
{
if (s == null || d == null)
{
return d;
}
try
{
var sType = s.GetType();
var dType = typeof(D);
//属性映射Key
string mapkey = dType.FullName + "_" + sType.FullName;
if (MapDic.ContainsKey(mapkey))
{
//已存在属性映射
foreach (var item in MapDic[mapkey])
{
//按照属性映射关系赋值
//.net 4
//dType.GetProperty(item).SetValue(d, sType.GetProperty(item).GetValue(s, null), null);
//.net 4.5
dType.GetProperty(item).SetValue(d, sType.GetProperty(item).GetValue(s));
}
}
else
{
//不存在属性映射,需要建立属性映射
List<string> namelist = new List<string>();
Dictionary<string, TypeAndValue> dic = new Dictionary<string, TypeAndValue>();
//遍历获取输入类型的属性(属性名称,类型,值)
foreach (PropertyInfo sP in sType.GetProperties())
{
//.net 4
//dic.Add(sP.Name, new TypeAndValue() { type = sP.PropertyType, value = sP.GetValue(s, null) });
//.net 4.5
dic.Add(sP.Name, new TypeAndValue() { type = sP.PropertyType, value = sP.GetValue(s) });
}
//遍历输出类型的属性,并与输入类型(相同名称和类型的属性)建立映射,并赋值
foreach (PropertyInfo dP in dType.GetProperties())
{
if (dic.Keys.Contains(dP.Name))
{
if (dP.PropertyType == dic[dP.Name].type)
{
namelist.Add(dP.Name);
//.net 4
//dP.SetValue(d, dic[dP.Name].value, null);
//.net 4.5
dP.SetValue(d, dic[dP.Name].value);
}
}
}
//保存映射
if (!MapDic.ContainsKey(mapkey))
{
MapDic.Add(mapkey, namelist);
}
}
}
catch (Exception ex)
{
throw ex;
}
return d;
}
/// <summary>
/// SList复制到DList
/// </summary>
/// <typeparam name="D">输出对象类型</typeparam>
/// <typeparam name="S">输入对象类型</typeparam>
/// <param name="sList">输入对象集合</param>
/// <returns></returns>
public static IQueryable<D> Copy<S, D>(IQueryable<S> sList)
where D : class, new()
where S : class, new()
{
List<D> dList = new List<D>();
foreach (var item in sList)
{
dList.Add(Copy<S, D>(item));
}
return dList.AsQueryable();
}
}
/// <summary>
/// 类型和值
/// </summary>
class TypeAndValue
{
/// <summary>
/// 类型
/// </summary>
public Type type { get; set; }
/// <summary>
/// 值
/// </summary>
public object value { get; set; }
}
}
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System
{
public class QuotedString
{
public static string ToQuotedString(string[] vs)
{
if (vs == null || vs.Length == 0) return null;
return ToQuotedDelimitedList(vs);
}
public static string ToQuotedString(int[] vs)
{
if (vs == null || vs.Length == 0) return null;
return ToQuotedDelimitedList(vs.Select(x => x.ToString()).ToArray()); ;
}
public const char DELIMITER_CHAR = ',';
/// <summary>
/// 字符串安全转数组,分隔符','
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static string[] DelimiteredListToArray(string t)
{
return DelimiteredListToArray(t, DELIMITER_CHAR);
}
public static string[] DelimiteredListToArray(string t, char delim)
{
if (string.IsNullOrEmpty(t)) return null;
return t.Split(delim);
}
/// <summary>
/// 字符串安全转数组,分隔符','
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static List<string> DelimiteredListToList(string t)
{
return DelimiteredListToList(t, DELIMITER_CHAR);
}
public static List<string> DelimiteredListToList(string t, char delim)
{
if (string.IsNullOrEmpty(t)) return null;
List<string> l = new List<string>();
l.AddRange(DelimiteredListToArray(t, delim));
return l;
}
/// <summary>
/// 数组变成字符串
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ToDelimiteredList(string[] s)
{
return ToDelimiteredList(s, DELIMITER_CHAR);
}
public static string ToQuotedDelimitedList(string[] s)
{
StringBuilder b = new StringBuilder();
foreach (string t in s)
{
if (b.Length > 0) b.Append(DELIMITER_CHAR);
b.Append('\'' + t + '\'');
}
return b.ToString();
}
public static string ToDelimiteredList(string[] s, char delim)
{
StringBuilder b = new StringBuilder();
foreach (string t in s)
{
b.Append(delim + t);
}
string r = b.ToString();
if (r.StartsWith(delim.ToString())) r = r.Substring(1);
return r;
}
public static string CreateRandomNumber(int NumCount)
{
string text = "0,1,2,3,4,5,6,7,8,9";
string[] array = text.Split(',');
string text2 = "";
int num = -1;
Random random = new Random();
for (int i = 0; i < NumCount; i++)
{
if (num != -1)
{
random = new Random(i * num * (int)DateTime.Now.Ticks);
}
int num2 = random.Next(array.Length - 1);
if (num == num2)
{
return CreateRandomNumber(NumCount);
}
num = num2;
text2 += array[num2];
}
return text2;
}
}
}
@@ -0,0 +1,295 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using CryptographyRSA = System.Security.Cryptography.RSA; // 别名避免与当前类名冲突
namespace System
{
/// <summary>
/// RSA操作类(跨平台实现)
/// </summary>
public class RSA
{
// 记录当前实例是否仅包含公钥(替代原来的 rsa.PublicOnly)
private bool publicOnly;
/// <summary>
/// 导出XML格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public string ToXML(bool convertToPublic = false)
{
bool includePrivate = !publicOnly && !convertToPublic;
return rsa.ToXmlString(includePrivate);
}
/// <summary>
/// 导出PEM PKCS#1格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public string ToPEM_PKCS1(bool convertToPublic = false)
{
if (!publicOnly && !convertToPublic)
{
return rsa.ExportRSAPrivateKeyPem();
}
return rsa.ExportRSAPublicKeyPem();
}
/// <summary>
/// 导出PEM PKCS#8格式密钥对,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public string ToPEM_PKCS8(bool convertToPublic = false)
{
if (!publicOnly && !convertToPublic)
{
return rsa.ExportPkcs8PrivateKeyPem();
}
return rsa.ExportSubjectPublicKeyInfoPem();
}
/// <summary>
/// 加密字符串(utf-8),出错抛异常
/// </summary>
public string Encode(string str)
{
return RSA_Unit.Base64EncodeBytes(Encode(Encoding.UTF8.GetBytes(str)));
}
/// <summary>
/// 加密数据,出错抛异常
/// </summary>
public byte[] Encode(byte[] data)
{
int blockLen = rsa.KeySize / 8 - 11;
if (data.Length <= blockLen)
{
return rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
}
using (var dataStream = new MemoryStream(data))
using (var enStream = new MemoryStream())
{
byte[] buffer = new byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0)
{
byte[] block = new byte[len];
Array.Copy(buffer, 0, block, 0, len);
byte[] enBlock = rsa.Encrypt(block, RSAEncryptionPadding.Pkcs1);
enStream.Write(enBlock, 0, enBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return enStream.ToArray();
}
}
/// <summary>
/// 解密字符串(utf-8),解密异常返回null
/// </summary>
public string DecodeOrNull(string str)
{
if (string.IsNullOrEmpty(str))
return null;
var bytes = RSA_Unit.Base64DecodeBytes(str);
if (bytes == null)
return null;
var decrypted = DecodeOrNull(bytes);
if (decrypted == null)
return null;
return Encoding.UTF8.GetString(decrypted);
}
/// <summary>
/// 解密数据,解密异常返回null
/// </summary>
public byte[] DecodeOrNull(byte[] data)
{
try
{
int blockLen = rsa.KeySize / 8;
if (data.Length <= blockLen)
{
return rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
}
using (var dataStream = new MemoryStream(data))
using (var deStream = new MemoryStream())
{
byte[] buffer = new byte[blockLen];
int len = dataStream.Read(buffer, 0, blockLen);
while (len > 0)
{
byte[] block = new byte[len];
Array.Copy(buffer, 0, block, 0, len);
byte[] deBlock = rsa.Decrypt(block, RSAEncryptionPadding.Pkcs1);
deStream.Write(deBlock, 0, deBlock.Length);
len = dataStream.Read(buffer, 0, blockLen);
}
return deStream.ToArray();
}
}
catch
{
return null;
}
}
/// <summary>
/// 对str进行签名,并指定hash算法(如:SHA256)
/// </summary>
public string Sign(string hash, string str)
{
return RSA_Unit.Base64EncodeBytes(Sign(hash, Encoding.UTF8.GetBytes(str)));
}
/// <summary>
/// 对data进行签名,并指定hash算法(如:SHA256)
/// </summary>
public byte[] Sign(string hash, byte[] data)
{
return rsa.SignData(data, new HashAlgorithmName(hash), RSASignaturePadding.Pkcs1);
}
/// <summary>
/// 验证字符串str的签名是否是sgin,并指定hash算法(如:SHA256)
/// </summary>
public bool Verify(string hash, string sgin, string str)
{
var bytes = RSA_Unit.Base64DecodeBytes(sgin);
if (bytes == null)
return false;
return Verify(hash, bytes, Encoding.UTF8.GetBytes(str));
}
/// <summary>
/// 验证data的签名是否是sgin,并指定hash算法(如:SHA256)
/// </summary>
public bool Verify(string hash, byte[] sgin, byte[] data)
{
try
{
return rsa.VerifyData(data, sgin, new HashAlgorithmName(hash), RSASignaturePadding.Pkcs1);
}
catch
{
return false;
}
}
private CryptographyRSA rsa;
public RSA() : this(2048)
{
}
/// <summary>
/// 用指定密钥大小创建一个新的RSA,出错抛异常
/// </summary>
public RSA(int keySize)
{
rsa = CryptographyRSA.Create();
rsa.KeySize = keySize;
publicOnly = false; // 新生成的密钥对包含私钥
}
/// <summary>
/// 通过指定的密钥,创建一个RSA,xml内可以只包含一个公钥或私钥,或都包含,出错抛异常
/// </summary>
public RSA(string xml)
{
rsa = CryptographyRSA.Create();
rsa.FromXmlString(xml);
// 判断是否仅包含公钥
publicOnly = false;
try
{
rsa.ExportParameters(true); // 能导出私钥参数说明含私钥
}
catch (CryptographicException)
{
publicOnly = true;
}
}
/// <summary>
/// 通过一个pem文件创建RSA,pem为公钥或私钥,出错抛异常
/// </summary>
public RSA(string pem, bool noop)
{
rsa = CryptographyRSA.Create();
// 1. 兼容文件路径
string pemContent = pem;
if (!pemContent.Contains("BEGIN"))
{
pemContent = File.ReadAllText(pem);
}
// 2. 提取 Base64 部分(忽略标签)
var match = Regex.Match(pemContent,
@"-----BEGIN [^-]+-----([\s\S]*?)-----END [^-]+-----",
RegexOptions.Singleline);
if (!match.Success)
throw new CryptographicException("无效的 PEM 格式。");
string base64 = match.Groups[1].Value
.Replace("\r", "")
.Replace("\n", "")
.Replace(" ", "")
.Replace("\t", "")
.Trim();
byte[] der = Convert.FromBase64String(base64);
// 3. 依次尝试常见 RSA 密钥格式(顺序可调整)
// 先尝试 PKCS#8 私钥,再尝试 PKCS#1 私钥,然后公钥
try
{
rsa.ImportPkcs8PrivateKey(der, out _);
publicOnly = false;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportRSAPrivateKey(der, out _);
publicOnly = false;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportSubjectPublicKeyInfo(der, out _);
publicOnly = true;
return;
}
catch (CryptographicException) { }
try
{
rsa.ImportRSAPublicKey(der, out _);
publicOnly = true;
return;
}
catch (CryptographicException) { }
throw new CryptographicException("无法识别的 RSA 密钥格式。");
}
}
}
@@ -0,0 +1,326 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace System
{
public class RSA_PEM
{
/// <summary>
/// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM
/// </summary>
public static RSACryptoServiceProvider FromPEM(string pem)
{
var rsaParams = new CspParameters();
rsaParams.Flags = CspProviderFlags.UseMachineKeyStore;
var rsa = new RSACryptoServiceProvider(rsaParams);
var param = new RSAParameters();
var base64 = _PEMCode.Replace(pem, "");
var data = RSA_Unit.Base64DecodeBytes(base64);
if (data == null)
{
throw new Exception("PEM内容无效");
}
var idx = 0;
//读取长度
Func<byte, int> readLen = (first) => {
if (data[idx] == first)
{
idx++;
if (data[idx] == 0x81)
{
idx++;
return data[idx++];
}
else if (data[idx] == 0x82)
{
idx++;
return (((int)data[idx++]) << 8) + data[idx++];
}
else if (data[idx] < 0x80)
{
return data[idx++];
}
}
throw new Exception("PEM未能提取到数据");
};
//读取块数据
Func<byte[]> readBlock = () => {
var len = readLen(0x02);
if (data[idx] == 0x00)
{
idx++;
len--;
}
var val = data.sub(idx, len);
idx += len;
return val;
};
//比较data从idx位置开始是否是byts内容
Func<byte[], bool> eq = (byts) => {
for (var i = 0; i < byts.Length; i++, idx++)
{
if (idx >= data.Length)
{
return false;
}
if (byts[i] != data[idx])
{
return false;
}
}
return true;
};
if (pem.Contains("PUBLIC KEY"))
{
/****使用公钥****/
//读取数据总长度
readLen(0x30);
if (!eq(_SeqOID))
{
throw new Exception("PEM未知格式");
}
//读取1长度
readLen(0x03);
idx++;//跳过0x00
//读取2长度
readLen(0x30);
//Modulus
param.Modulus = readBlock();
//Exponent
param.Exponent = readBlock();
}
else if (pem.Contains("PRIVATE KEY"))
{
/****使用私钥****/
//读取数据总长度
readLen(0x30);
//读取版本号
if (!eq(_Ver))
{
throw new Exception("PEM未知版本");
}
//检测PKCS8
var idx2 = idx;
if (eq(_SeqOID))
{
//读取1长度
readLen(0x04);
//读取2长度
readLen(0x30);
//读取版本号
if (!eq(_Ver))
{
throw new Exception("PEM版本无效");
}
}
else
{
idx = idx2;
}
//读取数据
param.Modulus = readBlock();
param.Exponent = readBlock();
param.D = readBlock();
param.P = readBlock();
param.Q = readBlock();
param.DP = readBlock();
param.DQ = readBlock();
param.InverseQ = readBlock();
}
else
{
throw new Exception("pem需要BEGIN END标头");
}
rsa.ImportParameters(param);
return rsa;
}
static private Regex _PEMCode = new Regex(@"--+.+?--+|\s+");
static private byte[] _SeqOID = new byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
static private byte[] _Ver = new byte[] { 0x02, 0x01, 0x00 };
/// <summary>
/// 将RSA中的密钥对转换成PEM格式,usePKCS8=false时返回PKCS#1格式,否则返回PKCS#8格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
/// </summary>
public static string ToPEM(RSACryptoServiceProvider rsa, bool convertToPublic, bool usePKCS8)
{
//https://www.jianshu.com/p/25803dd9527d
//https://www.cnblogs.com/ylz8401/p/8443819.html
//https://blog.csdn.net/jiayanhui2877/article/details/47187077
//https://blog.csdn.net/xuanshao_/article/details/51679824
//https://blog.csdn.net/xuanshao_/article/details/51672547
var ms = new MemoryStream();
//写入一个长度字节码
Action<int> writeLenByte = (len) => {
if (len < 0x80)
{
ms.WriteByte((byte)len);
}
else if (len <= 0xff)
{
ms.WriteByte(0x81);
ms.WriteByte((byte)len);
}
else
{
ms.WriteByte(0x82);
ms.WriteByte((byte)(len >> 8 & 0xff));
ms.WriteByte((byte)(len & 0xff));
}
};
//写入一块数据
Action<byte[]> writeBlock = (byts) => {
var addZero = (byts[0] >> 4) >= 0x8;
ms.WriteByte(0x02);
var len = byts.Length + (addZero ? 1 : 0);
writeLenByte(len);
if (addZero)
{
ms.WriteByte(0x00);
}
ms.Write(byts, 0, byts.Length);
};
//根据后续内容长度写入长度数据
Func<int, byte[], byte[]> writeLen = (index, byts) => {
var len = byts.Length - index;
ms.SetLength(0);
ms.Write(byts, 0, index);
writeLenByte(len);
ms.Write(byts, index, len);
return ms.ToArray();
};
if (rsa.PublicOnly || convertToPublic)
{
/****生成公钥****/
var param = rsa.ExportParameters(false);
//写入总字节数,不含本段长度,额外需要24字节的头,后续计算好填入
ms.WriteByte(0x30);
var index1 = (int)ms.Length;
//固定内容
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
ms.writeAll(_SeqOID);
//从0x00开始的后续长度
ms.WriteByte(0x03);
var index2 = (int)ms.Length;
ms.WriteByte(0x00);
//后续内容长度
ms.WriteByte(0x30);
var index3 = (int)ms.Length;
//写入Modulus
writeBlock(param.Modulus);
//写入Exponent
writeBlock(param.Exponent);
//计算空缺的长度
var byts = ms.ToArray();
byts = writeLen(index3, byts);
byts = writeLen(index2, byts);
byts = writeLen(index1, byts);
return "-----BEGIN PUBLIC KEY-----\n" + RSA_Unit.TextBreak(RSA_Unit.Base64EncodeBytes(byts), 64) + "\n-----END PUBLIC KEY-----";
}
else
{
/****生成私钥****/
var param = rsa.ExportParameters(true);
//写入总字节数,后续写入
ms.WriteByte(0x30);
int index1 = (int)ms.Length;
//写入版本号
ms.writeAll(_Ver);
//PKCS8 多一段数据
int index2 = -1, index3 = -1;
if (usePKCS8)
{
//固定内容
ms.writeAll(_SeqOID);
//后续内容长度
ms.WriteByte(0x04);
index2 = (int)ms.Length;
//后续内容长度
ms.WriteByte(0x30);
index3 = (int)ms.Length;
//写入版本号
ms.writeAll(_Ver);
}
//写入数据
writeBlock(param.Modulus);
writeBlock(param.Exponent);
writeBlock(param.D);
writeBlock(param.P);
writeBlock(param.Q);
writeBlock(param.DP);
writeBlock(param.DQ);
writeBlock(param.InverseQ);
//计算空缺的长度
var byts = ms.ToArray();
if (index2 != -1)
{
byts = writeLen(index3, byts);
byts = writeLen(index2, byts);
}
byts = writeLen(index1, byts);
var flag = " PRIVATE KEY";
if (!usePKCS8)
{
flag = " RSA" + flag;
}
return "-----BEGIN" + flag + "-----\n" + RSA_Unit.TextBreak(RSA_Unit.Base64EncodeBytes(byts), 64) + "\n-----END" + flag + "-----";
}
}
}
}
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System
{
/// <summary>
/// 封装的一些通用方法
/// </summary>
public class RSA_Unit
{
static public string Base64EncodeBytes(byte[] byts)
{
return Convert.ToBase64String(byts);
}
static public byte[] Base64DecodeBytes(string str)
{
try
{
return Convert.FromBase64String(str);
}
catch
{
return null;
}
}
/// <summary>
/// 把字符串按每行多少个字断行
/// </summary>
static public string TextBreak(string text, int line)
{
var idx = 0;
var len = text.Length;
var str = new StringBuilder();
while (idx < len)
{
if (idx > 0)
{
str.Append('\n');
}
if (idx + line >= len)
{
str.Append(text.Substring(idx));
}
else
{
str.Append(text.Substring(idx, line));
}
idx += line;
}
return str.ToString();
}
}
static public class Extensions
{
/// <summary>
/// 从数组start开始到指定长度复制一份
/// </summary>
static public T[] sub<T>(this T[] arr, int start, int count)
{
T[] val = new T[count];
for (var i = 0; i < count; i++)
{
val[i] = arr[start + i];
}
return val;
}
static public void writeAll(this Stream stream, byte[] byts)
{
stream.Write(byts, 0, byts.Length);
}
}
}
@@ -0,0 +1,29 @@
using System.Text;
using System.Xml.Serialization;
namespace CloudBuilder.Util
{
public class SerializeHelper
{
public static string Serialize(object o)
{
if (o == null) return null;
XmlSerializer serializer = new XmlSerializer(o.GetType());
using (MemoryStream stream = new MemoryStream())
{
StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
serializer.Serialize((TextWriter)writer, o);
stream.Seek(0L, SeekOrigin.Begin);
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
public static void WriteAllText(string filePath, object o)
{
File.WriteAllText(filePath, Serialize(o));
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System
{
public class TableName<T>
{
public TableName()
{
}
public const string VALUE = "Value";
public const string DISPLAY_NAME = "DisplayName";
public virtual string Selected { get; set; }
public virtual T Value { get; set; }
public virtual string DisplayName { get; set; }
}
}