RSAHelper.cs 11 KB

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