DotNetCore.SKIT.FlurlHttpCl.../src/SKIT.FlurlHttpClient.Wechat.TenpayBusiness/Utilities/RSAUtility.cs

204 lines
11 KiB
C#
Raw Normal View History

2022-11-09 20:48:03 +08:00
using System;
2022-05-09 19:28:47 +08:00
using System.Text;
using System.Text.RegularExpressions;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Utilities
{
/// <summary>
/// RSA 算法工具类。
/// </summary>
public static class RSAUtility
{
private const string RSA_CIPHER_ALGORITHM_ECB = "RSA/ECB";
private const string RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1 = "OAEPWITHSHA1ANDMGF1PADDING";
private const string RSA_SIGNER_ALGORITHM_SHA256 = "SHA-256withRSA";
private static byte[] ConvertPrivateKeyPkcs8PemToByteArray(string privateKey)
2022-11-09 23:02:53 +08:00
{
privateKey = privateKey
.Replace("-----BEGIN PRIVATE KEY-----", string.Empty)
.Replace("-----END PRIVATE KEY-----", string.Empty);
privateKey = Regex.Replace(privateKey, "\\s+", string.Empty);
return Convert.FromBase64String(privateKey);
}
private static byte[] ConvertPublicKeyPkcs8PemToByteArray(string publicKey)
2022-11-09 23:02:53 +08:00
{
publicKey = publicKey
.Replace("-----BEGIN PUBLIC KEY-----", string.Empty)
.Replace("-----END PUBLIC KEY-----", string.Empty);
publicKey = Regex.Replace(publicKey, "\\s+", string.Empty);
return Convert.FromBase64String(publicKey);
}
private static byte[] SignWithSHA256(RsaKeyParameters rsaPrivateKeyParams, byte[] msgBytes)
{
ISigner signer = SignerUtilities.GetSigner(RSA_SIGNER_ALGORITHM_SHA256);
signer.Init(true, rsaPrivateKeyParams);
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
return signer.GenerateSignature();
}
private static bool VerifyWithSHA256(RsaKeyParameters rsaPublicKeyParams, byte[] msgBytes, byte[] signBytes)
{
ISigner signer = SignerUtilities.GetSigner(RSA_SIGNER_ALGORITHM_SHA256);
signer.Init(false, rsaPublicKeyParams);
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
return signer.VerifySignature(signBytes);
}
private static byte[] DecryptWithECB(RsaKeyParameters rsaPrivateKeyParams, byte[] cipherBytes, string paddingAlgorithm)
{
IBufferedCipher cipher = CipherUtilities.GetCipher($"{RSA_CIPHER_ALGORITHM_ECB}/{paddingAlgorithm}");
cipher.Init(false, rsaPrivateKeyParams);
return cipher.DoFinal(cipherBytes);
}
private static byte[] EncryptWithECB(RsaKeyParameters rsaPublicKeyParams, byte[] msgBytes, string paddingAlgorithm)
{
IBufferedCipher cipher = CipherUtilities.GetCipher($"{RSA_CIPHER_ALGORITHM_ECB}/{paddingAlgorithm}");
cipher.Init(true, rsaPublicKeyParams);
return cipher.DoFinal(msgBytes);
}
2022-05-09 19:28:47 +08:00
/// <summary>
/// 使用私钥基于 SHA-256 算法生成签名。
/// </summary>
/// <param name="privateKeyBytes">PKCS#8 私钥字节数组。</param>
2022-11-09 23:02:53 +08:00
/// <param name="msgBytes">待签名的数据字节数组。</param>
2022-05-09 19:28:47 +08:00
/// <returns>签名字节数组。</returns>
2022-11-09 23:02:53 +08:00
public static byte[] SignWithSHA256(byte[] privateKeyBytes, byte[] msgBytes)
2022-05-09 19:28:47 +08:00
{
if (privateKeyBytes == null) throw new ArgumentNullException(nameof(privateKeyBytes));
2022-11-09 23:02:53 +08:00
if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes));
2022-05-09 19:28:47 +08:00
RsaKeyParameters rsaPrivateKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes);
return SignWithSHA256(rsaPrivateKeyParams, msgBytes);
2022-05-09 19:28:47 +08:00
}
/// <summary>
/// 使用私钥基于 SHA-256 算法生成签名。
/// </summary>
/// <param name="privateKey">PKCS#8 私钥PEM 格式)。</param>
2022-11-09 23:02:53 +08:00
/// <param name="message">待签名的文本数据。</param>
2022-05-09 19:28:47 +08:00
/// <returns>经 Base64 编码的签名。</returns>
2022-11-09 23:02:53 +08:00
public static string SignWithSHA256(string privateKey, string message)
2022-05-09 19:28:47 +08:00
{
if (privateKey == null) throw new ArgumentNullException(nameof(privateKey));
2022-11-09 23:02:53 +08:00
if (message == null) throw new ArgumentNullException(nameof(message));
2022-05-09 19:28:47 +08:00
byte[] privateKeyBytes = ConvertPrivateKeyPkcs8PemToByteArray(privateKey);
2022-11-09 23:02:53 +08:00
byte[] msgBytes = Encoding.UTF8.GetBytes(message);
byte[] signBytes = SignWithSHA256(privateKeyBytes, msgBytes);
2022-05-09 19:28:47 +08:00
return Convert.ToBase64String(signBytes);
}
/// <summary>
/// 使用公钥基于 SHA-256 算法验证签名。
/// </summary>
/// <param name="publicKeyBytes">PKCS#8 公钥字节数据。</param>
2022-11-09 23:02:53 +08:00
/// <param name="msgBytes">待验证的数据字节数据。</param>
2022-05-09 19:28:47 +08:00
/// <param name="signBytes">待验证的签名字节数据。</param>
/// <returns>验证结果。</returns>
2022-11-09 23:02:53 +08:00
public static bool VerifyWithSHA256(byte[] publicKeyBytes, byte[] msgBytes, byte[] signBytes)
2022-05-09 19:28:47 +08:00
{
if (publicKeyBytes == null) throw new ArgumentNullException(nameof(publicKeyBytes));
2022-11-09 23:02:53 +08:00
if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes));
2022-05-09 19:28:47 +08:00
if (signBytes == null) throw new ArgumentNullException(nameof(signBytes));
RsaKeyParameters rsaPublicKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
return VerifyWithSHA256(rsaPublicKeyParams, msgBytes, signBytes);
2022-05-09 19:28:47 +08:00
}
/// <summary>
/// 使用公钥基于 SHA-256 算法验证签名。
/// </summary>
/// <param name="publicKey">PKCS#8 公钥PEM 格式)。</param>
2022-11-09 23:02:53 +08:00
/// <param name="message">待验证的文本数据。</param>
2022-05-09 19:28:47 +08:00
/// <param name="signature">经 Base64 编码的待验证的签名。</param>
/// <returns>验证结果。</returns>
2022-11-09 23:02:53 +08:00
public static bool VerifyWithSHA256(string publicKey, string message, string signature)
2022-05-09 19:28:47 +08:00
{
if (publicKey == null) throw new ArgumentNullException(nameof(publicKey));
2022-11-09 23:02:53 +08:00
if (message == null) throw new ArgumentNullException(nameof(message));
2022-05-09 19:28:47 +08:00
if (signature == null) throw new ArgumentNullException(nameof(signature));
byte[] publicKeyBytes = ConvertPublicKeyPkcs8PemToByteArray(publicKey);
2022-11-09 23:02:53 +08:00
byte[] msgBytes = Encoding.UTF8.GetBytes(message);
2022-05-09 19:28:47 +08:00
byte[] signBytes = Convert.FromBase64String(signature);
2022-11-09 23:02:53 +08:00
return VerifyWithSHA256(publicKeyBytes, msgBytes, signBytes);
2022-05-09 19:28:47 +08:00
}
/// <summary>
/// 使用私钥基于 ECB 模式解密数据。
/// </summary>
/// <param name="privateKeyBytes">PKCS#8 私钥字节数据。</param>
/// <param name="cipherBytes">待解密的数据字节数据。</param>
/// <param name="paddingAlgorithm">填充算法。(默认值:<see cref="RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1"/></param>
/// <returns>解密后的数据字节数组。</returns>
public static byte[] DecryptWithECB(byte[] privateKeyBytes, byte[] cipherBytes, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
{
if (privateKeyBytes == null) throw new ArgumentNullException(nameof(privateKeyBytes));
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
RsaKeyParameters rsaPrivateKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes);
return DecryptWithECB(rsaPrivateKeyParams, cipherBytes, paddingAlgorithm);
2022-05-09 19:28:47 +08:00
}
/// <summary>
/// 使用私钥基于 ECB 模式解密数据。
/// </summary>
/// <param name="privateKey">PKCS#8 私钥PEM 格式)。</param>
/// <param name="cipherText">经 Base64 编码的待解密数据。</param>
/// <param name="paddingAlgorithm">填充算法。(默认值:<see cref="RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1"/></param>
/// <returns>解密后的文本数据。</returns>
public static string DecryptWithECB(string privateKey, string cipherText, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
{
if (privateKey == null) throw new ArgumentNullException(nameof(privateKey));
if (cipherText == null) throw new ArgumentNullException(nameof(cipherText));
byte[] privateKeyBytes = ConvertPrivateKeyPkcs8PemToByteArray(privateKey);
2022-05-09 19:28:47 +08:00
byte[] cipherBytes = Convert.FromBase64String(cipherText);
byte[] plainBytes = DecryptWithECB(privateKeyBytes, cipherBytes, paddingAlgorithm);
return Encoding.UTF8.GetString(plainBytes);
}
/// <summary>
/// 使用公钥基于 ECB 模式加密数据。
/// </summary>
/// <param name="publicKeyBytes">PKCS#8 公钥字节数据。</param>
/// <param name="plainBytes">待加密的数据字节数据。</param>
/// <param name="paddingAlgorithm">填充算法。(默认值:<see cref="RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1"/></param>
/// <returns>加密后的数据字节数组。</returns>
public static byte[] EncryptWithECB(byte[] publicKeyBytes, byte[] plainBytes, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
{
if (publicKeyBytes == null) throw new ArgumentNullException(nameof(publicKeyBytes));
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
RsaKeyParameters rsaPublicKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes);
return EncryptWithECB(rsaPublicKeyParams, plainBytes, paddingAlgorithm);
2022-05-09 19:28:47 +08:00
}
/// <summary>
/// 使用公钥基于 ECB 模式加密数据。
/// </summary>
/// <param name="publicKey">PKCS#8 公钥PEM 格式)。</param>
/// <param name="plainText">待加密的文本数据。</param>
/// <param name="paddingAlgorithm">填充算法。(默认值:<see cref="RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1"/></param>
/// <returns>经 Base64 编码的加密数据。</returns>
public static string EncryptWithECB(string publicKey, string plainText, string paddingAlgorithm = RSA_CIPHER_PADDING_OAEP_WITH_SHA1_AND_MGF1)
{
if (publicKey == null) throw new ArgumentNullException(nameof(publicKey));
if (plainText == null) throw new ArgumentNullException(nameof(plainText));
byte[] publicKeyBytes = ConvertPublicKeyPkcs8PemToByteArray(publicKey);
2022-05-09 19:28:47 +08:00
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
byte[] cipherBytes = EncryptWithECB(publicKeyBytes, plainBytes, paddingAlgorithm);
return Convert.ToBase64String(cipherBytes);
}
}
}