mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-12-29 09:54:44 +08:00
feat(core): 抽离公共的算法工具类
This commit is contained in:
@@ -56,10 +56,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
plainJson = Utilities.AesUtil.DecryptWithGCM(
|
||||
aesKey: client.MerchantV3Secret,
|
||||
nonce: resource.Nonce,
|
||||
associatedData: resource.AssociatedData,
|
||||
plainJson = Utilities.AESUtility.DecryptWithGCM(
|
||||
key: client.MerchantV3Secret,
|
||||
iv: resource.Nonce,
|
||||
aad: resource.AssociatedData,
|
||||
cipherText: resource.CipherText
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileHash))
|
||||
request.FileHash = Utilities.Sha256Util.Hash(request.FileBytes).ToLower();
|
||||
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileContentType))
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileHash))
|
||||
request.FileHash = Utilities.Sha256Util.Hash(request.FileBytes).ToLower();
|
||||
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileContentType))
|
||||
{
|
||||
@@ -81,7 +81,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".mp4";
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileHash))
|
||||
request.FileHash = Utilities.Sha256Util.Hash(request.FileBytes).ToLower();
|
||||
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileContentType))
|
||||
{
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileHash))
|
||||
request.FileHash = Utilities.Sha256Util.Hash(request.FileBytes).ToLower();
|
||||
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
|
||||
|
||||
if (string.IsNullOrEmpty(request.FileContentType))
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
|
||||
string nonce = Guid.NewGuid().ToString("N");
|
||||
string package = $"prepay_id={prepayId}";
|
||||
string sign = Utilities.RsaUtil.SignWithSHA256(
|
||||
string sign = Utilities.RSAUtility.SignWithSHA256(
|
||||
privateKey: client.MerchantCertPrivateKey,
|
||||
plainText: $"{appId}\n{timestamp}\n{nonce}\n{package}"
|
||||
);
|
||||
@@ -97,7 +97,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
|
||||
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
|
||||
string nonce = Guid.NewGuid().ToString("N");
|
||||
string sign = Utilities.RsaUtil.SignWithSHA256(
|
||||
string sign = Utilities.RSAUtility.SignWithSHA256(
|
||||
privateKey: client.MerchantCertPrivateKey,
|
||||
plainText: $"{appId}\n{timestamp}\n{nonce}\n{prepayId}"
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
accountValidationModel.AccountNameEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
accountValidationModel.AccountNameEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
accountValidationModel.AccountNameEncryptedData
|
||||
);
|
||||
@@ -53,7 +53,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
accountValidationModel.AccountNumberEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
accountValidationModel.AccountNumberEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
accountValidationModel.AccountNumberEncryptedData!
|
||||
);
|
||||
@@ -100,7 +100,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
downloadBillModel.EncryptKeyEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
downloadBillModel.EncryptKeyEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
downloadBillModel.EncryptKeyEncryptedData
|
||||
);
|
||||
@@ -144,7 +144,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
response.PayerPhoneEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
response.PayerPhoneEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
response.PayerPhoneEncryptedData!
|
||||
);
|
||||
@@ -188,10 +188,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
certificateModel.EncryptCertificate.CipherText = Utilities.AesUtil.DecryptWithGCM(
|
||||
aesKey: client.MerchantV3Secret,
|
||||
nonce: certificateModel.EncryptCertificate.Nonce,
|
||||
associatedData: certificateModel.EncryptCertificate.AssociatedData,
|
||||
certificateModel.EncryptCertificate.CipherText = Utilities.AESUtility.DecryptWithGCM(
|
||||
key: client.MerchantV3Secret,
|
||||
iv: certificateModel.EncryptCertificate.Nonce,
|
||||
aad: certificateModel.EncryptCertificate.AssociatedData,
|
||||
cipherText: certificateModel.EncryptCertificate.CipherText
|
||||
);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
complaintModel.PayerPhoneEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
complaintModel.PayerPhoneEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
complaintModel.PayerPhoneEncryptedData!
|
||||
);
|
||||
@@ -290,7 +290,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
guideModel.UserNameEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
guideModel.UserNameEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
guideModel.UserNameEncryptedData
|
||||
);
|
||||
@@ -305,7 +305,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
try
|
||||
{
|
||||
guideModel.UserMobileEncryptedData = Utilities.RsaUtil.DecryptWithECB(
|
||||
guideModel.UserMobileEncryptedData = Utilities.RSAUtility.DecryptWithECB(
|
||||
client.MerchantCertPrivateKey,
|
||||
guideModel.UserMobileEncryptedData
|
||||
);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
|
||||
try
|
||||
{
|
||||
return Utilities.RsaUtil.VerifyWithSHA256(
|
||||
return Utilities.RSAUtility.VerifyWithSHA256(
|
||||
publicKey: publicKey,
|
||||
plainText: GetPlainTextForSignature(response),
|
||||
signature: response.WechatpaySignature
|
||||
@@ -58,7 +58,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
|
||||
try
|
||||
{
|
||||
return Utilities.RsaUtil.VerifyWithSHA256ByCertificate(
|
||||
return Utilities.RSAUtility.VerifyWithSHA256ByCertificate(
|
||||
certificate: certificate,
|
||||
plainText: GetPlainTextForSignature(response),
|
||||
signature: response.WechatpaySignature
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Interceptors
|
||||
{
|
||||
try
|
||||
{
|
||||
signText = Utilities.RsaUtil.SignWithSHA256(_mchCertPk, plainText);
|
||||
signText = Utilities.RSAUtility.SignWithSHA256(_mchCertPk, plainText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -9,32 +9,32 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
/// <summary>
|
||||
/// AES 算法工具类。
|
||||
/// </summary>
|
||||
public static class AesUtil
|
||||
public static class AESUtility
|
||||
{
|
||||
private const int AES_TAG_LENGH_BIT = 128;
|
||||
private const int AES_BLOCK_SIZE = 128;
|
||||
private const string AES_GCM_CIPHER_ALG = "AES/GCM/NoPadding";
|
||||
|
||||
/// <summary>
|
||||
/// 基于 GCM 模式解密数据。
|
||||
/// </summary>
|
||||
/// <param name="aesKeyBytes">AES 密钥字节数组。</param>
|
||||
/// <param name="associatedDataBytes">附加数据包字节数组。</param>
|
||||
/// <param name="nonceBytes">加密使用的随机串初始化向量字节数组。</param>
|
||||
/// <param name="keyBytes">AES 密钥字节数组。</param>
|
||||
/// <param name="ivBytes">加密使用的初始化向量字节数组。</param>
|
||||
/// <param name="aadBytes">加密使用的附加数据包字节数组。</param>
|
||||
/// <param name="cipherBytes">待解密数据字节数组。</param>
|
||||
/// <returns>解密后的数据字节数组。</returns>
|
||||
public static byte[] DecryptWithGCM(byte[] aesKeyBytes, byte[] nonceBytes, byte[] associatedDataBytes, byte[] cipherBytes)
|
||||
public static byte[] DecryptWithGCM(byte[] keyBytes, byte[] ivBytes, byte[] aadBytes, byte[] cipherBytes)
|
||||
{
|
||||
if (aesKeyBytes == null) throw new ArgumentNullException(nameof(aesKeyBytes));
|
||||
if (nonceBytes == null) throw new ArgumentNullException(nameof(nonceBytes));
|
||||
if (associatedDataBytes == null) throw new ArgumentNullException(nameof(associatedDataBytes));
|
||||
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
||||
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
|
||||
if (aadBytes == null) throw new ArgumentNullException(nameof(aadBytes));
|
||||
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||
|
||||
IBufferedCipher cipher = CipherUtilities.GetCipher(AES_GCM_CIPHER_ALG);
|
||||
ICipherParameters aeadParams = new AeadParameters(
|
||||
new KeyParameter(aesKeyBytes),
|
||||
AES_TAG_LENGH_BIT,
|
||||
nonceBytes,
|
||||
associatedDataBytes
|
||||
new KeyParameter(keyBytes),
|
||||
AES_BLOCK_SIZE,
|
||||
ivBytes,
|
||||
aadBytes
|
||||
);
|
||||
cipher.Init(false, aeadParams);
|
||||
byte[] plainBytes = new byte[cipher.GetOutputSize(cipherBytes.Length)];
|
||||
@@ -46,21 +46,21 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
/// <summary>
|
||||
/// 基于 GCM 模式解密数据。
|
||||
/// </summary>
|
||||
/// <param name="aesKey">AES 密钥。</param>
|
||||
/// <param name="nonce">加密使用的随机串初始化向量。</param>
|
||||
/// <param name="associatedData">附加数据包。</param>
|
||||
/// <param name="key">AES 密钥。</param>
|
||||
/// <param name="iv">加密使用的初始化向量。</param>
|
||||
/// <param name="aad">加密使用的附加数据包。</param>
|
||||
/// <param name="cipherText">经 Base64 编码后的待解密数据。</param>
|
||||
/// <returns>解密后的文本数据。</returns>
|
||||
public static string DecryptWithGCM(string aesKey, string nonce, string? associatedData, string cipherText)
|
||||
public static string DecryptWithGCM(string key, string iv, string? aad, string cipherText)
|
||||
{
|
||||
if (aesKey == null) throw new ArgumentNullException(nameof(aesKey));
|
||||
if (nonce == null) throw new ArgumentNullException(nameof(nonce));
|
||||
if (key == null) throw new ArgumentNullException(nameof(key));
|
||||
if (iv == null) throw new ArgumentNullException(nameof(iv));
|
||||
if (cipherText == null) throw new ArgumentNullException(nameof(cipherText));
|
||||
|
||||
byte[] plainBytes = DecryptWithGCM(
|
||||
aesKeyBytes: Encoding.UTF8.GetBytes(aesKey),
|
||||
nonceBytes: Encoding.UTF8.GetBytes(nonce),
|
||||
associatedDataBytes: Encoding.UTF8.GetBytes(associatedData ?? string.Empty),
|
||||
keyBytes: Encoding.UTF8.GetBytes(key),
|
||||
ivBytes: Encoding.UTF8.GetBytes(iv),
|
||||
aadBytes: Encoding.UTF8.GetBytes(aad ?? string.Empty),
|
||||
cipherBytes: Convert.FromBase64String(cipherText)
|
||||
);
|
||||
return Encoding.UTF8.GetString(plainBytes);
|
||||
@@ -13,7 +13,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
/// <summary>
|
||||
/// RSA 算法工具类。
|
||||
/// </summary>
|
||||
public static class RsaUtil
|
||||
public static class RSAUtility
|
||||
{
|
||||
// REF: https://github.com/bcgit/bc-csharp/blob/master/crypto/src/security/CipherUtilities.cs
|
||||
private const string RSA_CIPHER_ALG = "RSA/ECB/PKCS1";
|
||||
@@ -91,7 +91,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
/// <summary>
|
||||
/// 使用证书基于 SHA-256 算法验证签名。
|
||||
/// </summary>
|
||||
/// <param name="publicKey">证书(cer 格式)。</param>
|
||||
/// <param name="certificate">证书(cer 格式)。</param>
|
||||
/// <param name="plainText">待验证的文本数据。</param>
|
||||
/// <param name="signature">经 Base64 编码的待验证的签名。</param>
|
||||
/// <returns>验证结果。</returns>
|
||||
44
src/SKIT.FlurlHttpClient.Wechat/Security/HMACSHA1Utility.cs
Normal file
44
src/SKIT.FlurlHttpClient.Wechat/Security/HMACSHA1Utility.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// HMAC-SHA-1 算法工具类。
|
||||
/// </summary>
|
||||
public static class HMACSHA1Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
/// </summary>
|
||||
/// <param name="secretBytes">密钥字节数组。</param>
|
||||
/// <param name="bytes">信息字节数组。</param>
|
||||
/// <returns>信息摘要。</returns>
|
||||
public static string Hash(byte[] secretBytes, byte[] bytes)
|
||||
{
|
||||
if (secretBytes == null) throw new ArgumentNullException(nameof(secretBytes));
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
using HMAC hmac = new HMACSHA1(secretBytes);
|
||||
byte[] hashBytes = hmac.ComputeHash(bytes);
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
/// </summary>
|
||||
/// <param name="secret">密钥。</param>
|
||||
/// <param name="message">文本信息。</param>
|
||||
/// <returns>信息摘要。</returns>
|
||||
public static string Hash(string secret, string message)
|
||||
{
|
||||
if (secret == null) throw new ArgumentNullException(nameof(secret));
|
||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||
|
||||
byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(message);
|
||||
return Hash(secretBytes, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// HMAC-SHA-1 算法工具类。
|
||||
/// HMAC-SHA-256 算法工具类。
|
||||
/// </summary>
|
||||
public static class HmacSha256Util
|
||||
public static class HMACSHA256Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
39
src/SKIT.FlurlHttpClient.Wechat/Security/MD5Utility.cs
Normal file
39
src/SKIT.FlurlHttpClient.Wechat/Security/MD5Utility.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// MD5 算法工具类。
|
||||
/// </summary>
|
||||
public static class MD5Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
/// </summary>
|
||||
/// <param name="bytes">信息字节数组。</param>
|
||||
/// <returns>信息摘要。</returns>
|
||||
public static string Hash(byte[] bytes)
|
||||
{
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
using MD5 md5 = MD5.Create();
|
||||
byte[] hashBytes = md5.ComputeHash(bytes);
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
/// </summary>
|
||||
/// <param name="message">文本信息。</param>
|
||||
/// <returns>信息摘要。</returns>
|
||||
public static string Hash(string message)
|
||||
{
|
||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(message);
|
||||
return Hash(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA-1 算法工具类。
|
||||
/// </summary>
|
||||
public static class Sha1Util
|
||||
public static class SHA1Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
namespace SKIT.FlurlHttpClient.Wechat.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA-256 算法工具类。
|
||||
/// </summary>
|
||||
public static class Sha256Util
|
||||
public static class SHA256Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取信息摘要。
|
||||
@@ -19,10 +18,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
|
||||
{
|
||||
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
|
||||
|
||||
IDigest digest = new Sha256Digest();
|
||||
byte[] hashBytes = new byte[digest.GetDigestSize()];
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
digest.DoFinal(hashBytes, 0);
|
||||
using SHA256 sha = SHA256.Create();
|
||||
byte[] hashBytes = sha.ComputeHash(bytes);
|
||||
return BitConverter.ToString(hashBytes).Replace("-", "");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user