初始化仓库
This commit is contained in:
88
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/AES.cs
vendored
Normal file
88
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/AES.cs
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
public class AES
|
||||
{
|
||||
/// <summary>
|
||||
/// 128位全0初始向量
|
||||
/// </summary>
|
||||
private static readonly byte[] AES_IV = InitIV(16);
|
||||
|
||||
/// <summary>
|
||||
/// AES加密
|
||||
/// </summary>
|
||||
/// <param name="plainText">明文</param>
|
||||
/// <param name="key">对称密钥</param>
|
||||
/// <returns>密文</returns>
|
||||
public static string Encrypt(string plainText, string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] keyBytes = Convert.FromBase64String(key);
|
||||
byte[] plainBytes = AlipayConstants.DEFAULT_CHARSET.GetBytes(plainText); ;
|
||||
|
||||
RijndaelManaged rijndatel = new RijndaelManaged
|
||||
{
|
||||
Key = keyBytes,
|
||||
Mode = CipherMode.CBC,
|
||||
Padding = PaddingMode.PKCS7,
|
||||
IV = AES_IV
|
||||
};
|
||||
|
||||
ICryptoTransform transform = rijndatel.CreateEncryptor(rijndatel.Key, rijndatel.IV);
|
||||
byte[] cipherBytes = transform.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
|
||||
return Convert.ToBase64String(cipherBytes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("AES加密失败,plainText=" + plainText +
|
||||
",keySize=" + key.Length + "。" + e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AES解密
|
||||
/// </summary>
|
||||
/// <param name="cipherText">密文</param>
|
||||
/// <param name="key">对称密钥</param>
|
||||
/// <returns>明文</returns>
|
||||
public static string Decrypt(string cipherText, string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] keyBytes = Convert.FromBase64String(key);
|
||||
byte[] cipherBytes = Convert.FromBase64String(cipherText);
|
||||
|
||||
RijndaelManaged rijndatel = new RijndaelManaged
|
||||
{
|
||||
Key = keyBytes,
|
||||
Mode = CipherMode.CBC,
|
||||
Padding = PaddingMode.PKCS7,
|
||||
IV = AES_IV
|
||||
};
|
||||
|
||||
ICryptoTransform transform = rijndatel.CreateDecryptor(rijndatel.Key, rijndatel.IV);
|
||||
byte[] plainBytes = transform.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
|
||||
return AlipayConstants.DEFAULT_CHARSET.GetString(plainBytes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception("AES解密失败,ciphertext=" + cipherText +
|
||||
",keySize=" + key.Length + "。" + e.Message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] InitIV(int blockSize)
|
||||
{
|
||||
byte[] iv = new byte[blockSize];
|
||||
for (int i = 0; i < blockSize; ++i)
|
||||
{
|
||||
iv[i] = 0x0;
|
||||
}
|
||||
return iv;
|
||||
}
|
||||
}
|
||||
}
|
||||
326
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/AntCertificationUtil.cs
vendored
Normal file
326
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/AntCertificationUtil.cs
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Org.BouncyCastle.X509;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 证书相关工具类
|
||||
/// </summary>
|
||||
public static class AntCertificationUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 提取根证书序列号
|
||||
/// </summary>
|
||||
/// <param name="rootCertContent">根证书文本</param>
|
||||
/// <returns>根证书序列号</returns>
|
||||
public static string GetRootCertSN(string rootCertContent)
|
||||
{
|
||||
string rootCertSN = "";
|
||||
try
|
||||
{
|
||||
List<X509Certificate> x509Certificates = ReadPemCertChain(rootCertContent);
|
||||
foreach (X509Certificate cert in x509Certificates)
|
||||
{
|
||||
//只提取与指定算法类型匹配的证书的序列号
|
||||
if (cert.SigAlgOid.StartsWith("1.2.840.113549.1.1", StringComparison.Ordinal))
|
||||
{
|
||||
string certSN = GetCertSN(cert);
|
||||
if (string.IsNullOrEmpty(rootCertSN))
|
||||
{
|
||||
rootCertSN = certSN;
|
||||
}
|
||||
else
|
||||
{
|
||||
rootCertSN = rootCertSN + "_" + certSN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("提取根证书序列号失败。" + ex.Message);
|
||||
}
|
||||
return rootCertSN;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化证书文本
|
||||
/// </summary>
|
||||
/// <param name="certContent">证书文本</param>
|
||||
/// <returns>X509Certificate证书对象</returns>
|
||||
public static X509Certificate ParseCert(string certContent)
|
||||
{
|
||||
return new X509CertificateParser().ReadCertificate(Encoding.UTF8.GetBytes(certContent));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算指定证书的序列号
|
||||
/// </summary>
|
||||
/// <param name="cert">证书</param>
|
||||
/// <returns>序列号</returns>
|
||||
public static string GetCertSN(X509Certificate cert)
|
||||
{
|
||||
string issuerDN = cert.IssuerDN.ToString();
|
||||
//提取出的证书的issuerDN本身是以CN开头的,则无需逆序,直接返回
|
||||
if (issuerDN.StartsWith("CN", StringComparison.Ordinal))
|
||||
{
|
||||
return CalculateMd5(issuerDN + cert.SerialNumber);
|
||||
}
|
||||
List<string> attributes = issuerDN.Split(',').ToList();
|
||||
attributes.Reverse();
|
||||
return CalculateMd5(string.Join(",", attributes.ToArray()) + cert.SerialNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验证书链是否可信
|
||||
/// </summary>
|
||||
/// <param name="certContent">需要验证的目标证书或者证书链文本</param>
|
||||
/// <param name="rootCertContent">可信根证书列表文本</param>
|
||||
/// <returns>true:证书可信;false:证书不可信</returns>
|
||||
public static bool IsTrusted(string certContent, string rootCertContent)
|
||||
{
|
||||
List<X509Certificate> certs = ReadPemCertChain(certContent);
|
||||
List<X509Certificate> rootCerts = ReadPemCertChain(rootCertContent);
|
||||
return VerifyCertChain(certs, rootCerts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从证书链文本反序列化证书链集合
|
||||
/// </summary>
|
||||
/// <param name="cert">证书链文本</param>
|
||||
/// <returns>证书链集合</returns>
|
||||
private static List<X509Certificate> ReadPemCertChain(string cert)
|
||||
{
|
||||
System.Collections.ICollection collection = new X509CertificateParser().ReadCertificates(Encoding.UTF8.GetBytes(cert));
|
||||
List<X509Certificate> result = new List<X509Certificate>();
|
||||
foreach (var each in collection)
|
||||
{
|
||||
result.Add((X509Certificate)each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将证书链按照完整的签发顺序进行排序,排序后证书链为:[issuerA, subjectA]-[issuerA, subjectB]-[issuerB, subjectC]-[issuerC, subjectD]...
|
||||
/// </summary>
|
||||
/// <param name="certChain">未排序的证书链</param>
|
||||
/// <returns>true:排序成功;false:证书链不完整</returns>
|
||||
private static bool SortCertChain(List<X509Certificate> certChain)
|
||||
{
|
||||
//主题和证书的映射
|
||||
Dictionary<X509Name, X509Certificate> subject2CertMap = new Dictionary<X509Name, X509Certificate>();
|
||||
//签发者和证书的映射
|
||||
Dictionary<X509Name, X509Certificate> issuer2CertMap = new Dictionary<X509Name, X509Certificate>();
|
||||
//是否包含自签名证书
|
||||
bool hasSelfSignedCert = false;
|
||||
foreach (X509Certificate cert in certChain)
|
||||
{
|
||||
if (IsSelfSigned(cert))
|
||||
{
|
||||
if (hasSelfSignedCert)
|
||||
{
|
||||
//同一条证书链中只能有一个自签名证书
|
||||
return false;
|
||||
}
|
||||
hasSelfSignedCert = true;
|
||||
}
|
||||
subject2CertMap[cert.SubjectDN] = cert;
|
||||
issuer2CertMap[cert.IssuerDN] = cert;
|
||||
}
|
||||
|
||||
List<X509Certificate> orderedCertChain = new List<X509Certificate>();
|
||||
|
||||
X509Certificate current = certChain[0];
|
||||
|
||||
AddressingUp(subject2CertMap, orderedCertChain, current);
|
||||
AddressingDown(issuer2CertMap, orderedCertChain, current);
|
||||
|
||||
//说明证书链不完整
|
||||
if (certChain.Count != orderedCertChain.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//用排序后的结果覆盖传入的证书链集合
|
||||
for (int i = 0; i < orderedCertChain.Count; i++)
|
||||
{
|
||||
certChain[i] = orderedCertChain[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsSelfSigned(X509Certificate cert)
|
||||
{
|
||||
return cert.SubjectDN.Equivalent(cert.IssuerDN);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向上构造证书链
|
||||
/// </summary>
|
||||
/// <param name="subject2CertMap">主题与证书的映射</param>
|
||||
/// <param name="orderedCertChain">储存排序后的证书链集合</param>
|
||||
/// <param name="current">当前需要插入排序后的证书链集合中的证书</param>
|
||||
private static void AddressingUp(Dictionary<X509Name, X509Certificate> subject2CertMap,
|
||||
List<X509Certificate> orderedCertChain, X509Certificate current)
|
||||
{
|
||||
orderedCertChain.Insert(0, current);
|
||||
if (IsSelfSigned(current))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!subject2CertMap.ContainsKey(current.IssuerDN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
X509Certificate issuer = subject2CertMap[current.IssuerDN];
|
||||
AddressingUp(subject2CertMap, orderedCertChain, issuer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向下构造证书链
|
||||
/// </summary>
|
||||
/// <param name="issuer2CertMap">签发者和证书的映射</param>
|
||||
/// <param name="certChain">储存排序后的证书链集合</param>
|
||||
/// <param name="current">当前需要插入排序后的证书链集合中的证书</param>
|
||||
private static void AddressingDown(Dictionary<X509Name, X509Certificate> issuer2CertMap,
|
||||
List<X509Certificate> certChain, X509Certificate current)
|
||||
{
|
||||
if (!issuer2CertMap.ContainsKey(current.SubjectDN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
X509Certificate subject = issuer2CertMap[current.SubjectDN];
|
||||
if (IsSelfSigned(subject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
certChain.Add(subject);
|
||||
AddressingDown(issuer2CertMap, certChain, subject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证证书是否是信任证书库中的证书签发的
|
||||
/// </summary>
|
||||
/// <param name="cert">待验证证书</param>
|
||||
/// <param name="rootCerts">可信根证书列表</param>
|
||||
/// <returns>true:验证通过;false:验证不通过</returns>
|
||||
private static bool VerifyCert(X509Certificate cert, List<X509Certificate> rootCerts)
|
||||
{
|
||||
if (!cert.IsValidNow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Dictionary<X509Name, X509Certificate> subject2CertMap = new Dictionary<X509Name, X509Certificate>();
|
||||
foreach (X509Certificate root in rootCerts)
|
||||
{
|
||||
subject2CertMap[root.SubjectDN] = root;
|
||||
}
|
||||
|
||||
X509Name issuerDN = cert.IssuerDN;
|
||||
if (!subject2CertMap.ContainsKey(issuerDN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
X509Certificate issuer = subject2CertMap[issuerDN];
|
||||
try
|
||||
{
|
||||
AsymmetricKeyParameter publicKey = issuer.GetPublicKey();
|
||||
cert.Verify(publicKey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("证书验证出现异常。" + ex.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证证书列表
|
||||
/// </summary>
|
||||
/// <param name="certs">待验证的证书列表</param>
|
||||
/// <param name="rootCerts">可信根证书列表</param>
|
||||
/// <returns>true:验证通过;false:验证不通过</returns>
|
||||
private static bool VerifyCertChain(List<X509Certificate> certs, List<X509Certificate> rootCerts)
|
||||
{
|
||||
//证书列表排序,形成排序后的证书链
|
||||
bool sorted = SortCertChain(certs);
|
||||
if (!sorted)
|
||||
{
|
||||
//不是完整的证书链
|
||||
return false;
|
||||
}
|
||||
|
||||
//先验证第一个证书是不是信任库中证书签发的
|
||||
X509Certificate previous = certs[0];
|
||||
bool firstOK = VerifyCert(previous, rootCerts);
|
||||
if (!firstOK || certs.Count == 1)
|
||||
{
|
||||
return firstOK;
|
||||
}
|
||||
|
||||
//验证证书链
|
||||
for (int i = 1; i < certs.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
X509Certificate cert = certs[i];
|
||||
if (!cert.IsValidNow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//用上级证书的公钥验证本证书是否是上级证书签发的
|
||||
cert.Verify(previous.GetPublicKey());
|
||||
|
||||
previous = cert;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//证书链验证失败
|
||||
Console.WriteLine("证书链验证失败。" + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static string CalculateMd5(string input)
|
||||
{
|
||||
using (MD5 md5 = new MD5CryptoServiceProvider())
|
||||
{
|
||||
string result = "";
|
||||
byte[] bytes = md5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes(input));
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
result += bytes[i].ToString("x2");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从证书中提取公钥并转换为PEM编码
|
||||
/// </summary>
|
||||
/// <param name="input">证书</param>
|
||||
/// <returns>PEM编码公钥</returns>
|
||||
public static string ExtractPemPublicKeyFromCert(X509Certificate input)
|
||||
{
|
||||
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(input.GetPublicKey());
|
||||
return Convert.ToBase64String(subjectPublicKeyInfo.GetDerEncoded());
|
||||
}
|
||||
}
|
||||
}
|
||||
34
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/ArgumentValidator.cs
vendored
Normal file
34
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/ArgumentValidator.cs
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数校验类
|
||||
/// </summary>
|
||||
public static class ArgumentValidator
|
||||
{
|
||||
public static void CheckArgument(bool expression, string errorMessage)
|
||||
{
|
||||
if (!expression)
|
||||
{
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CheckNotNull(object value, string errorMessage)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnsureNull(object value, string errorMessage)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/DictionaryUtil.cs
vendored
Normal file
63
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/DictionaryUtil.cs
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 字典工具类
|
||||
/// </summary>
|
||||
public static class DictionaryUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 将字典各层次Value中的JObject和JArray转换成C#标准库中的Dictionary和List
|
||||
/// </summary>
|
||||
/// <param name="iputObj">输入字典</param>
|
||||
/// <returns>转换后的输出字典</returns>
|
||||
public static Dictionary<string, object> ObjToDictionary(Dictionary<string, object> iputObj)
|
||||
{
|
||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||
foreach (string key in iputObj.Keys)
|
||||
{
|
||||
if (iputObj[key] is JArray)
|
||||
{
|
||||
List<object> objList = ((JArray)iputObj[key]).ToObject<List<object>>();
|
||||
result.Add(key, ConvertList(objList));
|
||||
}
|
||||
else if (iputObj[key] is JObject)
|
||||
{
|
||||
Dictionary<string, object> dicObj = ((JObject)iputObj[key]).ToObject<Dictionary<string, object>>();
|
||||
result.Add(key, ObjToDictionary(dicObj));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(key, iputObj[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static List<object> ConvertList(List<object> inputList)
|
||||
{
|
||||
List<object> result = new List<object>();
|
||||
foreach (var obj in inputList)
|
||||
{
|
||||
if (obj is JArray)
|
||||
{
|
||||
List<object> listObj = ((JArray)obj).ToObject<List<object>>();
|
||||
result.Add(ConvertList(listObj));
|
||||
}
|
||||
else if (obj is JObject)
|
||||
{
|
||||
Dictionary<string, object> dicObj = ((JObject)obj).ToObject<Dictionary<string, object>>();
|
||||
result.Add(ObjToDictionary(dicObj));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(obj);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/JsonUtil.cs
vendored
Normal file
53
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/JsonUtil.cs
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using Tea;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON工具类
|
||||
/// </summary>
|
||||
public class JsonUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 将字典集合转换为Json字符串,转换过程中对于TeaModel,使用标注的字段名称而不是字段的变量名
|
||||
/// </summary>
|
||||
/// <param name="input">字典集合</param>
|
||||
/// <returns>Json字符串</returns>
|
||||
public static string ToJsonString(IDictionary<string, object> input)
|
||||
{
|
||||
IDictionary<string, object> result = new Dictionary<string, object>();
|
||||
foreach (var pair in input)
|
||||
{
|
||||
if (pair.Value is TeaModel)
|
||||
{
|
||||
result.Add(pair.Key, GetTeaModelMap((TeaModel)pair.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
return JsonConvert.SerializeObject(result);
|
||||
}
|
||||
|
||||
private static IDictionary<string, object> GetTeaModelMap(TeaModel teaModel)
|
||||
{
|
||||
|
||||
IDictionary<string, object> result = new Dictionary<string, object>();
|
||||
IDictionary<string, object> teaModelMap = teaModel.ToMap();
|
||||
foreach (var pair in teaModelMap)
|
||||
{
|
||||
if (pair.Value is TeaModel)
|
||||
{
|
||||
result.Add(pair.Key, GetTeaModelMap((TeaModel)pair.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/MultipartUtil.cs
vendored
Normal file
79
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/MultipartUtil.cs
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP multipart/form-data格式相关工具类
|
||||
/// </summary>
|
||||
public static class MultipartUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取Multipart分界符
|
||||
/// </summary>
|
||||
/// <param name="boundary">用作分界的随机字符串</param>
|
||||
/// <returns>Multipart分界符</returns>
|
||||
public static byte[] GetEntryBoundary(string boundary)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Multipart结束标记
|
||||
/// </summary>
|
||||
/// <param name="boundary">用作分界的随机字符串</param>
|
||||
/// <returns>Multipart结束标记</returns>
|
||||
public static byte[] GetEndBoundary(string boundary)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Multipart中的文本参数结构
|
||||
/// </summary>
|
||||
/// <param name="fieldName">字段名称</param>
|
||||
/// <param name="fieldValue">字段值</param>
|
||||
/// <returns>文本参数结构</returns>
|
||||
public static byte[] GetTextEntry(string fieldName, string fieldValue)
|
||||
{
|
||||
string entry = "Content-Disposition:form-data;name=\""
|
||||
+ fieldName
|
||||
+ "\"\r\nContent-Type:text/plain\r\n\r\n"
|
||||
+ fieldValue;
|
||||
return AlipayConstants.DEFAULT_CHARSET.GetBytes(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取Multipart中的文件参数结构(不含文件内容,只有文件元数据)
|
||||
/// </summary>
|
||||
/// <param name="fieldName">字段名称</param>
|
||||
/// <param name="filePath">文件路径</param>
|
||||
/// <returns>文件参数结构(不含文件内容)</returns>
|
||||
public static byte[] GetFileEntry(String fieldName, String filePath)
|
||||
{
|
||||
ArgumentValidator.CheckArgument(File.Exists(filePath),
|
||||
Path.GetFullPath(filePath) + "文件不存在");
|
||||
ArgumentValidator.CheckArgument(Path.GetFileName(filePath).Contains("."),
|
||||
"文件名必须带上正确的扩展名");
|
||||
|
||||
String entry = "Content-Disposition:form-data;name=\""
|
||||
+ fieldName
|
||||
+ "\";filename=\""
|
||||
+ Path.GetFileName(filePath)
|
||||
+ "\"\r\nContent-Type:application/octet-stream"
|
||||
+ "\r\n\r\n";
|
||||
return AlipayConstants.DEFAULT_CHARSET.GetBytes(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 往指定流中写入整个字节数组
|
||||
/// </summary>
|
||||
/// <param name="stream">流</param>
|
||||
/// <param name="content">字节数组</param>
|
||||
public static void WriteToStream(Stream stream, byte[] content)
|
||||
{
|
||||
stream.Write(content, 0, content.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/PageUtil.cs
vendored
Normal file
59
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/PageUtil.cs
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成页面信息辅助类
|
||||
/// </summary>
|
||||
public static class PageUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成表单
|
||||
/// </summary>
|
||||
/// <param name="actionUrl">表单提交链接</param>
|
||||
/// <param name="parameters">表单参数</param>
|
||||
/// <returns>表单字符串</returns>
|
||||
public static string BuildForm(string actionUrl, IDictionary<string, string> parameters)
|
||||
{
|
||||
return "<form name=\"punchout_form\" method=\"post\" action=\""
|
||||
+ actionUrl
|
||||
+ "\">\n"
|
||||
+ BuildHiddenFields(parameters)
|
||||
+ "<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >\n"
|
||||
+ "</form>\n"
|
||||
+ "<script>document.forms[0].submit();</script>";
|
||||
}
|
||||
|
||||
private static string BuildHiddenFields(IDictionary<string, string> parameters)
|
||||
{
|
||||
if (parameters == null || parameters.Count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
foreach (var pair in parameters)
|
||||
{
|
||||
if (pair.Key == null || pair.Value == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
stringBuilder.Append(BuildHiddenField(pair.Key, pair.Value));
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private static string BuildHiddenField(string key, string value)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(64);
|
||||
builder.Append("<input type=\"hidden\" name=\"");
|
||||
builder.Append(key);
|
||||
builder.Append("\" value=\"");
|
||||
//转义双引号
|
||||
String a = value.Replace("\"", """);
|
||||
builder.Append(a).Append("\">\n");
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/ResponseChecker.cs
vendored
Normal file
31
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/ResponseChecker.cs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Reflection;
|
||||
using Tea;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 响应检查工具类
|
||||
/// </summary>
|
||||
public class ResponseChecker
|
||||
{
|
||||
public const string SUB_CODE_FIELD_NAME = "SubCode";
|
||||
|
||||
/// <summary>
|
||||
/// 判断一个请求返回的响应是否成功
|
||||
/// </summary>
|
||||
/// <param name="response">响应对象</param>
|
||||
/// <returns>true:成功;false:失败</returns>
|
||||
public static bool Success(TeaModel response)
|
||||
{
|
||||
PropertyInfo propertyInfo = response.GetType().GetProperty(SUB_CODE_FIELD_NAME);
|
||||
if (propertyInfo == null)
|
||||
{
|
||||
//没有SubCode属性的响应对象,通常是那些无需跟网关远程通信的API,只要本地执行完成都视为成功
|
||||
return true;
|
||||
}
|
||||
|
||||
string subCode = (string)propertyInfo.GetValue(response);
|
||||
return string.IsNullOrEmpty(subCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
213
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/SignContentExtractor.cs
vendored
Normal file
213
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/SignContentExtractor.cs
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// 待验签原文提取器
|
||||
/// 注:此处不可使用JSON反序列化工具进行提取,会破坏原有格式,对于签名而言差个空格都会验签不通过
|
||||
/// </summary>
|
||||
public class SignContentExtractor
|
||||
{
|
||||
/// <summary>
|
||||
/// 左大括号
|
||||
/// </summary>
|
||||
public const char LEFT_BRACE = '{';
|
||||
|
||||
/// <summary>
|
||||
/// 右大括号
|
||||
/// </summary>
|
||||
public const char RIGHT_BRACE = '}';
|
||||
|
||||
/// <summary>
|
||||
/// 双引号
|
||||
/// </summary>
|
||||
public const char DOUBLE_QUOTES = '"';
|
||||
|
||||
/// <summary>
|
||||
/// 获取待验签的原文
|
||||
/// </summary>
|
||||
/// <param name="body">网关的整体响应字符串</param>
|
||||
/// <param name="method">本次调用的OpenAPI接口名称</param>
|
||||
/// <returns>待验签的原文</returns>
|
||||
public static string GetSignSourceData(string body, string method)
|
||||
{
|
||||
string rootNode = method.Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
|
||||
string errorRootNode = AlipayConstants.ERROR_RESPONSE;
|
||||
|
||||
int indexOfRootNode = body.IndexOf(rootNode, StringComparison.Ordinal);
|
||||
int indexOfErrorRoot = body.IndexOf(errorRootNode, StringComparison.Ordinal);
|
||||
|
||||
string result = null;
|
||||
if (indexOfRootNode > 0)
|
||||
{
|
||||
result = ParseSignSourceData(body, rootNode, indexOfRootNode);
|
||||
}
|
||||
else if (indexOfErrorRoot > 0)
|
||||
{
|
||||
result = ParseSignSourceData(body, errorRootNode, indexOfErrorRoot);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string ParseSignSourceData(string body, string rootNode, int indexOfRootNode)
|
||||
{
|
||||
int signDataStartIndex = indexOfRootNode + rootNode.Length + 2;
|
||||
int indexOfSign = body.IndexOf("\"" + AlipayConstants.SIGN_FIELD + "\"", StringComparison.Ordinal);
|
||||
if (indexOfSign < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SignSourceData signSourceData = ExtractSignContent(body, signDataStartIndex);
|
||||
|
||||
//如果提取的待验签原始内容后还有rootNode
|
||||
if (body.LastIndexOf(rootNode, StringComparison.Ordinal) > signSourceData.EndIndex)
|
||||
{
|
||||
throw new Exception("检测到响应报文中有重复的" + rootNode + ",验签失败。");
|
||||
}
|
||||
|
||||
return signSourceData.SourceData;
|
||||
}
|
||||
|
||||
private static SignSourceData ExtractSignContent(string str, int begin)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int beginIndex = ExtractBeginPosition(str, begin);
|
||||
if (beginIndex >= str.Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int endIndex = ExtractEndPosition(str, beginIndex);
|
||||
return new SignSourceData()
|
||||
{
|
||||
SourceData = str.Substring(beginIndex, endIndex - beginIndex),
|
||||
BeginIndex = beginIndex,
|
||||
EndIndex = endIndex
|
||||
};
|
||||
}
|
||||
|
||||
private static int ExtractBeginPosition(string responseString, int begin)
|
||||
{
|
||||
int beginPosition = begin;
|
||||
//找到第一个左大括号(对应响应的是JSON对象的情况:普通调用OpenAPI响应明文)
|
||||
//或者双引号(对应响应的是JSON字符串的情况:加密调用OpenAPI响应Base64串),作为待验签内容的起点
|
||||
while (beginPosition < responseString.Length
|
||||
&& responseString[beginPosition] != LEFT_BRACE
|
||||
&& responseString[beginPosition] != DOUBLE_QUOTES)
|
||||
{
|
||||
++beginPosition;
|
||||
}
|
||||
return beginPosition;
|
||||
}
|
||||
|
||||
private static int ExtractEndPosition(string responseString, int beginPosition)
|
||||
{
|
||||
//提取明文验签内容终点
|
||||
if (responseString[beginPosition] == LEFT_BRACE)
|
||||
{
|
||||
return ExtractJsonObjectEndPosition(responseString, beginPosition);
|
||||
}
|
||||
//提取密文验签内容终点
|
||||
else
|
||||
{
|
||||
return ExtractJsonBase64ValueEndPosition(responseString, beginPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private static int ExtractJsonBase64ValueEndPosition(string responseString, int beginPosition)
|
||||
{
|
||||
for (int index = beginPosition; index < responseString.Length; ++index)
|
||||
{
|
||||
//找到第2个双引号作为终点,由于中间全部是Base64编码的密文,所以不会有干扰的特殊字符
|
||||
if (responseString[index] == DOUBLE_QUOTES && index != beginPosition)
|
||||
{
|
||||
return index + 1;
|
||||
}
|
||||
}
|
||||
//如果没有找到第2个双引号,说明验签内容片段提取失败,直接尝试选取剩余整个响应字符串进行验签
|
||||
return responseString.Length;
|
||||
}
|
||||
|
||||
private static int ExtractJsonObjectEndPosition(string responseString, int beginPosition)
|
||||
{
|
||||
//记录当前尚未发现配对闭合的大括号
|
||||
LinkedList<char> braces = new LinkedList<char>();
|
||||
//记录当前字符是否在双引号中
|
||||
bool inQuotes = false;
|
||||
//记录当前字符前面连续的转义字符个数
|
||||
int consecutiveEscapeCount = 0;
|
||||
//从待验签字符的起点开始遍历后续字符串,找出待验签字符串的终止点,终点即是与起点{配对的}
|
||||
for (int index = beginPosition; index < responseString.Length; ++index)
|
||||
{
|
||||
//提取当前字符
|
||||
char currentChar = responseString[index];
|
||||
|
||||
//如果当前字符是"且前面有偶数个转义标记(0也是偶数)
|
||||
if (currentChar == DOUBLE_QUOTES && consecutiveEscapeCount % 2 == 0)
|
||||
{
|
||||
//是否在引号中的状态取反
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
//如果当前字符是{且不在引号中
|
||||
else if (currentChar == LEFT_BRACE && !inQuotes)
|
||||
{
|
||||
//将该{加入未闭合括号中
|
||||
braces.AddLast(LEFT_BRACE);
|
||||
}
|
||||
//如果当前字符是}且不在引号中
|
||||
else if (currentChar == RIGHT_BRACE && !inQuotes)
|
||||
{
|
||||
//弹出一个未闭合括号
|
||||
braces.RemoveLast();
|
||||
//如果弹出后,未闭合括号为空,说明已经找到终点
|
||||
if (braces.Count == 0)
|
||||
{
|
||||
return index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
//如果当前字符是转义字符
|
||||
if (currentChar == '\\')
|
||||
{
|
||||
//连续转义字符个数+1
|
||||
++consecutiveEscapeCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
//连续转义字符个数置0
|
||||
consecutiveEscapeCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//如果没有找到配对的闭合括号,说明验签内容片段提取失败,直接尝试选取剩余整个响应字符串进行验签
|
||||
return responseString.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从响应字符串中提取到的待验签原始内容
|
||||
/// </summary>
|
||||
public class SignSourceData
|
||||
{
|
||||
/// <summary>
|
||||
/// 待验签原始内容
|
||||
/// </summary>
|
||||
public string SourceData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 待验签原始内容在响应字符串中的起始位置
|
||||
/// </summary>
|
||||
public int BeginIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 待验签原始内容在响应字符串中的结束位置
|
||||
/// </summary>
|
||||
public int EndIndex { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
260
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/Signer.cs
vendored
Normal file
260
vendor/alipaysdk/easysdk/kernel/csharp/EasySDKKernel/Kernel/Util/Signer.cs
vendored
Normal file
@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Alipay.EasySDK.Kernel.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA256WithRSA签名器
|
||||
/// </summary>
|
||||
public class Signer
|
||||
{
|
||||
/// <summary>
|
||||
/// 计算签名
|
||||
/// </summary>
|
||||
/// <param name="content">待签名的内容</param>
|
||||
/// <param name="privateKeyPem">私钥</param>
|
||||
/// <returns>签名值的Base64串</returns>
|
||||
public static string Sign(string content, string privateKeyPem)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RSACryptoServiceProvider rsaService = BuildRSAServiceProvider(Convert.FromBase64String(privateKeyPem)))
|
||||
{
|
||||
byte[] data = AlipayConstants.DEFAULT_CHARSET.GetBytes(content);
|
||||
byte[] sign = rsaService.SignData(data, "SHA256");
|
||||
return Convert.ToBase64String(sign);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMessage = "签名遭遇异常,content=" + content + " privateKeySize=" + privateKeyPem.Length + " reason=" + e.Message;
|
||||
Console.WriteLine(errorMessage);
|
||||
throw new Exception(errorMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证签名
|
||||
/// </summary>
|
||||
/// <param name="content">待验签的内容</param>
|
||||
/// <param name="sign">签名值的Base64串</param>
|
||||
/// <param name="publicKeyPem">支付宝公钥</param>
|
||||
/// <returns>true:验证成功;false:验证失败</returns>
|
||||
public static bool Verify(string content, string sign, string publicKeyPem)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RSACryptoServiceProvider rsaService = new RSACryptoServiceProvider())
|
||||
{
|
||||
rsaService.PersistKeyInCsp = false;
|
||||
rsaService.ImportParameters(ConvertFromPemPublicKey(publicKeyPem));
|
||||
return rsaService.VerifyData(AlipayConstants.DEFAULT_CHARSET.GetBytes(content),
|
||||
"SHA256", Convert.FromBase64String(sign));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMessage = "验签遭遇异常,content=" + content + " sign=" + sign +
|
||||
" publicKey=" + publicKeyPem + " reason=" + e.Message;
|
||||
Console.WriteLine(errorMessage);
|
||||
throw new Exception(errorMessage, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对参数集合进行验签
|
||||
/// </summary>
|
||||
/// <param name="parameters">参数集合</param>
|
||||
/// <param name="publicKeyPem">支付宝公钥</param>
|
||||
/// <returns>true:验证成功;false:验证失败</returns>
|
||||
public static bool VerifyParams(Dictionary<string, string> parameters, string publicKeyPem)
|
||||
{
|
||||
string sign = parameters[AlipayConstants.SIGN_FIELD];
|
||||
parameters.Remove(AlipayConstants.SIGN_FIELD);
|
||||
parameters.Remove(AlipayConstants.SIGN_TYPE_FIELD);
|
||||
|
||||
string content = GetSignContent(parameters);
|
||||
|
||||
return Verify(content, sign, publicKeyPem);
|
||||
}
|
||||
|
||||
private static string GetSignContent(IDictionary<string, string> parameters)
|
||||
{
|
||||
// 把字典按Key的字母顺序排序
|
||||
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
|
||||
IEnumerator<KeyValuePair<string, string>> iterator = sortedParams.GetEnumerator();
|
||||
|
||||
// 把所有参数名和参数值串在一起
|
||||
StringBuilder query = new StringBuilder("");
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
string key = iterator.Current.Key;
|
||||
string value = iterator.Current.Value;
|
||||
query.Append(key).Append("=").Append(value).Append("&");
|
||||
}
|
||||
string content = query.ToString().Substring(0, query.Length - 1);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private static RSAParameters ConvertFromPemPublicKey(string pemPublickKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pemPublickKey))
|
||||
{
|
||||
throw new Exception("PEM格式公钥不可为空。");
|
||||
}
|
||||
|
||||
//移除干扰文本
|
||||
pemPublickKey = pemPublickKey.Replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
|
||||
|
||||
byte[] keyData = Convert.FromBase64String(pemPublickKey);
|
||||
bool keySize1024 = (keyData.Length == 162);
|
||||
bool keySize2048 = (keyData.Length == 294);
|
||||
if (!(keySize1024 || keySize2048))
|
||||
{
|
||||
throw new Exception("公钥长度只支持1024和2048。");
|
||||
}
|
||||
byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
|
||||
byte[] pemPublicExponent = new byte[3];
|
||||
Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
|
||||
Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
|
||||
RSAParameters para = new RSAParameters
|
||||
{
|
||||
Modulus = pemModulus,
|
||||
Exponent = pemPublicExponent
|
||||
};
|
||||
return para;
|
||||
}
|
||||
|
||||
private static RSACryptoServiceProvider BuildRSAServiceProvider(byte[] privateKey)
|
||||
{
|
||||
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
|
||||
byte bt = 0;
|
||||
ushort twobytes = 0;
|
||||
int elems = 0;
|
||||
|
||||
//set up stream to decode the asn.1 encoded RSA private key
|
||||
//wrap Memory Stream with BinaryReader for easy reading
|
||||
using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(privateKey)))
|
||||
{
|
||||
twobytes = binaryReader.ReadUInt16();
|
||||
//data read as little endian order (actual data order for Sequence is 30 81)
|
||||
if (twobytes == 0x8130)
|
||||
{
|
||||
//advance 1 byte
|
||||
binaryReader.ReadByte();
|
||||
}
|
||||
else if (twobytes == 0x8230)
|
||||
{
|
||||
//advance 2 bytes
|
||||
binaryReader.ReadInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
twobytes = binaryReader.ReadUInt16();
|
||||
//version number
|
||||
if (twobytes != 0x0102)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
bt = binaryReader.ReadByte();
|
||||
if (bt != 0x00)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//all private key components are Integer sequences
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
MODULUS = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
E = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
D = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
P = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
Q = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
DP = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
DQ = binaryReader.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binaryReader);
|
||||
IQ = binaryReader.ReadBytes(elems);
|
||||
|
||||
//create RSACryptoServiceProvider instance and initialize with public key
|
||||
RSACryptoServiceProvider rsaService = new RSACryptoServiceProvider();
|
||||
RSAParameters rsaParams = new RSAParameters
|
||||
{
|
||||
Modulus = MODULUS,
|
||||
Exponent = E,
|
||||
D = D,
|
||||
P = P,
|
||||
Q = Q,
|
||||
DP = DP,
|
||||
DQ = DQ,
|
||||
InverseQ = IQ
|
||||
};
|
||||
rsaService.ImportParameters(rsaParams);
|
||||
return rsaService;
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetIntegerSize(BinaryReader binaryReader)
|
||||
{
|
||||
byte bt = 0;
|
||||
byte lowbyte = 0x00;
|
||||
byte highbyte = 0x00;
|
||||
int count = 0;
|
||||
|
||||
bt = binaryReader.ReadByte();
|
||||
|
||||
//expect integer
|
||||
if (bt != 0x02)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
bt = binaryReader.ReadByte();
|
||||
|
||||
if (bt == 0x81)
|
||||
{
|
||||
//data size in next byte
|
||||
count = binaryReader.ReadByte();
|
||||
}
|
||||
else if (bt == 0x82)
|
||||
{
|
||||
//data size in next 2 bytes
|
||||
highbyte = binaryReader.ReadByte();
|
||||
lowbyte = binaryReader.ReadByte();
|
||||
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
|
||||
count = BitConverter.ToInt32(modint, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we already have the data size
|
||||
count = bt;
|
||||
}
|
||||
while (binaryReader.ReadByte() == 0x00)
|
||||
{ //remove high order zeros in data
|
||||
count -= 1;
|
||||
}
|
||||
//last ReadByte wasn't a removed zero, so back up a byte
|
||||
binaryReader.BaseStream.Seek(-1, SeekOrigin.Current);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user