经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
C#.NET 国密SM3 HASH 哈希 与JAVA互通 ver:20230803
来源:cnblogs  作者:runliuv  时间:2023/8/7 9:14:30  对本文有异议

C#.NET 国密SM3 HASH 哈希 与JAVA互通 ver:20230803

 

.NET 环境:.NET6 控制台程序(.net core)。

JAVA 环境:JAVA8,带maven 的JAVA控制台程序。

 

简要解析:

1:明文输入参数都需要string转 byte [] ,要约定好编码,如:UTF8。

2:输出参数:byte [] ,在传输时需要转为string,要约定好编码,如:16进制字符串。

 

.NET 代码:

GmUtil 工具类,需要nuget下载 Portable.BouncyCastle 1.9.0 版本:

 

  1. using Org.BouncyCastle.Asn1;
  2. using Org.BouncyCastle.Asn1.GM;
  3. using Org.BouncyCastle.Asn1.X9;
  4. using Org.BouncyCastle.Crypto;
  5. using Org.BouncyCastle.Crypto.Digests;
  6. using Org.BouncyCastle.Crypto.Engines;
  7. using Org.BouncyCastle.Crypto.Generators;
  8. using Org.BouncyCastle.Crypto.Parameters;
  9. using Org.BouncyCastle.Math;
  10. using Org.BouncyCastle.Security;
  11. using Org.BouncyCastle.Utilities;
  12. using Org.BouncyCastle.Utilities.Encoders;
  13. using Org.BouncyCastle.X509;
  14. using System;
  15. using System.Collections.Generic;
  16. using System.IO;
  17. namespace CommonUtils
  18. {
  19. /**
  20. * need lib:
  21. * BouncyCastle.Crypto.dll(http://www.bouncycastle.org/csharp/index.html
  22. * 用BC的注意点:
  23. * 这个版本的BC对SM3withSM2的结果为asn1格式的r和s,如果需要直接拼接的r||s需要自己转换。下面rsAsn1ToPlainByteArray、rsPlainByteArrayToAsn1就在干这事。
  24. * 这个版本的BC对SM2的结果为C1||C2||C3,据说为旧标准,新标准为C1||C3||C2,用新标准的需要自己转换。下面(被注释掉的)changeC1C2C3ToC1C3C2、changeC1C3C2ToC1C2C3就在干这事。java版的高版本有加上C1C3C2,csharp版没准以后也会加,但目前还没有,java版的目前可以初始化时“ SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);”。
  25. *
  26. * 按要求国密算法仅允许使用加密机,本demo国密算法仅供学习使用,请不要用于生产用途。
  27. */
  28. public class GmUtil
  29. {
  30. //private static readonly ILog log = LogManager.GetLogger(typeof(GmUtil));
  31.  
  32. private static X9ECParameters x9ECParameters = GMNamedCurves.GetByName("sm2p256v1");
  33. private static ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
  34. /**
  35. *
  36. * @param msg
  37. * @param userId
  38. * @param privateKey
  39. * @return r||s,直接拼接byte数组的rs
  40. */
  41. public static byte[] SignSm3WithSm2(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
  42. {
  43. return RsAsn1ToPlainByteArray(SignSm3WithSm2Asn1Rs(msg, userId, privateKey));
  44. }
  45. /**
  46. * @param msg
  47. * @param userId
  48. * @param privateKey
  49. * @return rs in <b>asn1 format</b>
  50. */
  51. public static byte[] SignSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
  52. {
  53. try
  54. {
  55. ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
  56. signer.Init(true, new ParametersWithID(privateKey, userId));
  57. signer.BlockUpdate(msg, 0, msg.Length);
  58. byte[] sig = signer.GenerateSignature();
  59. return sig;
  60. }
  61. catch (Exception e)
  62. {
  63. //log.Error("SignSm3WithSm2Asn1Rs error: " + e.Message, e);
  64. return null;
  65. }
  66. }
  67. /**
  68. *
  69. * @param msg
  70. * @param userId
  71. * @param rs r||s,直接拼接byte数组的rs
  72. * @param publicKey
  73. * @return
  74. */
  75. public static bool VerifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, AsymmetricKeyParameter publicKey)
  76. {
  77. if (rs == null || msg == null || userId == null) return false;
  78. if (rs.Length != RS_LEN * 2) return false;
  79. return VerifySm3WithSm2Asn1Rs(msg, userId, RsPlainByteArrayToAsn1(rs), publicKey);
  80. }
  81. /**
  82. *
  83. * @param msg
  84. * @param userId
  85. * @param rs in <b>asn1 format</b>
  86. * @param publicKey
  87. * @return
  88. */
  89.  
  90. public static bool VerifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] sign, AsymmetricKeyParameter publicKey)
  91. {
  92. try
  93. {
  94. ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
  95. signer.Init(false, new ParametersWithID(publicKey, userId));
  96. signer.BlockUpdate(msg, 0, msg.Length);
  97. return signer.VerifySignature(sign);
  98. }
  99. catch (Exception e)
  100. {
  101. //log.Error("VerifySm3WithSm2Asn1Rs error: " + e.Message, e);
  102. return false;
  103. }
  104. }
  105. /**
  106. * bc加解密使用旧标c1||c2||c3,此方法在加密后调用,将结果转化为c1||c3||c2
  107. * @param c1c2c3
  108. * @return
  109. */
  110. private static byte[] ChangeC1C2C3ToC1C3C2(byte[] c1c2c3)
  111. {
  112. int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
  113. const int c3Len = 32; //new SM3Digest().getDigestSize();
  114. byte[] result = new byte[c1c2c3.Length];
  115. Buffer.BlockCopy(c1c2c3, 0, result, 0, c1Len); //c1
  116. Buffer.BlockCopy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3
  117. Buffer.BlockCopy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2
  118. return result;
  119. }
  120. /**
  121. * bc加解密使用旧标c1||c3||c2,此方法在解密前调用,将密文转化为c1||c2||c3再去解密
  122. * @param c1c3c2
  123. * @return
  124. */
  125. private static byte[] ChangeC1C3C2ToC1C2C3(byte[] c1c3c2)
  126. {
  127. int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
  128. const int c3Len = 32; //new SM3Digest().GetDigestSize();
  129. byte[] result = new byte[c1c3c2.Length];
  130. Buffer.BlockCopy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65
  131. Buffer.BlockCopy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2
  132. Buffer.BlockCopy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3
  133. return result;
  134. }
  135. /**
  136. * c1||c3||c2
  137. * @param data
  138. * @param key
  139. * @return
  140. */
  141. public static byte[] Sm2Decrypt(byte[] data, AsymmetricKeyParameter key)
  142. {
  143. return Sm2DecryptOld(ChangeC1C3C2ToC1C2C3(data), key);
  144. }
  145. /**
  146. * c1||c3||c2
  147. * @param data
  148. * @param key
  149. * @return
  150. */
  151.  
  152. public static byte[] Sm2Encrypt(byte[] data, AsymmetricKeyParameter key)
  153. {
  154. return ChangeC1C2C3ToC1C3C2(Sm2EncryptOld(data, key));
  155. }
  156. /**
  157. * c1||c2||c3
  158. * @param data
  159. * @param key
  160. * @return
  161. */
  162. public static byte[] Sm2EncryptOld(byte[] data, AsymmetricKeyParameter pubkey)
  163. {
  164. try
  165. {
  166. SM2Engine sm2Engine = new SM2Engine();
  167. sm2Engine.Init(true, new ParametersWithRandom(pubkey, new SecureRandom()));
  168. return sm2Engine.ProcessBlock(data, 0, data.Length);
  169. }
  170. catch (Exception e)
  171. {
  172. //log.Error("Sm2EncryptOld error: " + e.Message, e);
  173. return null;
  174. }
  175. }
  176. /**
  177. * c1||c2||c3
  178. * @param data
  179. * @param key
  180. * @return
  181. */
  182. public static byte[] Sm2DecryptOld(byte[] data, AsymmetricKeyParameter key)
  183. {
  184. try
  185. {
  186. SM2Engine sm2Engine = new SM2Engine();
  187. sm2Engine.Init(false, key);
  188. return sm2Engine.ProcessBlock(data, 0, data.Length);
  189. }
  190. catch (Exception e)
  191. {
  192. //log.Error("Sm2DecryptOld error: " + e.Message, e);
  193. return null;
  194. }
  195. }
  196. /**
  197. * @param bytes
  198. * @return
  199. */
  200. public static byte[] Sm3(byte[] bytes)
  201. {
  202. try
  203. {
  204. SM3Digest digest = new SM3Digest();
  205. digest.BlockUpdate(bytes, 0, bytes.Length);
  206. byte[] result = DigestUtilities.DoFinal(digest);
  207. return result;
  208. }
  209. catch (Exception e)
  210. {
  211. //log.Error("Sm3 error: " + e.Message, e);
  212. return null;
  213. }
  214. }
  215. private const int RS_LEN = 32;
  216. private static byte[] BigIntToFixexLengthBytes(BigInteger rOrS)
  217. {
  218. // for sm2p256v1, n is 00fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123,
  219. // r and s are the result of mod n, so they should be less than n and have length<=32
  220. byte[] rs = rOrS.ToByteArray();
  221. if (rs.Length == RS_LEN) return rs;
  222. else if (rs.Length == RS_LEN + 1 && rs[0] == 0) return Arrays.CopyOfRange(rs, 1, RS_LEN + 1);
  223. else if (rs.Length < RS_LEN)
  224. {
  225. byte[] result = new byte[RS_LEN];
  226. Arrays.Fill(result, (byte)0);
  227. Buffer.BlockCopy(rs, 0, result, RS_LEN - rs.Length, rs.Length);
  228. return result;
  229. }
  230. else
  231. {
  232. throw new ArgumentException("err rs: " + Hex.ToHexString(rs));
  233. }
  234. }
  235. /**
  236. * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s
  237. * @param rsDer rs in asn1 format
  238. * @return sign result in plain byte array
  239. */
  240. private static byte[] RsAsn1ToPlainByteArray(byte[] rsDer)
  241. {
  242. Asn1Sequence seq = Asn1Sequence.GetInstance(rsDer);
  243. byte[] r = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[0]).Value);
  244. byte[] s = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[1]).Value);
  245. byte[] result = new byte[RS_LEN * 2];
  246. Buffer.BlockCopy(r, 0, result, 0, r.Length);
  247. Buffer.BlockCopy(s, 0, result, RS_LEN, s.Length);
  248. return result;
  249. }
  250. /**
  251. * BC的SM3withSM2验签需要的rs是asn1格式的,这个方法将直接拼接r||s的字节数组转化成asn1格式
  252. * @param sign in plain byte array
  253. * @return rs result in asn1 format
  254. */
  255. private static byte[] RsPlainByteArrayToAsn1(byte[] sign)
  256. {
  257. if (sign.Length != RS_LEN * 2) throw new ArgumentException("err rs. ");
  258. BigInteger r = new BigInteger(1, Arrays.CopyOfRange(sign, 0, RS_LEN));
  259. BigInteger s = new BigInteger(1, Arrays.CopyOfRange(sign, RS_LEN, RS_LEN * 2));
  260. Asn1EncodableVector v = new Asn1EncodableVector();
  261. v.Add(new DerInteger(r));
  262. v.Add(new DerInteger(s));
  263. try
  264. {
  265. return new DerSequence(v).GetEncoded("DER");
  266. }
  267. catch (IOException e)
  268. {
  269. //log.Error("RsPlainByteArrayToAsn1 error: " + e.Message, e);
  270. return null;
  271. }
  272. }
  273. public static AsymmetricCipherKeyPair GenerateKeyPair()
  274. {
  275. try
  276. {
  277. ECKeyPairGenerator kpGen = new ECKeyPairGenerator();
  278. kpGen.Init(new ECKeyGenerationParameters(ecDomainParameters, new SecureRandom()));
  279. return kpGen.GenerateKeyPair();
  280. }
  281. catch (Exception e)
  282. {
  283. //log.Error("generateKeyPair error: " + e.Message, e);
  284. return null;
  285. }
  286. }
  287. public static ECPrivateKeyParameters GetPrivatekeyFromD(BigInteger d)
  288. {
  289. return new ECPrivateKeyParameters(d, ecDomainParameters);
  290. }
  291. public static ECPublicKeyParameters GetPublickeyFromXY(BigInteger x, BigInteger y)
  292. {
  293. return new ECPublicKeyParameters(x9ECParameters.Curve.CreatePoint(x, y), ecDomainParameters);
  294. }
  295. public static AsymmetricKeyParameter GetPublickeyFromX509File(FileInfo file)
  296. {
  297. FileStream fileStream = null;
  298. try
  299. {
  300. //file.DirectoryName + "\\" + file.Name
  301. fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
  302. X509Certificate certificate = new X509CertificateParser().ReadCertificate(fileStream);
  303. return certificate.GetPublicKey();
  304. }
  305. catch (Exception e)
  306. {
  307. //log.Error(file.Name + "读取失败,异常:" + e);
  308. }
  309. finally
  310. {
  311. if (fileStream != null)
  312. fileStream.Close();
  313. }
  314. return null;
  315. }
  316. public class Sm2Cert
  317. {
  318. public AsymmetricKeyParameter privateKey;
  319. public AsymmetricKeyParameter publicKey;
  320. public String certId;
  321. }
  322. private static byte[] ToByteArray(int i)
  323. {
  324. byte[] byteArray = new byte[4];
  325. byteArray[0] = (byte)(i >> 24);
  326. byteArray[1] = (byte)((i & 0xFFFFFF) >> 16);
  327. byteArray[2] = (byte)((i & 0xFFFF) >> 8);
  328. byteArray[3] = (byte)(i & 0xFF);
  329. return byteArray;
  330. }
  331. /**
  332. * 字节数组拼接
  333. *
  334. * @param params
  335. * @return
  336. */
  337. private static byte[] Join(params byte[][] byteArrays)
  338. {
  339. List<byte> byteSource = new List<byte>();
  340. for (int i = 0; i < byteArrays.Length; i++)
  341. {
  342. byteSource.AddRange(byteArrays[i]);
  343. }
  344. byte[] data = byteSource.ToArray();
  345. return data;
  346. }
  347. /**
  348. * 密钥派生函数
  349. *
  350. * @param Z
  351. * @param klen
  352. * 生成klen字节数长度的密钥
  353. * @return
  354. */
  355. private static byte[] KDF(byte[] Z, int klen)
  356. {
  357. int ct = 1;
  358. int end = (int)Math.Ceiling(klen * 1.0 / 32);
  359. List<byte> byteSource = new List<byte>();
  360. try
  361. {
  362. for (int i = 1; i < end; i++)
  363. {
  364. byteSource.AddRange(GmUtil.Sm3(Join(Z, ToByteArray(ct))));
  365. ct++;
  366. }
  367. byte[] last = GmUtil.Sm3(Join(Z, ToByteArray(ct)));
  368. if (klen % 32 == 0)
  369. {
  370. byteSource.AddRange(last);
  371. }
  372. else
  373. byteSource.AddRange(Arrays.CopyOfRange(last, 0, klen % 32));
  374. return byteSource.ToArray();
  375. }
  376. catch (Exception e)
  377. {
  378. //log.Error("KDF error: " + e.Message, e);
  379. }
  380. return null;
  381. }
  382. public static byte[] Sm4DecryptCBC(byte[] keyBytes, byte[] cipher, byte[] iv, String algo)
  383. {
  384. if (keyBytes.Length != 16) throw new ArgumentException("err key length");
  385. if (cipher.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");
  386. try
  387. {
  388. KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
  389. IBufferedCipher c = CipherUtilities.GetCipher(algo);
  390. if (iv == null) iv = ZeroIv(algo);
  391. c.Init(false, new ParametersWithIV(key, iv));
  392. return c.DoFinal(cipher);
  393. }
  394. catch (Exception e)
  395. {
  396. //log.Error("Sm4DecryptCBC error: " + e.Message, e);
  397. return null;
  398. }
  399. }
  400. public static byte[] Sm4EncryptCBC(byte[] keyBytes, byte[] plain, byte[] iv, String algo)
  401. {
  402. if (keyBytes.Length != 16) throw new ArgumentException("err key length");
  403. if (plain.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");
  404. try
  405. {
  406. KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
  407. IBufferedCipher c = CipherUtilities.GetCipher(algo);
  408. if (iv == null) iv = ZeroIv(algo);
  409. c.Init(true, new ParametersWithIV(key, iv));
  410. return c.DoFinal(plain);
  411. }
  412. catch (Exception e)
  413. {
  414. //log.Error("Sm4EncryptCBC error: " + e.Message, e);
  415. return null;
  416. }
  417. }
  418. public static byte[] Sm4EncryptECB(byte[] keyBytes, byte[] plain, string algo)
  419. {
  420. if (keyBytes.Length != 16) throw new ArgumentException("err key length");
  421. //NoPadding 的情况下需要校验数据长度是16的倍数.
  422. if (plain.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");
  423. try
  424. {
  425. KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
  426. IBufferedCipher c = CipherUtilities.GetCipher(algo);
  427. c.Init(true, key);
  428. return c.DoFinal(plain);
  429. }
  430. catch (Exception e)
  431. {
  432. //log.Error("Sm4EncryptECB error: " + e.Message, e);
  433. return null;
  434. }
  435. }
  436. public static byte[] Sm4DecryptECB(byte[] keyBytes, byte[] cipher, string algo)
  437. {
  438. if (keyBytes.Length != 16) throw new ArgumentException("err key length");
  439. if (cipher.Length % 16 != 0 && algo.Contains("NoPadding")) throw new ArgumentException("err data length");
  440. try
  441. {
  442. KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
  443. IBufferedCipher c = CipherUtilities.GetCipher(algo);
  444. c.Init(false, key);
  445. return c.DoFinal(cipher);
  446. }
  447. catch (Exception e)
  448. {
  449. //log.Error("Sm4DecryptECB error: " + e.Message, e);
  450. return null;
  451. }
  452. }
  453. public const String SM4_ECB_NOPADDING = "SM4/ECB/NoPadding";
  454. public const String SM4_CBC_NOPADDING = "SM4/CBC/NoPadding";
  455. public const String SM4_CBC_PKCS7PADDING = "SM4/CBC/PKCS7Padding";
  456. /**
  457. * cfca官网CSP沙箱导出的sm2文件
  458. * @param pem 二进制原文
  459. * @param pwd 密码
  460. * @return
  461. */
  462. public static Sm2Cert readSm2File(byte[] pem, String pwd)
  463. {
  464. Sm2Cert sm2Cert = new Sm2Cert();
  465. try
  466. {
  467. Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(pem);
  468. // ASN1Integer asn1Integer = (ASN1Integer) asn1Sequence.getObjectAt(0); //version=1
  469. Asn1Sequence priSeq = (Asn1Sequence)asn1Sequence[1];//private key
  470. Asn1Sequence pubSeq = (Asn1Sequence)asn1Sequence[2];//public key and x509 cert
  471. // ASN1ObjectIdentifier sm2DataOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(0);
  472. // ASN1ObjectIdentifier sm4AlgOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(1);
  473. Asn1OctetString priKeyAsn1 = (Asn1OctetString)priSeq[2];
  474. byte[] key = KDF(System.Text.Encoding.UTF8.GetBytes(pwd), 32);
  475. byte[] priKeyD = Sm4DecryptCBC(Arrays.CopyOfRange(key, 16, 32),
  476. priKeyAsn1.GetOctets(),
  477. Arrays.CopyOfRange(key, 0, 16), SM4_CBC_PKCS7PADDING);
  478. sm2Cert.privateKey = GetPrivatekeyFromD(new BigInteger(1, priKeyD));
  479. // log.Info(Hex.toHexString(priKeyD));
  480. // ASN1ObjectIdentifier sm2DataOidPub = (ASN1ObjectIdentifier) pubSeq.getObjectAt(0);
  481. Asn1OctetString pubKeyX509 = (Asn1OctetString)pubSeq[1];
  482. X509Certificate x509 = (X509Certificate)new X509CertificateParser().ReadCertificate(pubKeyX509.GetOctets());
  483. sm2Cert.publicKey = x509.GetPublicKey();
  484. sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
  485. return sm2Cert;
  486. }
  487. catch (Exception e)
  488. {
  489. //log.Error("readSm2File error: " + e.Message, e);
  490. return null;
  491. }
  492. }
  493. /**
  494. *
  495. * @param cert
  496. * @return
  497. */
  498. public static Sm2Cert ReadSm2X509Cert(byte[] cert)
  499. {
  500. Sm2Cert sm2Cert = new Sm2Cert();
  501. try
  502. {
  503. X509Certificate x509 = new X509CertificateParser().ReadCertificate(cert);
  504. sm2Cert.publicKey = x509.GetPublicKey();
  505. sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
  506. return sm2Cert;
  507. }
  508. catch (Exception e)
  509. {
  510. //log.Error("ReadSm2X509Cert error: " + e.Message, e);
  511. return null;
  512. }
  513. }
  514. public static byte[] ZeroIv(String algo)
  515. {
  516. try
  517. {
  518. IBufferedCipher cipher = CipherUtilities.GetCipher(algo);
  519. int blockSize = cipher.GetBlockSize();
  520. byte[] iv = new byte[blockSize];
  521. Arrays.Fill(iv, (byte)0);
  522. return iv;
  523. }
  524. catch (Exception e)
  525. {
  526. //log.Error("ZeroIv error: " + e.Message, e);
  527. return null;
  528. }
  529. }
  530. public static void Main2(string[] s)
  531. {
  532. // 随便看看
  533. //log.Info("GMNamedCurves: ");
  534. foreach (string e in GMNamedCurves.Names)
  535. {
  536. //log.Info(e);
  537. }
  538. //log.Info("sm2p256v1 n:" + x9ECParameters.N);
  539. //log.Info("sm2p256v1 nHex:" + Hex.ToHexString(x9ECParameters.N.ToByteArray()));
  540. // 生成公私钥对 ---------------------
  541. AsymmetricCipherKeyPair kp = GmUtil.GenerateKeyPair();
  542. //log.Info("private key d: " + ((ECPrivateKeyParameters)kp.Private).D);
  543. //log.Info("public key q:" + ((ECPublicKeyParameters)kp.Public).Q); //{x, y, zs...}
  544. //签名验签
  545. byte[] msg = System.Text.Encoding.UTF8.GetBytes("message digest");
  546. byte[] userId = System.Text.Encoding.UTF8.GetBytes("userId");
  547. byte[] sig = SignSm3WithSm2(msg, userId, kp.Private);
  548. //log.Info("testSignSm3WithSm2: " + Hex.ToHexString(sig));
  549. //log.Info("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, kp.Public));
  550. // 由d生成私钥 ---------------------
  551. BigInteger d = new BigInteger("097b5230ef27c7df0fa768289d13ad4e8a96266f0fcb8de40d5942af4293a54a", 16);
  552. ECPrivateKeyParameters bcecPrivateKey = GetPrivatekeyFromD(d);
  553. //log.Info("testGetFromD: " + bcecPrivateKey.D.ToString(16));
  554. //公钥X坐标PublicKeyXHex: 59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4
  555. //公钥Y坐标PublicKeyYHex: 9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8
  556. AsymmetricKeyParameter publicKey = GetPublickeyFromX509File(new FileInfo("d:/certs/69629141652.cer"));
  557. //log.Info(publicKey);
  558. AsymmetricKeyParameter publicKey1 = GetPublickeyFromXY(new BigInteger("59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4", 16), new BigInteger("9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8", 16));
  559. //log.Info("testReadFromX509File: " + ((ECPublicKeyParameters)publicKey).Q);
  560. //log.Info("testGetFromXY: " + ((ECPublicKeyParameters)publicKey1).Q);
  561. //log.Info("testPubKey: " + publicKey.Equals(publicKey1));
  562. //log.Info("testPubKey: " + ((ECPublicKeyParameters)publicKey).Q.Equals(((ECPublicKeyParameters)publicKey1).Q));
  563. // sm2 encrypt and decrypt test ---------------------
  564. AsymmetricCipherKeyPair kp2 = GenerateKeyPair();
  565. AsymmetricKeyParameter publicKey2 = kp2.Public;
  566. AsymmetricKeyParameter privateKey2 = kp2.Private;
  567. byte[] bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), publicKey2);
  568. //log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
  569. bs = Sm2Decrypt(bs, privateKey2);
  570. //log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
  571. // sm4 encrypt and decrypt test ---------------------
  572. //0123456789abcdeffedcba9876543210 + 0123456789abcdeffedcba9876543210 -> 681edf34d206965e86b3e94f536e4246
  573. byte[] plain = Hex.Decode("0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210");
  574. byte[] key = Hex.Decode("0123456789abcdeffedcba9876543210");
  575. byte[] cipher = Hex.Decode("595298c7c6fd271f0402f804c33d3f66");
  576. bs = Sm4EncryptECB(key, plain, GmUtil.SM4_ECB_NOPADDING);
  577. //log.Info("testSm4EncEcb: " + Hex.ToHexString(bs)); ;
  578. bs = Sm4DecryptECB(key, bs, GmUtil.SM4_ECB_NOPADDING);
  579. //log.Info("testSm4DecEcb: " + Hex.ToHexString(bs));
  580. //读.sm2文件
  581. String sm2 = "MIIDHQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDW5/I9kZhObxXE9Vh1CzHdZhIhxn+3byBU\nUrzmGRKbDRMgI3hJKdvpqWkM5G4LNcIwggLNBgoqgRzPVQYBBAIBBIICvTCCArkwggJdoAMCAQIC\nBRA2QSlgMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu\nY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex\nMB4XDTE4MTEyNjEwMTQxNVoXDTIwMTEyNjEwMTQxNVowcjELMAkGA1UEBhMCY24xEjAQBgNVBAoM\nCUNGQ0EgT0NBMTEOMAwGA1UECwwFQ1VQUkExFDASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQD\nDCAwNDFAWnRlc3RAMDAwMTAwMDA6U0lHTkAwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYIt\nA0IABDRNKhvnjaMUShsM4MJ330WhyOwpZEHoAGfqxFGX+rcL9x069dyrmiF3+2ezwSNh1/6YqfFZ\nX9koM9zE5RG4USmjgfMwgfAwHwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0g\nBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3Vz\nL3VzLTE0Lmh0bTA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIv\nY3JsNDI4NS5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBREhx9VlDdMIdIbhAxKnGhPx8FcHDAd\nBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANIADBFAiEAgWvQi3h6\niW4jgF4huuXfhWInJmTTYr2EIAdG8V4M8fYCIBixygdmfPL9szcK2pzCYmIb6CBzo5SMv50Odycc\nVfY6";
  582. bs = Convert.FromBase64String(sm2);
  583. String pwd = "cfca1234";
  584. GmUtil.Sm2Cert sm2Cert = GmUtil.readSm2File(bs, pwd);
  585. //log.Info("testReadSm2File, pubkey: " + ((ECPublicKeyParameters)sm2Cert.publicKey).Q.ToString());
  586. //log.Info("testReadSm2File, prikey: " + Hex.ToHexString(((ECPrivateKeyParameters)sm2Cert.privateKey).D.ToByteArray()));
  587. //log.Info("testReadSm2File, certId: " + sm2Cert.certId);
  588. bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), ((ECPublicKeyParameters)sm2Cert.publicKey));
  589. //log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
  590. bs = Sm2Decrypt(bs, ((ECPrivateKeyParameters)sm2Cert.privateKey));
  591. //log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
  592. msg = System.Text.Encoding.UTF8.GetBytes("message digest");
  593. userId = System.Text.Encoding.UTF8.GetBytes("userId");
  594. sig = SignSm3WithSm2(msg, userId, ((ECPrivateKeyParameters)sm2Cert.privateKey));
  595. //log.Info("testSignSm3WithSm2: " + Hex.ToHexString(sig));
  596. //log.Info("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, ((ECPublicKeyParameters)sm2Cert.publicKey)));
  597. }
  598. }
  599. }

使用:

  1. using CommonUtils;
  2. using Org.BouncyCastle.Crypto;
  3. using Org.BouncyCastle.Math;
  4. using Org.BouncyCastle.Utilities.Encoders;
  5. using System.Text;
  6. void TestSM3()
  7. {
  8. String content = "1234泰酷拉";
  9. Console.WriteLine("待处理字符串:" + content);
  10. byte[] digestByte = GmUtil.Sm3(Encoding.UTF8.GetBytes(content));
  11. string strSM3 = Hex.ToHexString(digestByte);
  12. Console.WriteLine("SM3 HASH后:" + strSM3);
  13. string javaSM3 = "40f9b63398b72bee91f5e59c3c3d7fe9f66c4fb1637ec7adb9babb880e6489ec";
  14. Console.WriteLine("javaSM3:" + javaSM3);
  15. if (strSM3 == javaSM3)
  16. {
  17. Console.WriteLine("相等");
  18. }
  19. }

JAVA 代码:

maven 引用这2个包。

  1. <dependency>
  2. <groupId>cn.hutool</groupId>
  3. <artifactId>hutool-all</artifactId>
  4. <version>5.8.1</version>
  5. </dependency>
  6.  
  7. <dependency>
  8. <groupId>org.bouncycastle</groupId>
  9. <artifactId>bcprov-jdk15on</artifactId>
  10. <version>1.70</version>
  11. </dependency>

调用:

  1. package org.example;
  2. import cn.hutool.crypto.SmUtil;
  3. import cn.hutool.crypto.asymmetric.KeyType;
  4. import cn.hutool.crypto.asymmetric.SM2;
  5. import org.bouncycastle.crypto.engines.SM2Engine;
  6. import org.bouncycastle.util.encoders.Hex;
  7. static void testSM3() {
  8. String content = "1234泰酷拉";
  9. System.out.println("待处理字符串:" + content);
  10. String digestHex = SmUtil.sm3(content);
  11. System.out.println("SM3 HASH后:" + digestHex);
  12. }

 

end

原文链接:https://www.cnblogs.com/runliuv/p/17604030.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号