001package top.cenze.utils.crypt; 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; 008import top.cenze.utils.crypt.sm.sm2.Cipher; 009import top.cenze.utils.crypt.sm.sm2.SM2; 010 011import java.io.IOException; 012import java.math.BigInteger; 013import java.util.HashMap; 014import java.util.Map; 015 016/** 017 * SM2国密加密解密工具 018 * 019 * @author chengze 020 * @date 2023-11-14 22:35 021 */ 022public class SM2Util { 023 024 //生成随机秘钥对 025 public static Map generateKeyPair() { 026 Map<String, String> keyMap = new HashMap<String, String>(); // 存储公钥和私钥 027 SM2 sm2 = SM2.Instance(); 028 AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair(); 029 ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate(); 030 ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic(); 031 BigInteger privateKey = ecpriv.getD(); 032 ECPoint publicKey = ecpub.getQ(); 033 publicKey.getEncoded(true); 034 keyMap.put("privateKey", ConvertUtil.byteToHex(privateKey.toByteArray())); 035 keyMap.put("publicKey", ConvertUtil.byteToHex(publicKey.getEncoded(true))); 036// System.out.println("公钥: " + ConvertUtil.byteToHex(publicKey.getEncoded())); 037// System.out.println("私钥: " + ConvertUtil.byteToHex(privateKey.toByteArray())); 038 039 return keyMap; 040 } 041 042 //数据加密 043 public static String encrypt(byte[] publicKey, byte[] data) throws IOException 044 { 045 if (publicKey == null || publicKey.length == 0) 046 { 047 return null; 048 } 049 050 if (data == null || data.length == 0) 051 { 052 return null; 053 } 054 055 byte[] source = new byte[data.length]; 056 System.arraycopy(data, 0, source, 0, data.length); 057 058 Cipher cipher = new Cipher(); 059 SM2 sm2 = SM2.Instance(); 060 ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); 061 062 ECPoint c1 = cipher.Init_enc(sm2, userKey); 063 cipher.Encrypt(source); 064 byte[] c3 = new byte[32]; 065 cipher.Dofinal(c3); 066 067// System.out.println("C1 " + Utils.byteToHex(c1.getEncoded())); 068// System.out.println("C2 " + Utils.byteToHex(source)); 069// System.out.println("C3 " + Utils.byteToHex(c3)); 070 //C1 C2 C3拼装成加密字串 071 return ConvertUtil.byteToHex(c1.getEncoded()) + ConvertUtil.byteToHex(source) + ConvertUtil.byteToHex(c3); 072 073 } 074 075 //数据解密 076 public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException 077 { 078 if (privateKey == null || privateKey.length == 0) 079 { 080 return null; 081 } 082 083 if (encryptedData == null || encryptedData.length == 0) 084 { 085 return null; 086 } 087 //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2 088 String data = ConvertUtil.byteToHex(encryptedData); 089 /***分解加密字串 090 * (C1 = C1标志位2位 + C1实体部分128位 = 130) 091 * (C3 = C3实体部分64位 = 64) 092 * (C2 = encryptedData.length * 2 - C1长度 - C2长度) 093 */ 094 byte[] c1Bytes = ConvertUtil.hexToByte(data.substring(0,130)); 095 int c2Len = encryptedData.length - 97; 096 byte[] c2 = ConvertUtil.hexToByte(data.substring(130,130 + 2 * c2Len)); 097 byte[] c3 = ConvertUtil.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len)); 098 099 SM2 sm2 = SM2.Instance(); 100 BigInteger userD = new BigInteger(1, privateKey); 101 102 //通过C1实体字节来生成ECPoint 103 ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes); 104 Cipher cipher = new Cipher(); 105 cipher.Init_dec(userD, c1); 106 cipher.Decrypt(c2); 107 cipher.Dofinal(c3); 108 109 //返回解密结果 110 return c2; 111 } 112 113 114 //数据加密 115 public static String encrypt(String publicKeyStr, String dataStr) throws IOException 116 { 117 byte[] publicKey = ConvertUtil.hexToByte(publicKeyStr); 118 byte[] data = dataStr.getBytes("UTF-8"); 119 120 byte[] source = new byte[data.length]; 121 System.arraycopy(data, 0, source, 0, data.length); 122 123 Cipher cipher = new Cipher(); 124 SM2 sm2 = SM2.Instance(); 125 ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); 126 127 ECPoint c1 = cipher.Init_enc(sm2, userKey); 128 cipher.Encrypt(source); 129 byte[] c3 = new byte[32]; 130 cipher.Dofinal(c3); 131 132 //C1 C2 C3拼装成加密字串 133 return ConvertUtil.byteToHex(c1.getEncoded()) + ConvertUtil.byteToHex(source) + ConvertUtil.byteToHex(c3); 134 135 } 136 137 //数据解密 138 public static byte[] decrypt(String privateKeyStr, String encryptedDataStr) throws IOException 139 { 140 byte[] privateKey = ConvertUtil.hexToByte(privateKeyStr); 141 byte[] encryptedData = ConvertUtil.hexToByte(encryptedDataStr); 142 //加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2 143 String data = ConvertUtil.byteToHex(encryptedData); 144 /***分解加密字串 145 * (C1 = C1标志位2位 + C1实体部分128位 = 130) 146 * (C3 = C3实体部分64位 = 64) 147 * (C2 = encryptedData.length * 2 - C1长度 - C2长度) 148 */ 149 byte[] c1Bytes = ConvertUtil.hexToByte(data.substring(0,130)); 150 int c2Len = encryptedData.length - 97; 151 byte[] c2 = ConvertUtil.hexToByte(data.substring(130,130 + 2 * c2Len)); 152 byte[] c3 = ConvertUtil.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len)); 153 154 SM2 sm2 = SM2.Instance(); 155 BigInteger userD = new BigInteger(1, privateKey); 156 157 //通过C1实体字节来生成ECPoint 158 ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes); 159 Cipher cipher = new Cipher(); 160 cipher.Init_dec(userD, c1); 161 cipher.Decrypt(c2); 162 cipher.Dofinal(c3); 163 164 //返回解密结果 165 return c2; 166 } 167 168// public static void main(String[] args){ 169// generateKeyPair(); 170// String publicKey = "04CF0565941EAE46B935057343EC7CD51F6BB4DCEC10238667625ECE3BD516F2323C781B0A5B97C123748353ACA81221C974C662A2C1C320F7532DDD2D3ECC106F"; 171// String privateKey = "00AA40384C9AB7CC44E8B2481737F98C88A8C8474497DA0CFE58B625BB3E79F97B"; 172// String ss = "oahgiooahgiouaoi弄我阿济格hi噢阿济格hi噢hi"; 173// 174// try { 175// String dataEn = encrypt(publicKey, ss); 176// System.out.println(dataEn); 177// 178// String dataDe = new String(decrypt(privateKey,dataEn)); 179// System.out.println(dataDe); 180// }catch (Exception e){ 181// e.printStackTrace(); 182// } 183// } 184}