using System; 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 { /// /// RSA 算法工具类。 /// 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[] ConvertPkcs8PrivateKeyToByteArray(string privateKey) { 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[] ConvertPkcs8PublicKeyToByteArray(string publicKey) { 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); } /// /// 使用私钥基于 SHA-256 算法生成签名。 /// /// PKCS#8 私钥字节数组。 /// 待签名的数据字节数组。 /// 签名字节数组。 public static byte[] SignWithSHA256(byte[] privateKeyBytes, byte[] msgBytes) { if (privateKeyBytes == null) throw new ArgumentNullException(nameof(privateKeyBytes)); if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes)); RsaKeyParameters rsaKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes); return SignWithSHA256(rsaKeyParams, msgBytes); } /// /// 使用私钥基于 SHA-256 算法生成签名。 /// /// PKCS#8 私钥(PEM 格式)。 /// 待签名的文本数据。 /// 经 Base64 编码的签名。 public static string SignWithSHA256(string privateKey, string message) { if (privateKey == null) throw new ArgumentNullException(nameof(privateKey)); if (message == null) throw new ArgumentNullException(nameof(message)); byte[] privateKeyBytes = ConvertPkcs8PrivateKeyToByteArray(privateKey); byte[] msgBytes = Encoding.UTF8.GetBytes(message); byte[] signBytes = SignWithSHA256(privateKeyBytes, msgBytes); return Convert.ToBase64String(signBytes); } /// /// 使用公钥基于 SHA-256 算法验证签名。 /// /// PKCS#8 公钥字节数据。 /// 待验证的数据字节数据。 /// 待验证的签名字节数据。 /// 验证结果。 public static bool VerifyWithSHA256(byte[] publicKeyBytes, byte[] msgBytes, byte[] signBytes) { if (publicKeyBytes == null) throw new ArgumentNullException(nameof(publicKeyBytes)); if (msgBytes == null) throw new ArgumentNullException(nameof(msgBytes)); if (signBytes == null) throw new ArgumentNullException(nameof(signBytes)); RsaKeyParameters rsaKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes); return VerifyWithSHA256(rsaKeyParams, msgBytes, signBytes); } /// /// 使用公钥基于 SHA-256 算法验证签名。 /// /// PKCS#8 公钥(PEM 格式)。 /// 待验证的文本数据。 /// 经 Base64 编码的待验证的签名。 /// 验证结果。 public static bool VerifyWithSHA256(string publicKey, string message, string signature) { if (publicKey == null) throw new ArgumentNullException(nameof(publicKey)); if (message == null) throw new ArgumentNullException(nameof(message)); if (signature == null) throw new ArgumentNullException(nameof(signature)); byte[] publicKeyBytes = ConvertPkcs8PublicKeyToByteArray(publicKey); byte[] msgBytes = Encoding.UTF8.GetBytes(message); byte[] signBytes = Convert.FromBase64String(signature); return VerifyWithSHA256(publicKeyBytes, msgBytes, signBytes); } /// /// 使用私钥基于 ECB 模式解密数据。 /// /// PKCS#8 私钥字节数据。 /// 待解密的数据字节数据。 /// 填充算法。(默认值:) /// 解密后的数据字节数组。 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 rsaKeyParams = (RsaKeyParameters)PrivateKeyFactory.CreateKey(privateKeyBytes); return DecryptWithECB(rsaKeyParams, cipherBytes, paddingAlgorithm); } /// /// 使用私钥基于 ECB 模式解密数据。 /// /// PKCS#8 私钥(PEM 格式)。 /// 经 Base64 编码的待解密数据。 /// 填充算法。(默认值:) /// 解密后的文本数据。 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 = ConvertPkcs8PrivateKeyToByteArray(privateKey); byte[] cipherBytes = Convert.FromBase64String(cipherText); byte[] plainBytes = DecryptWithECB(privateKeyBytes, cipherBytes, paddingAlgorithm); return Encoding.UTF8.GetString(plainBytes); } /// /// 使用公钥基于 ECB 模式加密数据。 /// /// PKCS#8 公钥字节数据。 /// 待加密的数据字节数据。 /// 填充算法。(默认值:) /// 加密后的数据字节数组。 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 rsaKeyParams = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes); return EncryptWithECB(rsaKeyParams, plainBytes, paddingAlgorithm); } /// /// 使用公钥基于 ECB 模式加密数据。 /// /// PKCS#8 公钥(PEM 格式)。 /// 待加密的文本数据。 /// 填充算法。(默认值:) /// 经 Base64 编码的加密数据。 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 = ConvertPkcs8PublicKeyToByteArray(publicKey); byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); byte[] cipherBytes = EncryptWithECB(publicKeyBytes, plainBytes, paddingAlgorithm); return Convert.ToBase64String(cipherBytes); } } }