using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Encodings; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace ProjectManagementSystem.Common.Function { public class RSAHelper { //参考连接:https://www.jianshu.com/p/faefcc58c79b //工具网址1:https://the-x.cn/certificate/PemToXml.aspx //工具网址2:https://superdry.apphb.com/tools/online-rsa-key-converter //需要依赖一个第三方库,叫BouncyCastle ;在线获取安装包的代码是:PM >Install-Package BouncyCastle //安装步骤:VS中选择 工具(T)---》NuGet包管理器(N)---》程序包管理器控制台(O)---》然后数据以上代码即可 #region Demo示例 public static void Demo() { string xmlgy = ""; string xmlsy = ""; string xmlmdata = ""; string xmljdata = ""; string xmlsign = ""; string xmlresult = ""; string pemgy = ""; string pemsy = ""; string pemmdata = ""; string pemjdata = ""; string pemsign = ""; string pemresult = ""; RSAHelper.GetXMLRSAKeys(out xmlsy, out xmlgy); RSAHelper.GetPEMRSAKeys(out pemsy, out pemgy); string str1 = "1234567890"; Console.WriteLine("===================xml==================="); Console.WriteLine("===================xml公钥"); Console.WriteLine(xmlgy); Console.WriteLine("===================xml私钥"); Console.WriteLine(xmlsy); Console.WriteLine("===================xml公钥加密后的数据"); xmlmdata = RSAHelper.XMLRSAEncrypt(xmlgy, str1); Console.WriteLine(xmlmdata); Console.WriteLine("===================xml私钥解密后的字符"); xmljdata = RSAHelper.XMLRSADecrypt(xmlsy, xmlmdata); Console.WriteLine(xmljdata); Console.WriteLine("===================xml私钥加签后的sign"); xmlsign = RSAHelper.XMLSign(xmlmdata, xmlsy); Console.WriteLine(xmlsign); Console.WriteLine("===================xml公钥验签后的结果"); xmlresult = RSAHelper.XMLSignCheck(xmlmdata, xmlsign, xmlgy).ToString(); Console.WriteLine(xmlresult); Console.WriteLine("===================xml==================="); Console.WriteLine("=========================================*****========================================="); Console.WriteLine("===================pem==================="); Console.WriteLine("===================pem公钥"); Console.WriteLine(pemgy); Console.WriteLine("===================pem私钥"); Console.WriteLine(pemsy); Console.WriteLine("===================pem公钥加密后的数据"); pemmdata = RSAHelper.PEMRSAEncrypt(pemgy, str1); Console.WriteLine(pemmdata); Console.WriteLine("===================pem私钥解密后的字符"); pemjdata = RSAHelper.PEMRSADecrypt(pemsy, pemmdata); Console.WriteLine(pemjdata); Console.WriteLine("===================pem私钥加签后的sign"); pemsign = RSAHelper.PEMSign(pemmdata, pemsy); Console.WriteLine(pemsign); Console.WriteLine("===================pem公钥验签后的结果"); pemresult = RSAHelper.PEMSignCheck(pemmdata, pemsign, pemgy).ToString(); Console.WriteLine(pemresult); Console.WriteLine("===================pem==================="); } #endregion #region 获取RSA密钥对 /// /// 获取XML格式密钥对 /// /// xml私钥 /// xml公钥 public static void GetXMLRSAKeys(out string xmlprikey, out string xmlpubkey) { try { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); xmlprikey = rsa.ToXmlString(true); xmlpubkey = rsa.ToXmlString(false); } catch (Exception ex) { throw ex; } } /// /// 获取PEM格式密钥对 /// /// pem私钥 /// pem公钥 public static void GetPEMRSAKeys(out string pemprikey, out string pempubkey) { try { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); pemprikey = XMLToPEM_Pri(rsa.ToXmlString(true)); pempubkey = XMLToPEM_Pub(rsa.ToXmlString(false)); } catch (Exception ex) { throw ex; } } #endregion #region RSA加密 /// /// 使用XML格式加密 /// /// xml公钥 /// 需要加密的字符串 /// 返回加密后的字符串 public static string XMLRSAEncrypt(string xmlpubkey, string encryptstr) { byte[] PlainTextBArray; byte[] CypherTextBArray; string Result; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(xmlpubkey); PlainTextBArray = (new UTF8Encoding()).GetBytes(encryptstr); CypherTextBArray = rsa.Encrypt(PlainTextBArray, false); Result = Convert.ToBase64String(CypherTextBArray); return Result; } /// /// 使用PEM格式加密 /// /// pem公钥 /// 需要加密的字符串 /// 返回加密后的字符串 public static string PEMRSAEncrypt(string pempubkey, string encryptstr) { StringReader sr = new StringReader(pempubkey); AsymmetricKeyParameter publickey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter; if (publickey == null) throw new Exception("PEM格式公钥不能为空"); try { var engine = new Pkcs1Encoding(new RsaEngine()); engine.Init(true, publickey); byte[] bytes = Encoding.UTF8.GetBytes(encryptstr);//Encoding.UTF8.GetBytes(data); bytes = engine.ProcessBlock(bytes, 0, bytes.Length); return Convert.ToBase64String(bytes);// Convert.ToBase64String(bytes); } catch { throw new Exception("加密失败"); } } #endregion #region RSA解密 /// /// 使用XML格式解密 /// /// xml格式私钥 /// 需要解密的字符串 /// 返回解密后的字符串 public static string XMLRSADecrypt(string xmlprikey, string decryptstr) { try { byte[] PlainTextBArray; byte[] DypherTextBArray; string Result; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(xmlprikey); PlainTextBArray = Convert.FromBase64String(decryptstr); DypherTextBArray = rsa.Decrypt(PlainTextBArray, false); Result = (new UTF8Encoding()).GetString(DypherTextBArray); return Result; } catch (Exception ex) { throw ex; } } /// /// 使用PEM格式解密 /// /// pem格式私钥 /// 需要解密的字符串 /// 返回解密后的字符串 public static string PEMRSADecrypt(string pemprikey, string decryptstr) { byte[] bytes = Convert.FromBase64String(decryptstr);// Convert.FromBase64String(data); StringReader sr = new StringReader(pemprikey); AsymmetricKeyParameter prikey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter; if (prikey == null) throw new Exception("私钥读取失败"); try { var engine = new Pkcs1Encoding(new RsaEngine()); engine.Init(false, prikey); bytes = engine.ProcessBlock(bytes, 0, bytes.Length); return Encoding.UTF8.GetString(bytes);////Encoding.UTF8.GetString(bytes); } catch { throw new Exception("解密失败"); } } #endregion #region RSA签名 /// /// 使用XML格式的私钥加签 /// /// 需要加签的字符串 /// xml格式的私钥 /// 返回签名 public static string XMLSign(string str, string xmlprikey) { //根据需要加签时的哈希算法转化成对应的hash字符节 byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str); var sha256 = new SHA256CryptoServiceProvider(); byte[] rgbHash = sha256.ComputeHash(bt); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(xmlprikey); RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。 byte[] inArray = formatter.CreateSignature(rgbHash); return Convert.ToBase64String(inArray); } /// /// 使用PEM格式的私钥加签 /// /// 需要加签的字符串 /// pem格式的私钥 /// 返回签名 public static string PEMSign(string str, string pemprikey) { pemprikey = PEMToXML_All(pemprikey, true); //根据需要加签时的哈希算法转化成对应的hash字符节 byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str); var sha256 = new SHA256CryptoServiceProvider(); byte[] rgbHash = sha256.ComputeHash(bt); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(pemprikey); RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。 byte[] inArray = formatter.CreateSignature(rgbHash); return Convert.ToBase64String(inArray); } #endregion #region RSA验签 /// /// 使用XML格式的公钥验签 /// /// 需要验签的字符串 /// 签名 /// xml格式的公钥 /// 是/否 public static bool XMLSignCheck(string str, string sign, string xmlpubkey) { try { byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str); var sha256 = new SHA256CryptoServiceProvider(); byte[] rgbHash = sha256.ComputeHash(bt); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(xmlpubkey); RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); deformatter.SetHashAlgorithm("SHA256"); byte[] rgbSignature = Convert.FromBase64String(sign); if (deformatter.VerifySignature(rgbHash, rgbSignature)) { return true; } return false; } catch { return false; } } /// /// 使用XML格式的公钥验签 /// /// 需要验签的字符串 /// 签名 /// pem格式的公钥 /// 是/否 public static bool PEMSignCheck(string str, string sign, string pempubkey) { try { pempubkey = PEMToXML_All(pempubkey, false); byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str); var sha256 = new SHA256CryptoServiceProvider(); byte[] rgbHash = sha256.ComputeHash(bt); RSACryptoServiceProvider key = new RSACryptoServiceProvider(); key.FromXmlString(pempubkey); RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); deformatter.SetHashAlgorithm("SHA256"); byte[] rgbSignature = Convert.FromBase64String(sign); if (deformatter.VerifySignature(rgbHash, rgbSignature)) { return true; } return false; } catch (Exception) { return false; } } #endregion #region XML转PEM /// /// XML格式的公钥转PEM格式的公钥 /// /// xml格式的公钥 /// pem格式的公钥 public static string XMLToPEM_Pub(string xmlpubkey) { var rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(xmlpubkey); var p = rsa.ExportParameters(false); RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent)); SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key); byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded(); string publicKey = Convert.ToBase64String(serializedPublicBytes); return Format(publicKey, true); } /// /// XML格式的私钥转PEM格式的私钥 /// /// xml格式的私钥 /// pem格式的私钥 public static string XMLToPEM_Pri(string xmlprikey) { var rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(xmlprikey); var p = rsa.ExportParameters(true); var key = new RsaPrivateCrtKeyParameters( new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D), new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ), new BigInteger(1, p.InverseQ)); PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(key); byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded(); string privateKey = Convert.ToBase64String(serializedPrivateBytes); return Format(privateKey, false); } /// /// 格式化公钥/私钥 /// /// 生成的公钥/私钥 /// true:公钥 false:私钥 /// PEM格式的公钥/私钥 private static string Format(string key, bool type) { string result = string.Empty; int length = key.Length / 64; for (int i = 0; i < length; i++) { int start = i * 64; result = result + key.Substring(start, 64) + "\r\n"; } result = result + key.Substring(length * 64); //if (type) //{ // result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n"); // result += "\r\n-----END PUBLIC KEY-----"; //} //else //{ // result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n"); // result += "\r\n-----END PRIVATE KEY-----"; //} return result; } #endregion #region PEM转XML /// /// PEM格式的密钥转XML格式 /// /// pem格式的密钥 /// true:私钥;false:公钥 /// xml格式密钥 public static string PEMToXML_All(string pemkey, bool isprikey) { if (isprikey) { pemkey = pemkey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", ""); } else { pemkey = pemkey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", ""); } string rsaKey = string.Empty; object pemObject = null; RSAParameters rsaPara = new RSAParameters(); using (StringReader sReader = new StringReader(pemkey)) { var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader); pemObject = pemReader.ReadObject(); } //RSA私钥 if (isprikey) { RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pemkey)); rsaPara = new RSAParameters { Modulus = key.Modulus.ToByteArrayUnsigned(), Exponent = key.PublicExponent.ToByteArrayUnsigned(), D = key.Exponent.ToByteArrayUnsigned(), P = key.P.ToByteArrayUnsigned(), Q = key.Q.ToByteArrayUnsigned(), DP = key.DP.ToByteArrayUnsigned(), DQ = key.DQ.ToByteArrayUnsigned(), InverseQ = key.QInv.ToByteArrayUnsigned(), }; } //RSA公钥 else { RsaKeyParameters key = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pemkey)); rsaPara.Modulus = key.Modulus.ToByteArrayUnsigned(); rsaPara.Exponent = key.Exponent.ToByteArrayUnsigned(); } RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaPara); using (StringWriter sw = new StringWriter()) { sw.Write(rsa.ToXmlString(isprikey ? true : false)); rsaKey = sw.ToString(); } return rsaKey; } #endregion } }