SM2.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package com.security.cipher.sm;
  2. import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
  3. import org.bouncycastle.crypto.params.ECDomainParameters;
  4. import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
  5. import org.bouncycastle.math.ec.ECCurve;
  6. import org.bouncycastle.math.ec.ECFieldElement;
  7. import org.bouncycastle.math.ec.ECFieldElement.Fp;
  8. import org.bouncycastle.math.ec.ECPoint;
  9. import java.math.BigInteger;
  10. import java.security.SecureRandom;
  11. public class SM2
  12. {
  13. /*
  14. // 测试参数
  15. public static final String[] ecc_param = {
  16. "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",
  17. "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",
  18. "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",
  19. "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",
  20. "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",
  21. "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"
  22. };
  23. */
  24. // 正式参数
  25. public static String[] ecc_param = {
  26. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
  27. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
  28. "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
  29. "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
  30. "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
  31. "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
  32. };
  33. public static SM2 Instance()
  34. {
  35. return new SM2();
  36. }
  37. public final BigInteger ecc_p;
  38. public final BigInteger ecc_a;
  39. public final BigInteger ecc_b;
  40. public final BigInteger ecc_n;
  41. public final BigInteger ecc_gx;
  42. public final BigInteger ecc_gy;
  43. public final ECCurve ecc_curve;
  44. public final ECPoint ecc_point_g;
  45. public final ECDomainParameters ecc_bc_spec;
  46. public final ECKeyPairGenerator ecc_key_pair_generator;
  47. public final ECFieldElement ecc_gx_fieldelement;
  48. public final ECFieldElement ecc_gy_fieldelement;
  49. public SM2()
  50. {
  51. this.ecc_p = new BigInteger(ecc_param[0], 16);
  52. this.ecc_a = new BigInteger(ecc_param[1], 16);
  53. this.ecc_b = new BigInteger(ecc_param[2], 16);
  54. this.ecc_n = new BigInteger(ecc_param[3], 16);
  55. this.ecc_gx = new BigInteger(ecc_param[4], 16);
  56. this.ecc_gy = new BigInteger(ecc_param[5], 16);
  57. this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);
  58. this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);
  59. this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);
  60. this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);
  61. this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
  62. ECKeyGenerationParameters ecc_ecgenparam;
  63. ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
  64. this.ecc_key_pair_generator = new ECKeyPairGenerator();
  65. this.ecc_key_pair_generator.init(ecc_ecgenparam);
  66. }
  67. public byte[] sm2GetZ(byte[] userId, ECPoint userKey)
  68. {
  69. SM3Digest sm3 = new SM3Digest();
  70. int len = userId.length * 8;
  71. sm3.update((byte) (len >> 8 & 0xFF));
  72. sm3.update((byte) (len & 0xFF));
  73. sm3.update(userId, 0, userId.length);
  74. byte[] p = Util.byteConvert32Bytes(ecc_a);
  75. sm3.update(p, 0, p.length);
  76. p = Util.byteConvert32Bytes(ecc_b);
  77. sm3.update(p, 0, p.length);
  78. p = Util.byteConvert32Bytes(ecc_gx);
  79. sm3.update(p, 0, p.length);
  80. p = Util.byteConvert32Bytes(ecc_gy);
  81. sm3.update(p, 0, p.length);
  82. p = Util.byteConvert32Bytes(userKey.getX().toBigInteger());
  83. sm3.update(p, 0, p.length);
  84. p = Util.byteConvert32Bytes(userKey.getY().toBigInteger());
  85. sm3.update(p, 0, p.length);
  86. byte[] md = new byte[sm3.getDigestSize()];
  87. sm3.doFinal(md, 0);
  88. return md;
  89. }
  90. public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey, SM2Result sm2Result)
  91. {
  92. BigInteger e = new BigInteger(1, md);
  93. BigInteger k = null;
  94. ECPoint kp = null;
  95. BigInteger r = null;
  96. BigInteger s = null;
  97. do
  98. {
  99. do
  100. {
  101. // 正式环境
  102. /*AsymmetricCipherKeyPair keypair = ecc_key_pair_generator.generateKeyPair();
  103. ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();
  104. ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();
  105. k = ecpriv.getD();
  106. kp = ecpub.getQ();*/
  107. // 国密规范测试 随机数k
  108. String kS = "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F";
  109. k = new BigInteger(kS, 16);
  110. kp = this.ecc_point_g.multiply(k);
  111. System.out.println("计算曲线点X1: " + kp.getX().toBigInteger().toString(16));
  112. System.out.println("计算曲线点Y1: " + kp.getY().toBigInteger().toString(16));
  113. System.out.println("");
  114. // r
  115. r = e.add(kp.getX().toBigInteger());
  116. r = r.mod(ecc_n);
  117. } while (r.equals(BigInteger.ZERO) || r.add(k).equals(ecc_n));
  118. // (1 + dA)~-1
  119. BigInteger da_1 = userD.add(BigInteger.ONE);
  120. da_1 = da_1.modInverse(ecc_n);
  121. // s
  122. s = r.multiply(userD);
  123. s = k.subtract(s).mod(ecc_n);
  124. s = da_1.multiply(s).mod(ecc_n);
  125. } while (s.equals(BigInteger.ZERO));
  126. sm2Result.r = r;
  127. sm2Result.s = s;
  128. }
  129. public void sm2Verify(byte md[], ECPoint userKey, BigInteger r, BigInteger s, SM2Result sm2Result)
  130. {
  131. sm2Result.R = null;
  132. BigInteger e = new BigInteger(1, md);
  133. BigInteger t = r.add(s).mod(ecc_n);
  134. if(t.equals(BigInteger.ZERO))
  135. {
  136. return;
  137. }
  138. else
  139. {
  140. ECPoint x1y1 = ecc_point_g.multiply(sm2Result.s);
  141. System.out.println("计算曲线点X0: " + x1y1.getX().toBigInteger().toString(16));
  142. System.out.println("计算曲线点Y0: " + x1y1.getY().toBigInteger().toString(16));
  143. System.out.println("");
  144. x1y1 = x1y1.add(userKey.multiply(t));
  145. System.out.println("计算曲线点X1: " + x1y1.getX().toBigInteger().toString(16));
  146. System.out.println("计算曲线点Y1: " + x1y1.getY().toBigInteger().toString(16));
  147. System.out.println("");
  148. sm2Result.R = e.add(x1y1.getX().toBigInteger()).mod(ecc_n);
  149. System.out.println("R: " + sm2Result.R.toString(16));
  150. return;
  151. }
  152. }
  153. }