平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

400 lines
11 KiB

  1. //
  2. namespace SafeCampus.Core.Utils;
  3. /// <summary>
  4. /// SM2工具类
  5. /// </summary>
  6. public class SM2CryptoUtil
  7. {
  8. #region 获取公钥私钥
  9. /// <summary>
  10. /// 获取公钥私钥
  11. /// </summary>
  12. /// <returns></returns>
  13. public static SM2Model GetKey()
  14. {
  15. var sm2 = SM2.Instance;
  16. var key = sm2.ecc_key_pair_generator.GenerateKeyPair();
  17. var ecpriv = (ECPrivateKeyParameters)key.Private;
  18. var ecpub = (ECPublicKeyParameters)key.Public;
  19. var privateKey = ecpriv.D;
  20. var publicKey = ecpub.Q;
  21. var sM2Model = new SM2Model();
  22. sM2Model.PrivateKey = Encoding.UTF8.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper();
  23. sM2Model.PublicKey = Encoding.UTF8.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper();
  24. return sM2Model;
  25. }
  26. #endregion 获取公钥私钥
  27. #region 加密
  28. /// <summary>
  29. /// 加密
  30. /// </summary>
  31. /// <param name="publickey">公钥</param>
  32. /// <param name="sourceData">需要加密的值</param>
  33. /// <returns>加密结果</returns>
  34. public static string Encrypt(string publickey, string sourceData)
  35. {
  36. var data = Encrypt(Hex.Decode(publickey), Encoding.UTF8.GetBytes(sourceData));
  37. return data;
  38. }
  39. /// <summary>
  40. /// 加密
  41. /// </summary>
  42. /// <param name="publicKey">公钥</param>
  43. /// <param name="data">需要加密的值</param>
  44. /// <returns></returns>
  45. public static string Encrypt(byte[] publicKey, byte[] data)
  46. {
  47. if (null == publicKey || publicKey.Length == 0)
  48. {
  49. return null;
  50. }
  51. if (data == null || data.Length == 0)
  52. {
  53. return null;
  54. }
  55. var source = new byte[data.Length];
  56. Array.Copy(data, 0, source, 0,
  57. data.Length);
  58. var cipher = new Cipher();
  59. var sm2 = SM2.Instance;
  60. var userKey = sm2.ecc_curve.DecodePoint(publicKey);
  61. var c1 = cipher.Init_enc(sm2, userKey);
  62. cipher.Encrypt(source);
  63. var c3 = new byte[32];
  64. cipher.Dofinal(c3);
  65. var sc1 = Encoding.UTF8.GetString(Hex.Encode(c1.GetEncoded()));
  66. var sc2 = Encoding.UTF8.GetString(Hex.Encode(source));
  67. var sc3 = Encoding.UTF8.GetString(Hex.Encode(c3));
  68. return (sc1 + sc2 + sc3).ToUpper();
  69. }
  70. #endregion 加密
  71. #region 解密
  72. /// <summary>
  73. ///
  74. /// </summary>
  75. /// <param name="privateKey"></param>
  76. /// <param name="encryptedData"></param>
  77. /// <returns></returns>
  78. public static string Decrypt(string privateKey, string encryptedData)
  79. {
  80. var data = Encoding.UTF8.GetString(Decrypt(Hex.Decode(privateKey), Hex.Decode(encryptedData)));
  81. return data;
  82. }
  83. /// <summary>
  84. /// 解密
  85. /// </summary>
  86. /// <param name="privateKey"></param>
  87. /// <param name="encryptedData"></param>
  88. /// <returns></returns>
  89. public static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)
  90. {
  91. if (null == privateKey || privateKey.Length == 0)
  92. {
  93. return null;
  94. }
  95. if (encryptedData == null || encryptedData.Length == 0)
  96. {
  97. return null;
  98. }
  99. var data = Encoding.UTF8.GetString(Hex.Encode(encryptedData));
  100. var c1Bytes = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(0, 130)));
  101. var c2Len = encryptedData.Length - 97;
  102. var c2 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130, 2 * c2Len)));
  103. var c3 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130 + 2 * c2Len, 64)));
  104. var sm2 = SM2.Instance;
  105. var userD = new BigInteger(1, privateKey);
  106. //ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);
  107. var c1 = sm2.ecc_curve.DecodePoint(c1Bytes);
  108. var cipher = new Cipher();
  109. cipher.Init_dec(userD, c1);
  110. cipher.Decrypt(c2);
  111. cipher.Dofinal(c3);
  112. return c2;
  113. }
  114. #endregion 解密
  115. private class Cipher
  116. {
  117. private int ct;
  118. private ECPoint p2;
  119. private SM3Digest sm3keybase;
  120. private SM3Digest sm3c3;
  121. private byte[] key;
  122. private byte keyOff;
  123. public Cipher()
  124. {
  125. ct = 1;
  126. key = new byte[32];
  127. keyOff = 0;
  128. }
  129. public static byte[] byteConvert32Bytes(BigInteger n)
  130. {
  131. byte[] tmpd;
  132. if (n == null)
  133. {
  134. return null;
  135. }
  136. if (n.ToByteArray().Length == 33)
  137. {
  138. tmpd = new byte[32];
  139. Array.Copy(n.ToByteArray(), 1, tmpd, 0,
  140. 32);
  141. }
  142. else if (n.ToByteArray().Length == 32)
  143. {
  144. tmpd = n.ToByteArray();
  145. }
  146. else
  147. {
  148. tmpd = new byte[32];
  149. for (var i = 0; i < 32 - n.ToByteArray().Length; i++)
  150. {
  151. tmpd[i] = 0;
  152. }
  153. Array.Copy(n.ToByteArray(), 0, tmpd, 32 - n.ToByteArray().Length,
  154. n.ToByteArray().Length);
  155. }
  156. return tmpd;
  157. }
  158. private void Reset()
  159. {
  160. sm3keybase = new SM3Digest();
  161. sm3c3 = new SM3Digest();
  162. var p = byteConvert32Bytes(p2.Normalize().XCoord.ToBigInteger());
  163. sm3keybase.BlockUpdate(p, 0, p.Length);
  164. sm3c3.BlockUpdate(p, 0, p.Length);
  165. p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
  166. sm3keybase.BlockUpdate(p, 0, p.Length);
  167. ct = 1;
  168. NextKey();
  169. }
  170. private void NextKey()
  171. {
  172. var sm3keycur = new SM3Digest(sm3keybase);
  173. sm3keycur.Update((byte)(ct >> 24 & 0xff));
  174. sm3keycur.Update((byte)(ct >> 16 & 0xff));
  175. sm3keycur.Update((byte)(ct >> 8 & 0xff));
  176. sm3keycur.Update((byte)(ct & 0xff));
  177. sm3keycur.DoFinal(key, 0);
  178. keyOff = 0;
  179. ct++;
  180. }
  181. public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
  182. {
  183. var key = sm2.ecc_key_pair_generator.GenerateKeyPair();
  184. var ecpriv = (ECPrivateKeyParameters)key.Private;
  185. var ecpub = (ECPublicKeyParameters)key.Public;
  186. var k = ecpriv.D;
  187. var c1 = ecpub.Q;
  188. p2 = userKey.Multiply(k);
  189. Reset();
  190. return c1;
  191. }
  192. public void Encrypt(byte[] data)
  193. {
  194. sm3c3.BlockUpdate(data, 0, data.Length);
  195. for (var i = 0; i < data.Length; i++)
  196. {
  197. if (keyOff == key.Length)
  198. {
  199. NextKey();
  200. }
  201. data[i] ^= key[keyOff++];
  202. }
  203. }
  204. public void Init_dec(BigInteger userD, ECPoint c1)
  205. {
  206. p2 = c1.Multiply(userD);
  207. Reset();
  208. }
  209. public void Decrypt(byte[] data)
  210. {
  211. for (var i = 0; i < data.Length; i++)
  212. {
  213. if (keyOff == key.Length)
  214. {
  215. NextKey();
  216. }
  217. data[i] ^= key[keyOff++];
  218. }
  219. sm3c3.BlockUpdate(data, 0, data.Length);
  220. }
  221. public void Dofinal(byte[] c3)
  222. {
  223. var p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
  224. sm3c3.BlockUpdate(p, 0, p.Length);
  225. sm3c3.DoFinal(c3, 0);
  226. Reset();
  227. }
  228. }
  229. private class SM2
  230. {
  231. public static SM2 Instance
  232. {
  233. get
  234. {
  235. return new SM2();
  236. }
  237. }
  238. public static SM2 InstanceTest
  239. {
  240. get
  241. {
  242. return new SM2();
  243. }
  244. }
  245. public static readonly string[] sm2_param =
  246. {
  247. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0
  248. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1
  249. "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2
  250. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3
  251. "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4
  252. "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"// gy,5
  253. };
  254. public string[] ecc_param = sm2_param;
  255. public readonly BigInteger ecc_p;
  256. public readonly BigInteger ecc_a;
  257. public readonly BigInteger ecc_b;
  258. public readonly BigInteger ecc_n;
  259. public readonly BigInteger ecc_gx;
  260. public readonly BigInteger ecc_gy;
  261. public readonly ECCurve ecc_curve;
  262. public readonly ECPoint ecc_point_g;
  263. public readonly ECDomainParameters ecc_bc_spec;
  264. public readonly ECKeyPairGenerator ecc_key_pair_generator;
  265. private SM2()
  266. {
  267. ecc_param = sm2_param;
  268. ECFieldElement ecc_gx_fieldelement;
  269. ECFieldElement ecc_gy_fieldelement;
  270. ecc_p = new BigInteger(ecc_param[0], 16);
  271. ecc_a = new BigInteger(ecc_param[1], 16);
  272. ecc_b = new BigInteger(ecc_param[2], 16);
  273. ecc_n = new BigInteger(ecc_param[3], 16);
  274. ecc_gx = new BigInteger(ecc_param[4], 16);
  275. ecc_gy = new BigInteger(ecc_param[5], 16);
  276. ecc_gx_fieldelement = new FpFieldElement(ecc_p, ecc_gx);
  277. ecc_gy_fieldelement = new FpFieldElement(ecc_p, ecc_gy);
  278. ecc_curve = new FpCurve(ecc_p, ecc_a, ecc_b);
  279. ecc_point_g = new FpPoint(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);
  280. ecc_bc_spec = new ECDomainParameters(ecc_curve, ecc_point_g, ecc_n);
  281. ECKeyGenerationParameters ecc_ecgenparam;
  282. ecc_ecgenparam = new ECKeyGenerationParameters(ecc_bc_spec, new SecureRandom());
  283. ecc_key_pair_generator = new ECKeyPairGenerator();
  284. ecc_key_pair_generator.Init(ecc_ecgenparam);
  285. }
  286. public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)
  287. {
  288. var sm3 = new SM3Digest();
  289. byte[] p;
  290. // userId length
  291. var len = userId.Length * 8;
  292. sm3.Update((byte)(len >> 8 & 0x00ff));
  293. sm3.Update((byte)(len & 0x00ff));
  294. // userId
  295. sm3.BlockUpdate(userId, 0, userId.Length);
  296. // a,b
  297. p = ecc_a.ToByteArray();
  298. sm3.BlockUpdate(p, 0, p.Length);
  299. p = ecc_b.ToByteArray();
  300. sm3.BlockUpdate(p, 0, p.Length);
  301. // gx,gy
  302. p = ecc_gx.ToByteArray();
  303. sm3.BlockUpdate(p, 0, p.Length);
  304. p = ecc_gy.ToByteArray();
  305. sm3.BlockUpdate(p, 0, p.Length);
  306. // x,y
  307. p = userKey.AffineXCoord.ToBigInteger().ToByteArray();
  308. sm3.BlockUpdate(p, 0, p.Length);
  309. p = userKey.AffineYCoord.ToBigInteger().ToByteArray();
  310. sm3.BlockUpdate(p, 0, p.Length);
  311. // Z
  312. var md = new byte[sm3.GetDigestSize()];
  313. sm3.DoFinal(md, 0);
  314. return md;
  315. }
  316. }
  317. public class SM2Model
  318. {
  319. /// <summary>
  320. /// 公钥
  321. /// </summary>
  322. public string PublicKey { get; set; }
  323. /// <summary>
  324. /// 私钥
  325. /// </summary>
  326. public string PrivateKey { get; set; }
  327. }
  328. }