RSAHelper.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. #endregion
  77. #region 加密
  78. // public string Encrypt(string text)
  79. // {
  80. // if (_publicKeyRsaProvider == null)
  81. // {
  82. // throw new Exception("_publicKeyRsaProvider is null");
  83. // }
  84. // return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.Pkcs1));
  85. // }
  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. #endregion
  118. #region 使用私钥创建RSA实例
  119. public RSA CreateRsaProviderFromPrivateKey(string privateKey)
  120. {
  121. var privateKeyBits = Convert.FromBase64String(privateKey);
  122. var rsa = RSA.Create();
  123. var rsaParameters = new RSAParameters();
  124. using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
  125. {
  126. byte bt = 0;
  127. ushort twobytes = 0;
  128. twobytes = binr.ReadUInt16();
  129. if (twobytes == 0x8130)
  130. binr.ReadByte();
  131. else if (twobytes == 0x8230)
  132. binr.ReadInt16();
  133. else
  134. throw new Exception("Unexpected value read binr.ReadUInt16()");
  135. twobytes = binr.ReadUInt16();
  136. if (twobytes != 0x0102)
  137. throw new Exception("Unexpected version");
  138. bt = binr.ReadByte();
  139. if (bt != 0x00)
  140. throw new Exception("Unexpected value read binr.ReadByte()");
  141. rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
  142. rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
  143. rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
  144. rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
  145. rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
  146. rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
  147. rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
  148. rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
  149. }
  150. rsa.ImportParameters(rsaParameters);
  151. return rsa;
  152. }
  153. #endregion
  154. #region 使用公钥创建RSA实例
  155. public RSA CreateRsaProviderFromPublicKey(string publicKeyString)
  156. {
  157. // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
  158. byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  159. byte[] seq = new byte[15];
  160. var x509Key = Convert.FromBase64String(publicKeyString);
  161. // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
  162. using (MemoryStream mem = new MemoryStream(x509Key))
  163. {
  164. using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
  165. {
  166. byte bt = 0;
  167. ushort twobytes = 0;
  168. twobytes = binr.ReadUInt16();
  169. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  170. binr.ReadByte(); //advance 1 byte
  171. else if (twobytes == 0x8230)
  172. binr.ReadInt16(); //advance 2 bytes
  173. else
  174. return null;
  175. seq = binr.ReadBytes(15); //read the Sequence OID
  176. if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
  177. return null;
  178. twobytes = binr.ReadUInt16();
  179. if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
  180. binr.ReadByte(); //advance 1 byte
  181. else if (twobytes == 0x8203)
  182. binr.ReadInt16(); //advance 2 bytes
  183. else
  184. return null;
  185. bt = binr.ReadByte();
  186. if (bt != 0x00) //expect null byte next
  187. return null;
  188. twobytes = binr.ReadUInt16();
  189. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  190. binr.ReadByte(); //advance 1 byte
  191. else if (twobytes == 0x8230)
  192. binr.ReadInt16(); //advance 2 bytes
  193. else
  194. return null;
  195. twobytes = binr.ReadUInt16();
  196. byte lowbyte = 0x00;
  197. byte highbyte = 0x00;
  198. if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
  199. lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
  200. else if (twobytes == 0x8202)
  201. {
  202. highbyte = binr.ReadByte(); //advance 2 bytes
  203. lowbyte = binr.ReadByte();
  204. }
  205. else
  206. return null;
  207. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
  208. int modsize = BitConverter.ToInt32(modint, 0);
  209. int firstbyte = binr.PeekChar();
  210. if (firstbyte == 0x00)
  211. { //if first byte (highest order) of modulus is zero, don't include it
  212. binr.ReadByte(); //skip this null byte
  213. modsize -= 1; //reduce modulus buffer size by 1
  214. }
  215. byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
  216. if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
  217. return null;
  218. int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
  219. byte[] exponent = binr.ReadBytes(expbytes);
  220. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  221. var rsa = RSA.Create();
  222. RSAParameters rsaKeyInfo = new RSAParameters
  223. {
  224. Modulus = modulus,
  225. Exponent = exponent
  226. };
  227. rsa.ImportParameters(rsaKeyInfo);
  228. return rsa;
  229. }
  230. }
  231. }
  232. #endregion
  233. #region 导入密钥算法
  234. private int GetIntegerSize(BinaryReader binr)
  235. {
  236. byte bt = 0;
  237. int count = 0;
  238. bt = binr.ReadByte();
  239. if (bt != 0x02)
  240. return 0;
  241. bt = binr.ReadByte();
  242. if (bt == 0x81)
  243. count = binr.ReadByte();
  244. else
  245. if (bt == 0x82)
  246. {
  247. var highbyte = binr.ReadByte();
  248. var lowbyte = binr.ReadByte();
  249. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  250. count = BitConverter.ToInt32(modint, 0);
  251. }
  252. else
  253. {
  254. count = bt;
  255. }
  256. while (binr.ReadByte() == 0x00)
  257. {
  258. count -= 1;
  259. }
  260. binr.BaseStream.Seek(-1, SeekOrigin.Current);
  261. return count;
  262. }
  263. private bool CompareBytearrays(byte[] a, byte[] b)
  264. {
  265. if (a.Length != b.Length)
  266. return false;
  267. int i = 0;
  268. foreach (byte c in a)
  269. {
  270. if (c != b[i])
  271. return false;
  272. i++;
  273. }
  274. return true;
  275. }
  276. #endregion
  277. }
  278. /// <summary>
  279. /// RSA算法类型
  280. /// </summary>
  281. public enum RSAType
  282. {
  283. /// <summary>
  284. /// SHA1
  285. /// </summary>
  286. RSA = 0,
  287. /// <summary>
  288. /// RSA2 密钥长度至少为2048
  289. /// SHA256
  290. /// </summary>
  291. RSA2
  292. }
  293. }