RSAHelper.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6. namespace MySystem
  7. {
  8. /// <summary>
  9. /// RSA加解密 使用OpenSSL的公钥加密/私钥解密
  10. /// 作者:李志强
  11. /// 创建时间:2017年10月30日15:50:14
  12. /// QQ:501232752
  13. /// </summary>
  14. public class RSAHelper
  15. {
  16. private readonly RSA _privateKeyRsaProvider;
  17. private readonly RSA _publicKeyRsaProvider;
  18. private readonly HashAlgorithmName _hashAlgorithmName;
  19. private readonly Encoding _encoding;
  20. /// <summary>
  21. /// 实例化RSAHelper
  22. /// </summary>
  23. /// <param name="rsaType">加密算法类型 RSA SHA1;RSA2 SHA256 密钥长度至少为2048</param>
  24. /// <param name="encoding">编码类型</param>
  25. /// <param name="privateKey">私钥</param>
  26. /// <param name="publicKey">公钥</param>
  27. public RSAHelper(RSAType rsaType, Encoding encoding, string privateKey, string publicKey = null)
  28. {
  29. _encoding = encoding;
  30. if (!string.IsNullOrEmpty(privateKey))
  31. {
  32. _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey);
  33. }
  34. if (!string.IsNullOrEmpty(publicKey))
  35. {
  36. _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey);
  37. }
  38. _hashAlgorithmName = rsaType == RSAType.RSA ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256;
  39. }
  40. #region 使用私钥签名
  41. /// <summary>
  42. /// 使用私钥签名
  43. /// </summary>
  44. /// <param name="data">原始数据</param>
  45. /// <returns></returns>
  46. public string Sign(string data)
  47. {
  48. byte[] dataBytes = _encoding.GetBytes(data);
  49. var signatureBytes = _privateKeyRsaProvider.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1);
  50. return Convert.ToBase64String(signatureBytes);
  51. }
  52. #endregion
  53. #region 使用公钥验证签名
  54. /// <summary>
  55. /// 使用公钥验证签名
  56. /// </summary>
  57. /// <param name="data">原始数据</param>
  58. /// <param name="sign">签名</param>
  59. /// <returns></returns>
  60. public bool Verify(string data, string sign)
  61. {
  62. byte[] dataBytes = _encoding.GetBytes(data);
  63. byte[] signBytes = Convert.FromBase64String(sign);
  64. var verify = _publicKeyRsaProvider.VerifyData(dataBytes, signBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1);
  65. return verify;
  66. }
  67. #endregion
  68. #region 解密
  69. public string Decrypt(string cipherText)
  70. {
  71. if (_privateKeyRsaProvider == null)
  72. {
  73. throw new Exception("_privateKeyRsaProvider is null");
  74. }
  75. return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText), RSAEncryptionPadding.Pkcs1));
  76. }
  77. #endregion
  78. #region 加密
  79. public string Encrypt(string text)
  80. {
  81. if (_publicKeyRsaProvider == null)
  82. {
  83. throw new Exception("_publicKeyRsaProvider is null");
  84. }
  85. return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1));
  86. }
  87. public string Encrypt2(string text)
  88. {
  89. if (_publicKeyRsaProvider == null)
  90. {
  91. throw new Exception("_publicKeyRsaProvider is null");
  92. }
  93. byte[] textByte = Encoding.UTF8.GetBytes(text);
  94. if(textByte.Length > 64)
  95. {
  96. List<byte> contentTmp = new List<byte>();
  97. List<byte> buffer = new List<byte>();
  98. for (int i = 0; i < textByte.Length; i++)
  99. {
  100. buffer.Add(textByte[i]);
  101. if ((i + 1) % 64 == 0 || i == textByte.Length - 1)
  102. {
  103. contentTmp.AddRange(_publicKeyRsaProvider.Encrypt(buffer.ToArray(), RSAEncryptionPadding.Pkcs1));
  104. buffer = new List<byte>();
  105. }
  106. }
  107. return Convert.ToBase64String(contentTmp.ToArray());
  108. }
  109. return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1));
  110. }
  111. #endregion
  112. #region 使用私钥创建RSA实例
  113. public RSA CreateRsaProviderFromPrivateKey(string privateKey)
  114. {
  115. var privateKeyBits = Convert.FromBase64String(privateKey);
  116. var rsa = RSA.Create();
  117. var rsaParameters = new RSAParameters();
  118. using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
  119. {
  120. byte bt = 0;
  121. ushort twobytes = 0;
  122. twobytes = binr.ReadUInt16();
  123. if (twobytes == 0x8130)
  124. binr.ReadByte();
  125. else if (twobytes == 0x8230)
  126. binr.ReadInt16();
  127. else
  128. throw new Exception("Unexpected value read binr.ReadUInt16()");
  129. twobytes = binr.ReadUInt16();
  130. if (twobytes != 0x0102)
  131. throw new Exception("Unexpected version");
  132. bt = binr.ReadByte();
  133. if (bt != 0x00)
  134. throw new Exception("Unexpected value read binr.ReadByte()");
  135. rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
  136. rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
  137. rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
  138. rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
  139. rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
  140. rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
  141. rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
  142. rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
  143. }
  144. rsa.ImportParameters(rsaParameters);
  145. return rsa;
  146. }
  147. #endregion
  148. #region 使用公钥创建RSA实例
  149. public RSA CreateRsaProviderFromPublicKey(string publicKeyString)
  150. {
  151. // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
  152. byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  153. byte[] seq = new byte[15];
  154. var x509Key = Convert.FromBase64String(publicKeyString);
  155. // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
  156. using (MemoryStream mem = new MemoryStream(x509Key))
  157. {
  158. using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
  159. {
  160. byte bt = 0;
  161. ushort twobytes = 0;
  162. twobytes = binr.ReadUInt16();
  163. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  164. binr.ReadByte(); //advance 1 byte
  165. else if (twobytes == 0x8230)
  166. binr.ReadInt16(); //advance 2 bytes
  167. else
  168. return null;
  169. seq = binr.ReadBytes(15); //read the Sequence OID
  170. if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
  171. return null;
  172. twobytes = binr.ReadUInt16();
  173. if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
  174. binr.ReadByte(); //advance 1 byte
  175. else if (twobytes == 0x8203)
  176. binr.ReadInt16(); //advance 2 bytes
  177. else
  178. return null;
  179. bt = binr.ReadByte();
  180. if (bt != 0x00) //expect null byte next
  181. return null;
  182. twobytes = binr.ReadUInt16();
  183. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  184. binr.ReadByte(); //advance 1 byte
  185. else if (twobytes == 0x8230)
  186. binr.ReadInt16(); //advance 2 bytes
  187. else
  188. return null;
  189. twobytes = binr.ReadUInt16();
  190. byte lowbyte = 0x00;
  191. byte highbyte = 0x00;
  192. if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
  193. lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
  194. else if (twobytes == 0x8202)
  195. {
  196. highbyte = binr.ReadByte(); //advance 2 bytes
  197. lowbyte = binr.ReadByte();
  198. }
  199. else
  200. return null;
  201. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
  202. int modsize = BitConverter.ToInt32(modint, 0);
  203. int firstbyte = binr.PeekChar();
  204. if (firstbyte == 0x00)
  205. { //if first byte (highest order) of modulus is zero, don't include it
  206. binr.ReadByte(); //skip this null byte
  207. modsize -= 1; //reduce modulus buffer size by 1
  208. }
  209. byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
  210. if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
  211. return null;
  212. int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
  213. byte[] exponent = binr.ReadBytes(expbytes);
  214. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  215. var rsa = RSA.Create();
  216. RSAParameters rsaKeyInfo = new RSAParameters
  217. {
  218. Modulus = modulus,
  219. Exponent = exponent
  220. };
  221. rsa.ImportParameters(rsaKeyInfo);
  222. return rsa;
  223. }
  224. }
  225. }
  226. #endregion
  227. #region 导入密钥算法
  228. private int GetIntegerSize(BinaryReader binr)
  229. {
  230. byte bt = 0;
  231. int count = 0;
  232. bt = binr.ReadByte();
  233. if (bt != 0x02)
  234. return 0;
  235. bt = binr.ReadByte();
  236. if (bt == 0x81)
  237. count = binr.ReadByte();
  238. else
  239. if (bt == 0x82)
  240. {
  241. var highbyte = binr.ReadByte();
  242. var lowbyte = binr.ReadByte();
  243. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  244. count = BitConverter.ToInt32(modint, 0);
  245. }
  246. else
  247. {
  248. count = bt;
  249. }
  250. while (binr.ReadByte() == 0x00)
  251. {
  252. count -= 1;
  253. }
  254. binr.BaseStream.Seek(-1, SeekOrigin.Current);
  255. return count;
  256. }
  257. private bool CompareBytearrays(byte[] a, byte[] b)
  258. {
  259. if (a.Length != b.Length)
  260. return false;
  261. int i = 0;
  262. foreach (byte c in a)
  263. {
  264. if (c != b[i])
  265. return false;
  266. i++;
  267. }
  268. return true;
  269. }
  270. #endregion
  271. }
  272. /// <summary>
  273. /// RSA算法类型
  274. /// </summary>
  275. public enum RSAType
  276. {
  277. /// <summary>
  278. /// SHA1
  279. /// </summary>
  280. RSA = 0,
  281. /// <summary>
  282. /// RSA2 密钥长度至少为2048
  283. /// SHA256
  284. /// </summary>
  285. RSA2
  286. }
  287. }