C#实现RSA加密与解密、签名与认证

一、RSA简介

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。
RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。
RSA的缺点主要有:
A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。

B)分组长度太大,为保证安全性,n 至少也要 600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,SET(Secure Electronic Transaction)协议中要求CA采用2048bits长的密钥,其他实体使用1024比特的密钥。

C)RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。

这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, 
AdiShamir 和Leonard Adleman。早在1973年,英国国家通信总局的数学家Clifford Cocks就发现了类似的算法。但是他的发现被列为绝密,直到1998年才公诸于世。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
其中,n是两个大质数p、q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度。
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n及e1),(n及e2)就是密钥对。
RSA加解密的算法完全相同,设A为明文,B为密文,则:A=B^e1 mod n;B=A^e2 mod n;
e1和e2可以互换使用,即:

A=B^e2 mod n;B=A^e1 mod n;

C#实现RSA加密与解密、签名与认证

二、MD5加密介绍

参考:http://blog.csdn.net/wonsoft/article/details/5913572
MD5的全称是message-digest algorithm 5(信息-摘要算法,在90年代初由mit laboratory for computer science和rsa data security inc的ronald l. rivest开发出来, 经md2、md3和md4发展而来。
MD5具有很好的安全性(因为它具有不可逆的特征,加过密的密文经过解密后和加密前的东东相同的可能性极小)

  1. public string GetStrMd5(string ConvertString)
  2. {
  3. string strBodyBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(ConvertString));
  4. string t2=System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strBodyBase64, "MD5").ToUpper();
  5. return t2;
  6. }

三、C#对PKCS#8编码的RSA私钥进行签名

 对MD5加密后的长度为32的密文进行PKCS8的RSA签名的方法:
  1. /// <summary>
  2. /// 对MD5加密后的长度为32的密文进行签名
  3. /// </summary>
  4. /// <param name="strPrivateKey">私钥</param>
  5. /// <param name="strContent">MD5加密后的密文</param>
  6. /// <returns></returns>
  7. public string SignatureFormatter(string strPrivateKey, string strContent)
  8. {
  9. byte[] btContent = Encoding.UTF8.GetBytes(strContent);
  10. byte[] hv = MD5.Create().ComputeHash(btContent);
  11. RSACryptoServiceProvider rsp = new RSACryptoServiceProvider();
  12. rsp.FromXmlString(strPrivateKey);
  13. RSAPKCS1SignatureFormatter rf = new RSAPKCS1SignatureFormatter(rsp);
  14. rf.SetHashAlgorithm("MD5");
  15. byte[] signature = rf.CreateSignature(hv);
  16. return Convert.ToBase64String(signature);
  17. }

四、C#实现RSA加密与解密、签名与认证常用方法

1.RSA加密解密:
 (1)获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥 (2)加密 (3)解密
2.RSA签名和验证
 (1)获取密钥,这里是产生密钥,实际应用中可以从各种存储介质上读取密钥 (2)获取待签名的Hash码 (3)获取签名的字符串 (4)验证
3.公钥与私钥的理解:
 (1)私钥用来进行解密和签名,是给自己用的。
 (2)公钥由本人公开,用于加密和验证签名,是给别人用的。
    (3)当该用户发送文件时,用私钥签名,别人用他给的公钥验证签名,可以保证该信息是由他发送的。当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他接收到。

  1. using System.Security.Cryptography;
  2. class RSACryption
  3. {
  4. #region RSA 加密解密
  5. #region RSA 的密钥产生
  6. /// <summary>
  7. /// RSA产生密钥
  8. /// </summary>
  9. /// <param name="xmlKeys">私钥</param>
  10. /// <param name="xmlPublicKey">公钥</param>
  11. public void RSAKey(out string xmlKeys, out string xmlPublicKey)
  12. {
  13. try
  14. {
  15. System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  16. xmlKeys = rsa.ToXmlString(true);
  17. xmlPublicKey = rsa.ToXmlString(false);
  18. }
  19. catch (Exception ex)
  20. {
  21. throw ex;
  22. }
  23. }
  24. #endregion
  25. #region RSA加密函数
  26. //##############################################################################
  27. //RSA 方式加密
  28. //KEY必须是XML的形式,返回的是字符串
  29. //该加密方式有长度限制的!
  30. //##############################################################################
  31. /// <summary>
  32. /// RSA的加密函数
  33. /// </summary>
  34. /// <param name="xmlPublicKey">公钥</param>
  35. /// <param name="encryptString">待加密的字符串</param>
  36. /// <returns></returns>
  37. public string RSAEncrypt(string xmlPublicKey, string encryptString)
  38. {
  39. try
  40. {
  41. byte[] PlainTextBArray;
  42. byte[] CypherTextBArray;
  43. string Result;
  44. System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  45. rsa.FromXmlString(xmlPublicKey);
  46. PlainTextBArray = (new UnicodeEncoding()).GetBytes(encryptString);
  47. CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
  48. Result = Convert.ToBase64String(CypherTextBArray);
  49. return Result;
  50. }
  51. catch (Exception ex)
  52. {
  53. throw ex;
  54. }
  55. }
  56. /// <summary>
  57. /// RSA的加密函数
  58. /// </summary>
  59. /// <param name="xmlPublicKey">公钥</param>
  60. /// <param name="EncryptString">待加密的字节数组</param>
  61. /// <returns></returns>
  62. public string RSAEncrypt(string xmlPublicKey, byte[] EncryptString)
  63. {
  64. try
  65. {
  66. byte[] CypherTextBArray;
  67. string Result;
  68. System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  69. rsa.FromXmlString(xmlPublicKey);
  70. CypherTextBArray = rsa.Encrypt(EncryptString, false);
  71. Result = Convert.ToBase64String(CypherTextBArray);
  72. return Result;
  73. }
  74. catch (Exception ex)
  75. {
  76. throw ex;
  77. }
  78. }
  79. #endregion
  80. #region RSA的解密函数
  81. /// <summary>
  82. /// RSA的解密函数
  83. /// </summary>
  84. /// <param name="xmlPrivateKey">私钥</param>
  85. /// <param name="decryptString">待解密的字符串</param>
  86. /// <returns></returns>
  87. public string RSADecrypt(string xmlPrivateKey, string decryptString)
  88. {
  89. try
  90. {
  91. byte[] PlainTextBArray;
  92. byte[] DypherTextBArray;
  93. string Result;
  94. System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  95. rsa.FromXmlString(xmlPrivateKey);
  96. PlainTextBArray = Convert.FromBase64String(decryptString);
  97. DypherTextBArray = rsa.Decrypt(PlainTextBArray, false);
  98. Result = (new UnicodeEncoding()).GetString(DypherTextBArray);
  99. return Result;
  100. }
  101. catch (Exception ex)
  102. {
  103. throw ex;
  104. }
  105. }
  106. /// <summary>
  107. /// RSA的解密函数
  108. /// </summary>
  109. /// <param name="xmlPrivateKey">私钥</param>
  110. /// <param name="DecryptString">待解密的字节数组</param>
  111. /// <returns></returns>
  112. public string RSADecrypt(string xmlPrivateKey, byte[] DecryptString)
  113. {
  114. try
  115. {
  116. byte[] DypherTextBArray;
  117. string Result;
  118. System.Security.Cryptography.RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  119. rsa.FromXmlString(xmlPrivateKey);
  120. DypherTextBArray = rsa.Decrypt(DecryptString, false);
  121. Result = (new UnicodeEncoding()).GetString(DypherTextBArray);
  122. return Result;
  123. }
  124. catch (Exception ex)
  125. {
  126. throw ex;
  127. }
  128. }
  129. #endregion
  130. #endregion
  131. #region RSA数字签名
  132. #region 获取Hash描述表
  133. /// <summary>
  134. /// 获取Hash描述表
  135. /// </summary>
  136. /// <param name="strSource">待签名的字符串</param>
  137. /// <param name="HashData">Hash描述</param>
  138. /// <returns></returns>
  139. public bool GetHash(string strSource, ref byte[] HashData)
  140. {
  141. try
  142. {
  143. byte[] Buffer;
  144. System.Security.Cryptography.HashAlgorithm MD5 = System.Security.Cryptography.HashAlgorithm.Create("MD5");
  145. Buffer = System.Text.Encoding.GetEncoding("GB2312").GetBytes(strSource);
  146. HashData = MD5.ComputeHash(Buffer);
  147. return true;
  148. }
  149. catch (Exception ex)
  150. {
  151. throw ex;
  152. }
  153. }
  154. /// <summary>
  155. /// 获取Hash描述表
  156. /// </summary>
  157. /// <param name="strSource">待签名的字符串</param>
  158. /// <param name="strHashData">Hash描述</param>
  159. /// <returns></returns>
  160. public bool GetHash(string strSource, ref string strHashData)
  161. {
  162. try
  163. {
  164. //从字符串中取得Hash描述
  165. byte[] Buffer;
  166. byte[] HashData;
  167. System.Security.Cryptography.HashAlgorithm MD5 = System.Security.Cryptography.HashAlgorithm.Create("MD5");
  168. Buffer = System.Text.Encoding.GetEncoding("GB2312").GetBytes(strSource);
  169. HashData = MD5.ComputeHash(Buffer);
  170. strHashData = Convert.ToBase64String(HashData);
  171. return true;
  172. }
  173. catch (Exception ex)
  174. {
  175. throw ex;
  176. }
  177. }
  178. /// <summary>
  179. /// 获取Hash描述表
  180. /// </summary>
  181. /// <param name="objFile">待签名的文件</param>
  182. /// <param name="HashData">Hash描述</param>
  183. /// <returns></returns>
  184. public bool GetHash(System.IO.FileStream objFile, ref byte[] HashData)
  185. {
  186. try
  187. {
  188. //从文件中取得Hash描述
  189. System.Security.Cryptography.HashAlgorithm MD5 = System.Security.Cryptography.HashAlgorithm.Create("MD5");
  190. HashData = MD5.ComputeHash(objFile);
  191. objFile.Close();
  192. return true;
  193. }
  194. catch (Exception ex)
  195. {
  196. throw ex;
  197. }
  198. }
  199. /// <summary>
  200. /// 获取Hash描述表
  201. /// </summary>
  202. /// <param name="objFile">待签名的文件</param>
  203. /// <param name="strHashData">Hash描述</param>
  204. /// <returns></returns>
  205. public bool GetHash(System.IO.FileStream objFile, ref string strHashData)
  206. {
  207. try
  208. {
  209. //从文件中取得Hash描述
  210. byte[] HashData;
  211. System.Security.Cryptography.HashAlgorithm MD5 = System.Security.Cryptography.HashAlgorithm.Create("MD5");
  212. HashData = MD5.ComputeHash(objFile);
  213. objFile.Close();
  214. strHashData = Convert.ToBase64String(HashData);
  215. return true;
  216. }
  217. catch (Exception ex)
  218. {
  219. throw ex;
  220. }
  221. }
  222. #endregion
  223. #region RSA签名
  224. /// <summary>
  225. /// RSA签名
  226. /// </summary>
  227. /// <param name="strKeyPrivate">私钥</param>
  228. /// <param name="HashbyteSignature">待签名Hash描述</param>
  229. /// <param name="EncryptedSignatureData">签名后的结果</param>
  230. /// <returns></returns>
  231. public bool SignatureFormatter(string strKeyPrivate, byte[] HashbyteSignature, ref byte[] EncryptedSignatureData)
  232. {
  233. try
  234. {
  235. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  236. RSA.FromXmlString(strKeyPrivate);
  237. System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter
  238. (RSA);
  239. //设置签名的算法为MD5
  240. RSAFormatter.SetHashAlgorithm("MD5");
  241. //执行签名
  242. EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
  243. return true;
  244. }
  245. catch (Exception ex)
  246. {
  247. throw ex;
  248. }
  249. }
  250. /// <summary>
  251. /// RSA签名
  252. /// </summary>
  253. /// <param name="strKeyPrivate">私钥</param>
  254. /// <param name="HashbyteSignature">待签名Hash描述</param>
  255. /// <param name="m_strEncryptedSignatureData">签名后的结果</param>
  256. /// <returns></returns>
  257. public bool SignatureFormatter(string strKeyPrivate, byte[] HashbyteSignature, ref string strEncryptedSignatureData)
  258. {
  259. try
  260. {
  261. byte[] EncryptedSignatureData;
  262. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  263. RSA.FromXmlString(strKeyPrivate);
  264. System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter
  265. (RSA);
  266. //设置签名的算法为MD5
  267. RSAFormatter.SetHashAlgorithm("MD5");
  268. //执行签名
  269. EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
  270. strEncryptedSignatureData = Convert.ToBase64String(EncryptedSignatureData);
  271. return true;
  272. }
  273. catch (Exception ex)
  274. {
  275. throw ex;
  276. }
  277. }
  278. /// <summary>
  279. /// RSA签名
  280. /// </summary>
  281. /// <param name="strKeyPrivate">私钥</param>
  282. /// <param name="strHashbyteSignature">待签名Hash描述</param>
  283. /// <param name="EncryptedSignatureData">签名后的结果</param>
  284. /// <returns></returns>
  285. public bool SignatureFormatter(string strKeyPrivate, string strHashbyteSignature, ref byte[] EncryptedSignatureData)
  286. {
  287. try
  288. {
  289. byte[] HashbyteSignature;
  290. HashbyteSignature = Convert.FromBase64String(strHashbyteSignature);
  291. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  292. RSA.FromXmlString(strKeyPrivate);
  293. System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter
  294. (RSA);
  295. //设置签名的算法为MD5
  296. RSAFormatter.SetHashAlgorithm("MD5");
  297. //执行签名
  298. EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
  299. return true;
  300. }
  301. catch (Exception ex)
  302. {
  303. throw ex;
  304. }
  305. }
  306. /// <summary>
  307. /// RSA签名
  308. /// </summary>
  309. /// <param name="strKeyPrivate">私钥</param>
  310. /// <param name="strHashbyteSignature">待签名Hash描述</param>
  311. /// <param name="strEncryptedSignatureData">签名后的结果</param>
  312. /// <returns></returns>
  313. public bool SignatureFormatter(string strKeyPrivate, string strHashbyteSignature, ref string strEncryptedSignatureData)
  314. {
  315. try
  316. {
  317. byte[] HashbyteSignature;
  318. byte[] EncryptedSignatureData;
  319. HashbyteSignature = Convert.FromBase64String(strHashbyteSignature);
  320. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  321. RSA.FromXmlString(strKeyPrivate);
  322. System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter
  323. (RSA);
  324. //设置签名的算法为MD5
  325. RSAFormatter.SetHashAlgorithm("MD5");
  326. //执行签名
  327. EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
  328. strEncryptedSignatureData = Convert.ToBase64String(EncryptedSignatureData);
  329. return true;
  330. }
  331. catch (Exception ex)
  332. {
  333. throw ex;
  334. }
  335. }
  336. #endregion
  337. #region RSA 签名验证
  338. /// <summary>
  339. /// RSA签名验证
  340. /// </summary>
  341. /// <param name="strKeyPublic">公钥</param>
  342. /// <param name="HashbyteDeformatter">Hash描述</param>
  343. /// <param name="DeformatterData">签名后的结果</param>
  344. /// <returns></returns>
  345. public bool SignatureDeformatter(string strKeyPublic, byte[] HashbyteDeformatter, byte[] DeformatterData)
  346. {
  347. try
  348. {
  349. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  350. RSA.FromXmlString(strKeyPublic);
  351. System.Security.Cryptography.RSAPKCS1SignatureDeformatter RSADeformatter = new
  352. System.Security.Cryptography.RSAPKCS1SignatureDeformatter(RSA);
  353. //指定解密的时候HASH算法为MD5
  354. RSADeformatter.SetHashAlgorithm("MD5");
  355. if (RSADeformatter.VerifySignature(HashbyteDeformatter, DeformatterData))
  356. {
  357. return true;
  358. }
  359. else
  360. {
  361. return false;
  362. }
  363. }
  364. catch (Exception ex)
  365. {
  366. throw ex;
  367. }
  368. }
  369. /// <summary>
  370. /// RSA签名验证
  371. /// </summary>
  372. /// <param name="strKeyPublic">公钥</param>
  373. /// <param name="strHashbyteDeformatter">Hash描述</param>
  374. /// <param name="DeformatterData">签名后的结果</param>
  375. /// <returns></returns>
  376. public bool SignatureDeformatter(string strKeyPublic, string strHashbyteDeformatter, byte[] DeformatterData)
  377. {
  378. try
  379. {
  380. byte[] HashbyteDeformatter;
  381. HashbyteDeformatter = Convert.FromBase64String(strHashbyteDeformatter);
  382. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  383. RSA.FromXmlString(strKeyPublic);
  384. System.Security.Cryptography.RSAPKCS1SignatureDeformatter RSADeformatter = new
  385. System.Security.Cryptography.RSAPKCS1SignatureDeformatter(RSA);
  386. //指定解密的时候HASH算法为MD5
  387. RSADeformatter.SetHashAlgorithm("MD5");
  388. if (RSADeformatter.VerifySignature(HashbyteDeformatter, DeformatterData))
  389. {
  390. return true;
  391. }
  392. else
  393. {
  394. return false;
  395. }
  396. }
  397. catch (Exception ex)
  398. {
  399. throw ex;
  400. }
  401. }
  402. /// <summary>
  403. /// RSA签名验证
  404. /// </summary>
  405. /// <param name="strKeyPublic">公钥</param>
  406. /// <param name="HashbyteDeformatter">Hash描述</param>
  407. /// <param name="strDeformatterData">签名后的结果</param>
  408. /// <returns></returns>
  409. public bool SignatureDeformatter(string strKeyPublic, byte[] HashbyteDeformatter, string strDeformatterData)
  410. {
  411. try
  412. {
  413. byte[] DeformatterData;
  414. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  415. RSA.FromXmlString(strKeyPublic);
  416. System.Security.Cryptography.RSAPKCS1SignatureDeformatter RSADeformatter = new
  417. System.Security.Cryptography.RSAPKCS1SignatureDeformatter(RSA);
  418. //指定解密的时候HASH算法为MD5
  419. RSADeformatter.SetHashAlgorithm("MD5");
  420. DeformatterData = Convert.FromBase64String(strDeformatterData);
  421. if (RSADeformatter.VerifySignature(HashbyteDeformatter, DeformatterData))
  422. {
  423. return true;
  424. }
  425. else
  426. {
  427. return false;
  428. }
  429. }
  430. catch (Exception ex)
  431. {
  432. throw ex;
  433. }
  434. }
  435. /// <summary>
  436. /// RSA签名验证
  437. /// </summary>
  438. /// <param name="strKeyPublic">公钥</param>
  439. /// <param name="strHashbyteDeformatter">Hash描述</param>
  440. /// <param name="strDeformatterData">签名后的结果</param>
  441. /// <returns></returns>
  442. public bool SignatureDeformatter(string strKeyPublic, string strHashbyteDeformatter, string strDeformatterData)
  443. {
  444. try
  445. {
  446. byte[] DeformatterData;
  447. byte[] HashbyteDeformatter;
  448. HashbyteDeformatter = Convert.FromBase64String(strHashbyteDeformatter);
  449. System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
  450. RSA.FromXmlString(strKeyPublic);
  451. System.Security.Cryptography.RSAPKCS1SignatureDeformatter RSADeformatter = new
  452. System.Security.Cryptography.RSAPKCS1SignatureDeformatter(RSA);
  453. //指定解密的时候HASH算法为MD5
  454. RSADeformatter.SetHashAlgorithm("MD5");
  455. DeformatterData = Convert.FromBase64String(strDeformatterData);
  456. if (RSADeformatter.VerifySignature(HashbyteDeformatter, DeformatterData))
  457. {
  458. return true;
  459. }
  460. else
  461. {
  462. return false;
  463. }
  464. }
  465. catch (Exception ex)
  466. {
  467. throw ex;
  468. }
  469. }
  470. #endregion
  471. #endregion
  472. }

参考网站:

http://www.cnblogs.com/linzheng/archive/2011/02/20/1959123.html
http://www.cnblogs.com/sydeveloper/archive/2012/08/11/2633624.html
http://codego.net/126956/

上一篇:IOS, Android, Java Web Rest : RSA 加密和解密问题


下一篇:RSA加密和解密工具类