RSAHelper.cs 9.8 KB

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