RSAHelper.cs 10 KB

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