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}