RSAHelper.cs 8.9 KB

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