RSAHelper.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. using Org.BouncyCastle.Asn1.Pkcs;
  2. using Org.BouncyCastle.Asn1.X509;
  3. using Org.BouncyCastle.Crypto;
  4. using Org.BouncyCastle.Crypto.Encodings;
  5. using Org.BouncyCastle.Crypto.Engines;
  6. using Org.BouncyCastle.Crypto.Parameters;
  7. using Org.BouncyCastle.Math;
  8. using Org.BouncyCastle.OpenSsl;
  9. using Org.BouncyCastle.Pkcs;
  10. using Org.BouncyCastle.Security;
  11. using Org.BouncyCastle.X509;
  12. using System;
  13. using System.IO;
  14. using System.Security.Cryptography;
  15. using System.Text;
  16. namespace ProjectManagementSystem.Common.Function
  17. {
  18. public class RSAHelper
  19. {
  20. //参考连接:https://www.jianshu.com/p/faefcc58c79b
  21. //工具网址1:https://the-x.cn/certificate/PemToXml.aspx
  22. //工具网址2:https://superdry.apphb.com/tools/online-rsa-key-converter
  23. //需要依赖一个第三方库,叫BouncyCastle ;在线获取安装包的代码是:PM >Install-Package BouncyCastle
  24. //安装步骤:VS中选择 工具(T)---》NuGet包管理器(N)---》程序包管理器控制台(O)---》然后数据以上代码即可
  25. #region Demo示例
  26. public static void Demo()
  27. {
  28. string xmlgy = "";
  29. string xmlsy = "";
  30. string xmlmdata = "";
  31. string xmljdata = "";
  32. string xmlsign = "";
  33. string xmlresult = "";
  34. string pemgy = "";
  35. string pemsy = "";
  36. string pemmdata = "";
  37. string pemjdata = "";
  38. string pemsign = "";
  39. string pemresult = "";
  40. RSAHelper.GetXMLRSAKeys(out xmlsy, out xmlgy);
  41. RSAHelper.GetPEMRSAKeys(out pemsy, out pemgy);
  42. string str1 = "1234567890";
  43. Console.WriteLine("===================xml===================");
  44. Console.WriteLine("===================xml公钥");
  45. Console.WriteLine(xmlgy);
  46. Console.WriteLine("===================xml私钥");
  47. Console.WriteLine(xmlsy);
  48. Console.WriteLine("===================xml公钥加密后的数据");
  49. xmlmdata = RSAHelper.XMLRSAEncrypt(xmlgy, str1);
  50. Console.WriteLine(xmlmdata);
  51. Console.WriteLine("===================xml私钥解密后的字符");
  52. xmljdata = RSAHelper.XMLRSADecrypt(xmlsy, xmlmdata);
  53. Console.WriteLine(xmljdata);
  54. Console.WriteLine("===================xml私钥加签后的sign");
  55. xmlsign = RSAHelper.XMLSign(xmlmdata, xmlsy);
  56. Console.WriteLine(xmlsign);
  57. Console.WriteLine("===================xml公钥验签后的结果");
  58. xmlresult = RSAHelper.XMLSignCheck(xmlmdata, xmlsign, xmlgy).ToString();
  59. Console.WriteLine(xmlresult);
  60. Console.WriteLine("===================xml===================");
  61. Console.WriteLine("=========================================*****=========================================");
  62. Console.WriteLine("===================pem===================");
  63. Console.WriteLine("===================pem公钥");
  64. Console.WriteLine(pemgy);
  65. Console.WriteLine("===================pem私钥");
  66. Console.WriteLine(pemsy);
  67. Console.WriteLine("===================pem公钥加密后的数据");
  68. pemmdata = RSAHelper.PEMRSAEncrypt(pemgy, str1);
  69. Console.WriteLine(pemmdata);
  70. Console.WriteLine("===================pem私钥解密后的字符");
  71. pemjdata = RSAHelper.PEMRSADecrypt(pemsy, pemmdata);
  72. Console.WriteLine(pemjdata);
  73. Console.WriteLine("===================pem私钥加签后的sign");
  74. pemsign = RSAHelper.PEMSign(pemmdata, pemsy);
  75. Console.WriteLine(pemsign);
  76. Console.WriteLine("===================pem公钥验签后的结果");
  77. pemresult = RSAHelper.PEMSignCheck(pemmdata, pemsign, pemgy).ToString();
  78. Console.WriteLine(pemresult);
  79. Console.WriteLine("===================pem===================");
  80. }
  81. #endregion
  82. #region 获取RSA密钥对
  83. /// <summary>
  84. /// 获取XML格式密钥对
  85. /// </summary>
  86. /// <param name="xmlprikey">xml私钥</param>
  87. /// <param name="xmlpubkey">xml公钥</param>
  88. public static void GetXMLRSAKeys(out string xmlprikey, out string xmlpubkey)
  89. {
  90. try
  91. {
  92. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  93. xmlprikey = rsa.ToXmlString(true);
  94. xmlpubkey = rsa.ToXmlString(false);
  95. }
  96. catch (Exception ex)
  97. {
  98. throw ex;
  99. }
  100. }
  101. /// <summary>
  102. /// 获取PEM格式密钥对
  103. /// </summary>
  104. /// <param name="pemprikey">pem私钥</param>
  105. /// <param name="pempubkey">pem公钥</param>
  106. public static void GetPEMRSAKeys(out string pemprikey, out string pempubkey)
  107. {
  108. try
  109. {
  110. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  111. pemprikey = XMLToPEM_Pri(rsa.ToXmlString(true));
  112. pempubkey = XMLToPEM_Pub(rsa.ToXmlString(false));
  113. }
  114. catch (Exception ex)
  115. {
  116. throw ex;
  117. }
  118. }
  119. #endregion
  120. #region RSA加密
  121. /// <summary>
  122. /// 使用XML格式加密
  123. /// </summary>
  124. /// <param name="xmlpubkey">xml公钥</param>
  125. /// <param name="encryptstr">需要加密的字符串</param>
  126. /// <returns>返回加密后的字符串</returns>
  127. public static string XMLRSAEncrypt(string xmlpubkey, string encryptstr)
  128. {
  129. byte[] PlainTextBArray;
  130. byte[] CypherTextBArray;
  131. string Result;
  132. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  133. rsa.FromXmlString(xmlpubkey);
  134. PlainTextBArray = (new UTF8Encoding()).GetBytes(encryptstr);
  135. CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
  136. Result = Convert.ToBase64String(CypherTextBArray);
  137. return Result;
  138. }
  139. /// <summary>
  140. /// 使用PEM格式加密
  141. /// </summary>
  142. /// <param name="pempubkey">pem公钥</param>
  143. /// <param name="encryptstr">需要加密的字符串</param>
  144. /// <returns>返回加密后的字符串</returns>
  145. public static string PEMRSAEncrypt(string pempubkey, string encryptstr)
  146. {
  147. StringReader sr = new StringReader(pempubkey);
  148. AsymmetricKeyParameter publickey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter;
  149. if (publickey == null)
  150. throw new Exception("PEM格式公钥不能为空");
  151. try
  152. {
  153. var engine = new Pkcs1Encoding(new RsaEngine());
  154. engine.Init(true, publickey);
  155. byte[] bytes = Encoding.UTF8.GetBytes(encryptstr);//Encoding.UTF8.GetBytes(data);
  156. bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
  157. return Convert.ToBase64String(bytes);// Convert.ToBase64String(bytes);
  158. }
  159. catch
  160. {
  161. throw new Exception("加密失败");
  162. }
  163. }
  164. #endregion
  165. #region RSA解密
  166. /// <summary>
  167. /// 使用XML格式解密
  168. /// </summary>
  169. /// <param name="xmlprikey">xml格式私钥</param>
  170. /// <param name="decryptstr">需要解密的字符串</param>
  171. /// <returns>返回解密后的字符串</returns>
  172. public static string XMLRSADecrypt(string xmlprikey, string decryptstr)
  173. {
  174. try
  175. {
  176. byte[] PlainTextBArray;
  177. byte[] DypherTextBArray;
  178. string Result;
  179. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  180. rsa.FromXmlString(xmlprikey);
  181. PlainTextBArray = Convert.FromBase64String(decryptstr);
  182. DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
  183. Result = (new UTF8Encoding()).GetString(DypherTextBArray);
  184. return Result;
  185. }
  186. catch (Exception ex)
  187. {
  188. throw ex;
  189. }
  190. }
  191. /// <summary>
  192. /// 使用PEM格式解密
  193. /// </summary>
  194. /// <param name="pemprikey">pem格式私钥</param>
  195. /// <param name="decryptstr">需要解密的字符串</param>
  196. /// <returns>返回解密后的字符串</returns>
  197. public static string PEMRSADecrypt(string pemprikey, string decryptstr)
  198. {
  199. byte[] bytes = Convert.FromBase64String(decryptstr);// Convert.FromBase64String(data);
  200. StringReader sr = new StringReader(pemprikey);
  201. AsymmetricKeyParameter prikey = new PemReader(sr).ReadObject() as AsymmetricKeyParameter;
  202. if (prikey == null)
  203. throw new Exception("私钥读取失败");
  204. try
  205. {
  206. var engine = new Pkcs1Encoding(new RsaEngine());
  207. engine.Init(false, prikey);
  208. bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
  209. return Encoding.UTF8.GetString(bytes);////Encoding.UTF8.GetString(bytes);
  210. }
  211. catch
  212. {
  213. throw new Exception("解密失败");
  214. }
  215. }
  216. #endregion
  217. #region RSA签名
  218. /// <summary>
  219. /// 使用XML格式的私钥加签
  220. /// </summary>
  221. /// <param name="str">需要加签的字符串</param>
  222. /// <param name="xmlprikey">xml格式的私钥</param>
  223. /// <returns>返回签名</returns>
  224. public static string XMLSign(string str, string xmlprikey)
  225. {
  226. //根据需要加签时的哈希算法转化成对应的hash字符节
  227. byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
  228. var sha256 = new SHA256CryptoServiceProvider();
  229. byte[] rgbHash = sha256.ComputeHash(bt);
  230. RSACryptoServiceProvider key = new RSACryptoServiceProvider();
  231. key.FromXmlString(xmlprikey);
  232. RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
  233. formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
  234. byte[] inArray = formatter.CreateSignature(rgbHash);
  235. return Convert.ToBase64String(inArray);
  236. }
  237. /// <summary>
  238. /// 使用PEM格式的私钥加签
  239. /// </summary>
  240. /// <param name="str">需要加签的字符串</param>
  241. /// <param name="pemprikey">pem格式的私钥</param>
  242. /// <returns>返回签名</returns>
  243. public static string PEMSign(string str, string pemprikey)
  244. {
  245. pemprikey = PEMToXML_All(pemprikey, true);
  246. //根据需要加签时的哈希算法转化成对应的hash字符节
  247. byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
  248. var sha256 = new SHA256CryptoServiceProvider();
  249. byte[] rgbHash = sha256.ComputeHash(bt);
  250. RSACryptoServiceProvider key = new RSACryptoServiceProvider();
  251. key.FromXmlString(pemprikey);
  252. RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
  253. formatter.SetHashAlgorithm("SHA256"); //此处是你需要加签的hash算法,需要和上边你计算的hash值的算法一致,不然会报错。
  254. byte[] inArray = formatter.CreateSignature(rgbHash);
  255. return Convert.ToBase64String(inArray);
  256. }
  257. #endregion
  258. #region RSA验签
  259. /// <summary>
  260. /// 使用XML格式的公钥验签
  261. /// </summary>
  262. /// <param name="str">需要验签的字符串</param>
  263. /// <param name="sign">签名</param>
  264. /// <param name="xmlpubkey">xml格式的公钥</param>
  265. /// <returns>是/否</returns>
  266. public static bool XMLSignCheck(string str, string sign, string xmlpubkey)
  267. {
  268. try
  269. {
  270. byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
  271. var sha256 = new SHA256CryptoServiceProvider();
  272. byte[] rgbHash = sha256.ComputeHash(bt);
  273. RSACryptoServiceProvider key = new RSACryptoServiceProvider();
  274. key.FromXmlString(xmlpubkey);
  275. RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
  276. deformatter.SetHashAlgorithm("SHA256");
  277. byte[] rgbSignature = Convert.FromBase64String(sign);
  278. if (deformatter.VerifySignature(rgbHash, rgbSignature))
  279. {
  280. return true;
  281. }
  282. return false;
  283. }
  284. catch
  285. {
  286. return false;
  287. }
  288. }
  289. /// <summary>
  290. /// 使用XML格式的公钥验签
  291. /// </summary>
  292. /// <param name="str">需要验签的字符串</param>
  293. /// <param name="sign">签名</param>
  294. /// <param name="pempubkey">pem格式的公钥</param>
  295. /// <returns>是/否</returns>
  296. public static bool PEMSignCheck(string str, string sign, string pempubkey)
  297. {
  298. try
  299. {
  300. pempubkey = PEMToXML_All(pempubkey, false);
  301. byte[] bt = Encoding.GetEncoding("utf-8").GetBytes(str);
  302. var sha256 = new SHA256CryptoServiceProvider();
  303. byte[] rgbHash = sha256.ComputeHash(bt);
  304. RSACryptoServiceProvider key = new RSACryptoServiceProvider();
  305. key.FromXmlString(pempubkey);
  306. RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
  307. deformatter.SetHashAlgorithm("SHA256");
  308. byte[] rgbSignature = Convert.FromBase64String(sign);
  309. if (deformatter.VerifySignature(rgbHash, rgbSignature))
  310. {
  311. return true;
  312. }
  313. return false;
  314. }
  315. catch (Exception)
  316. {
  317. return false;
  318. }
  319. }
  320. #endregion
  321. #region XML转PEM
  322. /// <summary>
  323. /// XML格式的公钥转PEM格式的公钥
  324. /// </summary>
  325. /// <param name="xmlpubkey">xml格式的公钥</param>
  326. /// <returns>pem格式的公钥</returns>
  327. public static string XMLToPEM_Pub(string xmlpubkey)
  328. {
  329. var rsa = new RSACryptoServiceProvider();
  330. rsa.FromXmlString(xmlpubkey);
  331. var p = rsa.ExportParameters(false);
  332. RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent));
  333. SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
  334. byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
  335. string publicKey = Convert.ToBase64String(serializedPublicBytes);
  336. return Format(publicKey, true);
  337. }
  338. /// <summary>
  339. /// XML格式的私钥转PEM格式的私钥
  340. /// </summary>
  341. /// <param name="xmlprikey">xml格式的私钥</param>
  342. /// <returns>pem格式的私钥</returns>
  343. public static string XMLToPEM_Pri(string xmlprikey)
  344. {
  345. var rsa = new RSACryptoServiceProvider();
  346. rsa.FromXmlString(xmlprikey);
  347. var p = rsa.ExportParameters(true);
  348. var key = new RsaPrivateCrtKeyParameters(
  349. new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D),
  350. new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ),
  351. new BigInteger(1, p.InverseQ));
  352. PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(key);
  353. byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
  354. string privateKey = Convert.ToBase64String(serializedPrivateBytes);
  355. return Format(privateKey, false);
  356. }
  357. /// <summary>
  358. /// 格式化公钥/私钥
  359. /// </summary>
  360. /// <param name="key">生成的公钥/私钥</param>
  361. /// <param name="type">true:公钥 false:私钥</param>
  362. /// <returns>PEM格式的公钥/私钥</returns>
  363. private static string Format(string key, bool type)
  364. {
  365. string result = string.Empty;
  366. int length = key.Length / 64;
  367. for (int i = 0; i < length; i++)
  368. {
  369. int start = i * 64;
  370. result = result + key.Substring(start, 64) + "\r\n";
  371. }
  372. result = result + key.Substring(length * 64);
  373. //if (type)
  374. //{
  375. // result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n");
  376. // result += "\r\n-----END PUBLIC KEY-----";
  377. //}
  378. //else
  379. //{
  380. // result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n");
  381. // result += "\r\n-----END PRIVATE KEY-----";
  382. //}
  383. return result;
  384. }
  385. #endregion
  386. #region PEM转XML
  387. /// <summary>
  388. /// PEM格式的密钥转XML格式
  389. /// </summary>
  390. /// <param name="pemkey">pem格式的密钥</param>
  391. /// <param name="isprikey">true:私钥;false:公钥</param>
  392. /// <returns>xml格式密钥</returns>
  393. public static string PEMToXML_All(string pemkey, bool isprikey)
  394. {
  395. if (isprikey)
  396. {
  397. pemkey = pemkey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "");
  398. }
  399. else
  400. {
  401. pemkey = pemkey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
  402. }
  403. string rsaKey = string.Empty;
  404. object pemObject = null;
  405. RSAParameters rsaPara = new RSAParameters();
  406. using (StringReader sReader = new StringReader(pemkey))
  407. {
  408. var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader);
  409. pemObject = pemReader.ReadObject();
  410. }
  411. //RSA私钥
  412. if (isprikey)
  413. {
  414. RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(pemkey));
  415. rsaPara = new RSAParameters
  416. {
  417. Modulus = key.Modulus.ToByteArrayUnsigned(),
  418. Exponent = key.PublicExponent.ToByteArrayUnsigned(),
  419. D = key.Exponent.ToByteArrayUnsigned(),
  420. P = key.P.ToByteArrayUnsigned(),
  421. Q = key.Q.ToByteArrayUnsigned(),
  422. DP = key.DP.ToByteArrayUnsigned(),
  423. DQ = key.DQ.ToByteArrayUnsigned(),
  424. InverseQ = key.QInv.ToByteArrayUnsigned(),
  425. };
  426. }
  427. //RSA公钥
  428. else
  429. {
  430. RsaKeyParameters key = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pemkey));
  431. rsaPara.Modulus = key.Modulus.ToByteArrayUnsigned();
  432. rsaPara.Exponent = key.Exponent.ToByteArrayUnsigned();
  433. }
  434. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  435. rsa.ImportParameters(rsaPara);
  436. using (StringWriter sw = new StringWriter())
  437. {
  438. sw.Write(rsa.ToXmlString(isprikey ? true : false));
  439. rsaKey = sw.ToString();
  440. }
  441. return rsaKey;
  442. }
  443. #endregion
  444. }
  445. }