SM2Utils.java 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package com.security.cipher.sm;
  2. import org.bouncycastle.asn1.ASN1EncodableVector;
  3. import org.bouncycastle.asn1.ASN1InputStream;
  4. import org.bouncycastle.asn1.ASN1Sequence;
  5. import org.bouncycastle.asn1.DERInteger;
  6. import org.bouncycastle.asn1.DERObject;
  7. import org.bouncycastle.asn1.DERSequence;
  8. import org.bouncycastle.math.ec.ECPoint;
  9. import java.io.ByteArrayInputStream;
  10. import java.io.IOException;
  11. import java.math.BigInteger;
  12. import java.util.Enumeration;
  13. public class SM2Utils
  14. {
  15. public static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException
  16. {
  17. if (publicKey == null || publicKey.length == 0)
  18. {
  19. return null;
  20. }
  21. if (data == null || data.length == 0)
  22. {
  23. return null;
  24. }
  25. byte[] source = new byte[data.length];
  26. System.arraycopy(data, 0, source, 0, data.length);
  27. Cipher cipher = new Cipher();
  28. SM2 sm2 = SM2.Instance();
  29. ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
  30. ECPoint c1 = cipher.Init_enc(sm2, userKey);
  31. cipher.Encrypt(source);
  32. byte[] c3 = new byte[32];
  33. cipher.Dofinal(c3);
  34. // System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
  35. // System.out.println("C2 " + Util.byteToHex(source));
  36. // System.out.println("C3 " + Util.byteToHex(c3));
  37. //C1 C2 C3拼装成加密字串
  38. String encryptdata = Util.encodeHexString(c1.getEncoded())+Util.encodeHexString(source)+Util.encodeHexString(c3);
  39. return Util.hexStringToBytes(encryptdata);
  40. /*
  41. DERInteger x = new DERInteger(c1.getX().toBigInteger());
  42. DERInteger y = new DERInteger(c1.getY().toBigInteger());
  43. DEROctetString derDig = new DEROctetString(c3);
  44. DEROctetString derEnc = new DEROctetString(source);
  45. ASN1EncodableVector v = new ASN1EncodableVector();
  46. v.add(x);
  47. v.add(y);
  48. v.add(derDig);
  49. v.add(derEnc);
  50. DERSequence seq = new DERSequence(v);
  51. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  52. DEROutputStream dos = new DEROutputStream(bos);
  53. dos.writeObject(seq);
  54. return bos.toByteArray();
  55. */
  56. }
  57. public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException
  58. {
  59. if (privateKey == null || privateKey.length == 0)
  60. {
  61. return null;
  62. }
  63. if (encryptedData == null || encryptedData.length == 0)
  64. {
  65. return null;
  66. }
  67. //byte[] enc = new byte[encryptedData.length];
  68. //System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length);
  69. //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
  70. String data = Util.byteToHex(encryptedData);
  71. /***分解加密字串
  72. * (C1 = C1标志位2位 + C1实体部分128位 = 130)
  73. * (C3 = C3实体部分64位 = 64)
  74. * (C2 = encryptedData.length * 2 - C1长度 - C2长度)
  75. */
  76. byte[] c1Bytes = Util.hexToByte(data.substring(0,130));
  77. int c2Len = encryptedData.length - 97;
  78. byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));
  79. byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len));
  80. SM2 sm2 = SM2.Instance();
  81. BigInteger userD = new BigInteger(1, privateKey);
  82. /*
  83. ByteArrayInputStream bis = new ByteArrayInputStream(enc);
  84. ASN1InputStream dis = new ASN1InputStream(bis);
  85. DERObject derObj = dis.readObject();
  86. ASN1Sequence asn1 = (ASN1Sequence) derObj;
  87. DERInteger x = (DERInteger) asn1.getObjectAt(0);
  88. DERInteger y = (DERInteger) asn1.getObjectAt(1);
  89. ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true);
  90. Cipher cipher = new Cipher();
  91. cipher.Init_dec(userD, c1);
  92. DEROctetString data = (DEROctetString) asn1.getObjectAt(3);
  93. enc = data.getOctets();
  94. cipher.Decrypt(enc);
  95. byte[] c3 = new byte[32];
  96. cipher.Dofinal(c3);
  97. return enc;
  98. */
  99. //通过C1实体字节来生成ECPoint
  100. ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
  101. Cipher cipher = new Cipher();
  102. cipher.Init_dec(userD, c1);
  103. cipher.Decrypt(c2);
  104. cipher.Dofinal(c3);
  105. //返回解密结果
  106. return c2;
  107. }
  108. public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException
  109. {
  110. if (privateKey == null || privateKey.length == 0)
  111. {
  112. return null;
  113. }
  114. if (sourceData == null || sourceData.length == 0)
  115. {
  116. return null;
  117. }
  118. SM2 sm2 = SM2.Instance();
  119. BigInteger userD = new BigInteger(privateKey);
  120. System.out.println("userD: " + userD.toString(16));
  121. System.out.println("");
  122. ECPoint userKey = sm2.ecc_point_g.multiply(userD);
  123. System.out.println("椭圆曲线点X: " + userKey.getX().toBigInteger().toString(16));
  124. System.out.println("椭圆曲线点Y: " + userKey.getY().toBigInteger().toString(16));
  125. System.out.println("");
  126. SM3Digest sm3 = new SM3Digest();
  127. byte[] z = sm2.sm2GetZ(userId, userKey);
  128. System.out.println("SM3摘要Z: " + Util.getHexString(z));
  129. System.out.println("");
  130. System.out.println("M: " + Util.getHexString(sourceData));
  131. System.out.println("");
  132. sm3.update(z, 0, z.length);
  133. sm3.update(sourceData, 0, sourceData.length);
  134. byte[] md = new byte[32];
  135. sm3.doFinal(md, 0);
  136. System.out.println("SM3摘要值: " + Util.getHexString(md));
  137. System.out.println("");
  138. SM2Result sm2Result = new SM2Result();
  139. sm2.sm2Sign(md, userD, userKey, sm2Result);
  140. System.out.println("r: " + sm2Result.r.toString(16));
  141. System.out.println("s: " + sm2Result.s.toString(16));
  142. System.out.println("");
  143. DERInteger d_r = new DERInteger(sm2Result.r);
  144. DERInteger d_s = new DERInteger(sm2Result.s);
  145. ASN1EncodableVector v2 = new ASN1EncodableVector();
  146. v2.add(d_r);
  147. v2.add(d_s);
  148. DERObject sign = new DERSequence(v2);
  149. byte[] signdata = sign.getDEREncoded();
  150. return signdata;
  151. }
  152. @SuppressWarnings("unchecked")
  153. public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException
  154. {
  155. if (publicKey == null || publicKey.length == 0)
  156. {
  157. return false;
  158. }
  159. if (sourceData == null || sourceData.length == 0)
  160. {
  161. return false;
  162. }
  163. SM2 sm2 = SM2.Instance();
  164. ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
  165. SM3Digest sm3 = new SM3Digest();
  166. byte[] z = sm2.sm2GetZ(userId, userKey);
  167. sm3.update(z, 0, z.length);
  168. sm3.update(sourceData, 0, sourceData.length);
  169. byte[] md = new byte[32];
  170. sm3.doFinal(md, 0);
  171. System.out.println("SM3摘要值: " + Util.getHexString(md));
  172. System.out.println("");
  173. ByteArrayInputStream bis = new ByteArrayInputStream(signData);
  174. ASN1InputStream dis = new ASN1InputStream(bis);
  175. DERObject derObj = dis.readObject();
  176. Enumeration<DERInteger> e = ((ASN1Sequence) derObj).getObjects();
  177. BigInteger r = ((DERInteger)e.nextElement()).getValue();
  178. BigInteger s = ((DERInteger)e.nextElement()).getValue();
  179. SM2Result sm2Result = new SM2Result();
  180. sm2Result.r = r;
  181. sm2Result.s = s;
  182. System.out.println("r: " + sm2Result.r.toString(16));
  183. System.out.println("s: " + sm2Result.s.toString(16));
  184. System.out.println("");
  185. sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
  186. return sm2Result.r.equals(sm2Result.R);
  187. }
  188. /*
  189. public static void main(String[] args) throws Exception
  190. {
  191. String plainText = "message digest";
  192. byte[] sourceData = plainText.getBytes();
  193. // 国密规范测试私钥
  194. String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263";
  195. String prikS = new String(Base64.encode(Util.hexToByte(prik)));
  196. System.out.println("prikS: " + prikS);
  197. System.out.println("");
  198. // 国密规范测试用户ID
  199. String userId = "[email protected]";
  200. System.out.println("ID: " + Util.getHexString(userId.getBytes()));
  201. System.out.println("");
  202. System.out.println("签名: ");
  203. byte[] c = SM2Utils.sign(userId.getBytes(), Base64.decode(prikS.getBytes()), sourceData);
  204. System.out.println("sign: " + Util.getHexString(c));
  205. System.out.println("");
  206. // 国密规范测试公钥
  207. String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857";
  208. String pubkS = new String(Base64.encode(Util.hexToByte(pubk)));
  209. System.out.println("pubkS: " + pubkS);
  210. System.out.println("");
  211. System.out.println("验签: ");
  212. boolean vs = SM2Utils.verifySign(userId.getBytes(), Base64.decode(pubkS.getBytes()), sourceData, c);
  213. System.out.println("验签结果: " + vs);
  214. System.out.println("");
  215. System.out.println("加密: ");
  216. byte[] cipherText = SM2Utils.encrypt(Base64.decode(pubkS.getBytes()), sourceData);
  217. System.out.println(new String(Base64.encode(cipherText)));
  218. System.out.println("");
  219. System.out.println("解密: ");
  220. plainText = new String(SM2Utils.decrypt(Base64.decode(prikS.getBytes()), cipherText));
  221. System.out.println(plainText);
  222. }
  223. */
  224. public static void SM2_TEST() throws Exception
  225. {
  226. String plainText = "1122334455667788";
  227. byte[] sourceData = Util.hexStringToBytes(plainText);
  228. // 国密规范测试私钥
  229. String prik = "969FC0F73FA117A040B37D5B5018382A74D40590EAA02809B87FA09196F8276D";
  230. // 国密规范测试公钥
  231. String pubk = "04ABC2230A05A72CEB667B20019C4F2A580E4D0A3BE9D20BF914565AB3B82631E1C0E15803FA3ADE3E6D9EEF293CBD8BAECC51D82B61404A39584198B6985686FB";
  232. System.out.println("加密: ");
  233. byte[] cipherText = SM2Utils.encrypt(Util.hexStringToBytes(pubk), sourceData);
  234. System.out.println(Util.encodeHexString(cipherText));
  235. System.out.println("");
  236. System.out.println("解密: ");
  237. String data = "04ADE0AFDD137B5E9B2CF3F4D71D329E06F3E8006598A12BB8B6A4B31F8E1D2266EFB1015812E10DC058940A3C8AB8BA29FFE788F85A5D236C3526BBA8D0E0A10D5806DAE0C2DEFADC1A49CE657D4311CDF65D9F38F1CF5004F2E4BA922EA538C9E75007CA0C7AADD8";
  238. plainText = Util.encodeHexString(SM2Utils.decrypt(Util.hexStringToBytes(prik), Util.hexStringToBytes(data)));
  239. System.out.println(plainText);
  240. }
  241. }