001package top.cenze.utils.crypt.sm.sm2; 002 003import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 004import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 005import org.bouncycastle.crypto.params.ECPublicKeyParameters; 006import org.bouncycastle.math.ec.ECPoint; 007import top.cenze.utils.ConvertUtil; 008 009import java.io.IOException; 010import java.math.BigInteger; 011 012public class SM2EncDecUtils { 013 //生成随机秘钥对 014 public static SM2KeyVO generateKeyPair(){ 015 SM2 sm2 = SM2.Instance(); 016 AsymmetricCipherKeyPair key = null; 017 while (true){ 018 key=sm2.ecc_key_pair_generator.generateKeyPair(); 019 if(((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length==32){ 020 break; 021 } 022 } 023 ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate(); 024 ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic(); 025 BigInteger privateKey = ecpriv.getD(); 026 ECPoint publicKey = ecpub.getQ(); 027 SM2KeyVO sm2KeyVO = new SM2KeyVO(); 028 sm2KeyVO.setPublicKey(publicKey); 029 sm2KeyVO.setPrivateKey(privateKey); 030 //System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded())); 031 //System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray())); 032 return sm2KeyVO; 033 } 034 035 //数据加密 036 public static String encrypt(byte[] publicKey, byte[] data) throws IOException 037 { 038 if (publicKey == null || publicKey.length == 0) 039 { 040 return null; 041 } 042 043 if (data == null || data.length == 0) 044 { 045 return null; 046 } 047 048 byte[] source = new byte[data.length]; 049 System.arraycopy(data, 0, source, 0, data.length); 050 051 Cipher cipher = new Cipher(); 052 SM2 sm2 = SM2.Instance(); 053 ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); 054 055 ECPoint c1 = cipher.Init_enc(sm2, userKey); 056 cipher.Encrypt(source); 057 byte[] c3 = new byte[32]; 058 cipher.Dofinal(c3); 059 060// System.out.println("C1 " + Util.byteToHex(c1.getEncoded())); 061// System.out.println("C2 " + Util.byteToHex(source)); 062// System.out.println("C3 " + Util.byteToHex(c3)); 063 //C1 C2 C3拼装成加密字串 064 // C1 | C2 | C3 065 //return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3); 066 // C1 | C3 | C2 067 return ConvertUtil.byteToHex(c1.getEncoded()) + ConvertUtil.byteToHex(c3) + ConvertUtil.byteToHex(source); 068 } 069 070 //数据解密 071 public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException 072 { 073 if (privateKey == null || privateKey.length == 0) 074 { 075 return null; 076 } 077 078 if (encryptedData == null || encryptedData.length == 0) 079 { 080 return null; 081 } 082 //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2 083 String data = ConvertUtil.byteToHex(encryptedData); 084 /***分解加密字串 C1 | C2 | C3 085 * (C1 = C1标志位2位 + C1实体部分128位 = 130) 086 * (C3 = C3实体部分64位 = 64) 087 * (C2 = encryptedData.length * 2 - C1长度 - C2长度) 088 089 byte[] c1Bytes = Util.hexToByte(data.substring(0,130)); 090 int c2Len = encryptedData.length - 97; 091 byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len)); 092 byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len)); 093 */ 094 /***分解加密字串 C1 | C3 | C2 095 * (C1 = C1标志位2位 + C1实体部分128位 = 130) 096 * (C3 = C3实体部分64位 = 64) 097 * (C2 = encryptedData.length * 2 - C1长度 - C2长度) 098 */ 099 byte[] c1Bytes = ConvertUtil.hexToByte(data.substring(0,130)); 100 int c2Len = encryptedData.length - 97; 101 byte[] c3 = ConvertUtil.hexToByte(data.substring(130,130 + 64)); 102 byte[] c2 = ConvertUtil.hexToByte(data.substring(194,194 + 2 * c2Len)); 103 104 SM2 sm2 = SM2.Instance(); 105 BigInteger userD = new BigInteger(1, privateKey); 106 107 //通过C1实体字节来生成ECPoint 108 ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes); 109 Cipher cipher = new Cipher(); 110 cipher.Init_dec(userD, c1); 111 cipher.Decrypt(c2); 112 cipher.Dofinal(c3); 113 114 //返回解密结果 115 return c2; 116 } 117 118/* public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair) 119 { 120 SM3Digest sm3 = new SM3Digest(); 121 122 ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.getPublic(); 123 124 byte[] z = SM2CryptoServiceProvider.Sm2GetZ(Encoding.Default.GetBytes(SM2CryptoServiceProvider.userId), ecpub.getQ()); 125 sm3.update(z, 0, z.length); 126 127 byte[] p = md; 128 sm3.update(p, 0, p.length); 129 130 byte[] hashData = new byte[32]; 131 sm3.doFinal(hashData, 0); 132 133 // e 134 BigInteger e = new BigInteger(1, hashData); 135 // k 136 BigInteger k = null; 137 ECPoint kp = null; 138 BigInteger r = null; 139 BigInteger s = null; 140 BigInteger userD = null; 141 142 do 143 { 144 do 145 { 146 147 ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.getPrivate(); 148 k = ecpriv.getD(); 149 kp = ecpub.getQ(); 150 151 userD = ecpriv.getD(); 152 153 // r 154 r = e.add(kp.getX().toBigInteger()); 155 r = r.mod(ecc_n); 156 } 157 while (r.equals(BigInteger.ZERO) || r.add(k).equals(ecc_n)); 158 159 // (1 + dA)~-1 160 BigInteger da_1 = userD.add(BigInteger.ONE); 161 da_1 = da_1.modInverse(ecc_n); 162 // s 163 s = r.multiply(userD); 164 s = k.subtract(s).mod(ecc_n); 165 s = da_1.multiply(s).mod(ecc_n); 166 } 167 while (s.equals(BigInteger.ZERO)); 168 169 byte[] btRS = new byte[64]; 170 byte[] btR = r.toByteArray(); 171 byte[] btS = s.toByteArray(); 172 Array.Copy(btR, btR.length - 32, btRS, 0, 32); 173 Array.Copy(btS, btS.length - 32, btRS, 32, 32); 174 175 return new BigInteger[] { r, s }; 176 }*/ 177 178// public static void main(String[] args) throws Exception 179// { 180// String plainText = "ILoveYou11"; 181// //SM3测试 182// //生成密钥对 183// //generateKeyPair(); 184// byte[] sourceData = plainText.getBytes(); 185// 186// //下面的秘钥可以使用generateKeyPair()生成的秘钥内容 187// // 国密规范正式私钥 188// //String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94"; 189// // 国密规范正式公钥 190// //String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A"; 191// 192// String prik = "4cf170068e9c47ebdb521fb9fc62c4a55a5773fb9da33b0acf8129e28d09d205"; 193// String pubk = "04aabda53043e8dcb86d42f690b61a4db869821dadf9f851ec3c5c43d0c8f95a6677fdba984afc3bb010a8436b1d17cefc2011a34e01e9e801124d29ffa928d803"; 194// String publicKey ="04BB34D657EE7E8490E66EF577E6B3CEA28B739511E787FB4F71B7F38F241D87F18A5A93DF74E90FF94F4EB907F271A36B295B851F971DA5418F4915E2C1A23D6E"; 195// String privatekey = "0B1CE43098BC21B8E82B5C065EDB534CB86532B1900A49D49F3C53762D2997FA"; 196// prik=privatekey; 197// pubk=publicKey; 198// System.out.println("加密: "); 199// String cipherText = SM2EncDecUtils.encrypt(ConvertUtil.hexToByte(pubk), sourceData); 200// //cipherText = "0452ba81cf5119c9f29c81c2be9c4a49ad8c0a33ed899b60548d21a62971a8e994cafc0e9fbc710a0a220b055804bb890833b50ac04ec4e130a5db75338c0c1d49a52a6d373076a5db370564a5cebb5300f79877003c52adf49dac16370e51e14e0754110547bb3b"; 201// System.out.println(cipherText); 202// System.out.println("解密: "); 203// plainText = new String(SM2EncDecUtils.decrypt(ConvertUtil.hexToByte(prik), ConvertUtil.hexToByte(cipherText))); 204// System.out.println(plainText); 205// 206// } 207}