001package top.cenze.utils.crypt.sm.sm2; 002 003import org.bouncycastle.asn1.*; 004import org.bouncycastle.crypto.digests.SM3Digest; 005import org.bouncycastle.math.ec.ECPoint; 006import top.cenze.utils.ConvertUtil; 007 008import java.io.ByteArrayInputStream; 009import java.math.BigInteger; 010import java.util.Enumeration; 011 012/** 013 * 国密算法的签名、验签 014 */ 015public class SM2SignVerUtils { 016 /** 017 * 默认USERID 018 */ 019 public static String USER_ID = "1234567812345678"; 020 /** 021 * 私钥签名 022 * 使用SM3进行对明文数据计算一个摘要值 023 * @param privatekey 私钥 024 * @param sourceData 明文数据 025 * @return 签名后的值 026 * @throws Exception 027 */ 028 public static SM2SignVO Sign2SM2(byte[] privatekey,byte[] sourceData) throws Exception { 029 SM2SignVO sm2SignVO = new SM2SignVO(); 030 sm2SignVO.setSm2_type("sign"); 031 SM2Factory factory = SM2Factory.getInstance(); 032 BigInteger userD = new BigInteger(1,privatekey); 033 //System.out.println("userD:"+userD.toString(16)); 034 sm2SignVO.setSm2_userd(userD.toString(16)); 035 036 ECPoint userKey = factory.ecc_point_g.multiply(userD); 037 //System.out.println("椭圆曲线点X: "+ userKey.getXCoord().toBigInteger().toString(16)); 038 //System.out.println("椭圆曲线点Y: "+ userKey.getYCoord().toBigInteger().toString(16)); 039 040 SM3Digest sm3Digest = new SM3Digest(); 041 byte [] z = factory.sm2GetZ(USER_ID.getBytes(), userKey); 042 //System.out.println("SM3摘要Z: " + Util.getHexString(z)); 043 //System.out.println("被加密数据的16进制: " + Util.getHexString(sourceData)); 044 sm2SignVO.setSm3_z(ConvertUtil.getHexString(z)); 045 sm2SignVO.setSign_express(ConvertUtil.getHexString(sourceData)); 046 047 sm3Digest.update(z, 0, z.length); 048 sm3Digest.update(sourceData,0,sourceData.length); 049 byte [] md = new byte[32]; 050 sm3Digest.doFinal(md, 0); 051 //System.out.println("SM3摘要值: " + ConvertUtil.getHexString(md)); 052 sm2SignVO.setSm3_digest(ConvertUtil.getHexString(md)); 053 054 SM2Result sm2Result = new SM2Result(); 055 factory.sm2Sign(md, userD, userKey, sm2Result); 056 //System.out.println("r: " + sm2Result.r.toString(16)); 057 //System.out.println("s: " + sm2Result.s.toString(16)); 058 sm2SignVO.setSign_r(sm2Result.r.toString(16)); 059 sm2SignVO.setSign_s(sm2Result.s.toString(16)); 060 061 ASN1Integer d_r = new ASN1Integer(sm2Result.r); 062 ASN1Integer d_s = new ASN1Integer(sm2Result.s); 063 ASN1EncodableVector v2 = new ASN1EncodableVector(); 064 v2.add(d_r); 065 v2.add(d_s); 066 DERSequence sign = new DERSequence(v2); 067 String result = ConvertUtil.byteToHex(sign.getEncoded()); 068 sm2SignVO.setSm2_sign(result); 069 return sm2SignVO; 070 } 071 /** 072 * 验证签名 073 * @param publicKey 公钥信息 074 * @param sourceData 密文信息 075 * @param signData 签名信息 076 * @return 验签的对象 包含了相关参数和验签结果 077 */ 078 @SuppressWarnings("unchecked") 079 public static SM2SignVO VerifySignSM2(byte[] publicKey,byte[] sourceData,byte[] signData){ 080 try { 081 byte[] formatedPubKey; 082 SM2SignVO verifyVo = new SM2SignVO(); 083 verifyVo.setSm2_type("verify"); 084 if (publicKey.length == 64) { 085 // 添加一字节标识,用于ECPoint解析 086 formatedPubKey = new byte[65]; 087 formatedPubKey[0] = 0x04; 088 System.arraycopy(publicKey, 0, formatedPubKey, 1, publicKey.length); 089 } else{ 090 formatedPubKey = publicKey; 091 } 092 SM2Factory factory = SM2Factory.getInstance(); 093 ECPoint userKey = factory.ecc_curve.decodePoint(formatedPubKey); 094 095 SM3Digest sm3Digest = new SM3Digest(); 096 byte [] z = factory.sm2GetZ(USER_ID.getBytes(), userKey); 097 //System.out.println("SM3摘要Z: " + ConvertUtil.getHexString(z)); 098 verifyVo.setSm3_z(ConvertUtil.getHexString(z)); 099 sm3Digest.update(z,0,z.length); 100 sm3Digest.update(sourceData,0,sourceData.length); 101 byte [] md = new byte[32]; 102 sm3Digest.doFinal(md, 0); 103 //System.out.println("SM3摘要值: " + ConvertUtil.getHexString(md)); 104 verifyVo.setSm3_digest(ConvertUtil.getHexString(md)); 105 ByteArrayInputStream bis = new ByteArrayInputStream(signData); 106 ASN1InputStream dis = new ASN1InputStream(bis); 107 SM2Result sm2Result = null; 108 ASN1Primitive derObj = dis.readObject(); 109 Enumeration<ASN1Integer> e = ((ASN1Sequence)derObj).getObjects(); 110 BigInteger r = ((ASN1Integer) e.nextElement()).getValue(); 111 BigInteger s = ((ASN1Integer) e.nextElement()).getValue(); 112 sm2Result = new SM2Result(); 113 sm2Result.r = r; 114 sm2Result.s = s; 115 //System.out.println("vr: " + sm2Result.r.toString(16)); 116 //System.out.println("vs: " + sm2Result.s.toString(16)); 117 verifyVo.setVerify_r(sm2Result.r.toString(16)); 118 verifyVo.setVerify_s(sm2Result.s.toString(16)); 119 factory.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result); 120 boolean verifyFlag = sm2Result.r.equals(sm2Result.R); 121 verifyVo.setVerify(verifyFlag); 122 return verifyVo; 123 } catch (IllegalArgumentException e) { 124 return null; 125 }catch (Exception e) { 126 e.printStackTrace(); 127 return null; 128 } 129 } 130 131// public static void main(String[] args) throws Exception { 132// String text = "这是一段明文"; 133// byte [] sourceData = text.getBytes(); 134// //String publicKey ="FA05C51AD1162133DFDF862ECA5E4A481B52FB37FF83E53D45FD18BBD6F32668A92C4692EEB305684E3B9D4ACE767F91D5D108234A9F07936020A92210BA9447"; 135// //String privatekey = "5EB4DF17021CC719B678D970C620690A11B29C8357D71FA4FF9BF7FB6D89767A"; 136// String publicKey ="04BB34D657EE7E8490E66EF577E6B3CEA28B739511E787FB4F71B7F38F241D87F18A5A93DF74E90FF94F4EB907F271A36B295B851F971DA5418F4915E2C1A23D6E"; 137// String privatekey = "0B1CE43098BC21B8E82B5C065EDB534CB86532B1900A49D49F3C53762D2997FA"; 138// SM2SignVO sign = SM2SignVerUtils.Sign2SM2(ConvertUtil.hexStringToBytes(privatekey), sourceData); 139// SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(ConvertUtil.hexStringToBytes(publicKey), sourceData, ConvertUtil.hexStringToBytes(sign.getSm2_signForSoft())); 140// System.out.println("签名得到的r值:"+sign.getSign_r()+"\n签名值 "+sign.getSm2_signForSoft()); 141// System.out.println("验签得到的R值:"+verify.getVerify_r()); 142// System.err.println("\n验签结果" +verify.isVerify()); 143// } 144}