package TCPNet; import Security.BC_KeyManager; import TCPNet.request.BaseRequest; import TCPNet.response.BaseResponse; import Utils.Base64Helper; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.JSONToken; import org.bouncycastle.crypto.InvalidCipherTextException; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.ArrayList; import java.util.Random; /* * @Author: Wang Feng * @Description: * @Version: 1.0.0 * @Date: 20:50 2021/6/24 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ class SSL_SetupMessage extends BaseRequest { public String Pubkey; public String Secretkey; } class SSL_Message_Helper{ // 为了直接将SSL_Message的json格式解析为java对象, // 而定义本类 public int IsEncrypted; public int MType; public String Data; public String Pubkey = ""; public int Code = 0; } class SSL_Message extends BaseRequest{ public int IsEncrypted; public int MType; public byte[] Data; public String Pubkey=""; public int Code=0; @Override public void unJson(byte[] data,Object thisObj) { SSL_Message_Helper newObj= JSONObject.parseObject(new String(data), SSL_Message_Helper.class); try { Class thiscls = SSL_Message.class; Class cls = SSL_Message_Helper.class; Field[] fields = cls.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; f.setAccessible(true); // 将属性值的名字的属性值的值放入this中 Field thisf = thiscls.getDeclaredField(f.getName()); thisf.setAccessible(true); if(thisf.getType()==(byte[].class)){ // byte[]需要解码base64 String base64S=(String)(f.get(newObj)); byte[] decodeBytes= Base64Helper.BlockChain_Base64Decode_GoLanUn(base64S); thisf.set(this, decodeBytes); }else { thisf.set(this, f.get(newObj)); } } } catch (IllegalAccessException | NoSuchFieldException e) { e.printStackTrace(); } } } class SSL_RespMessage extends BaseResponse { public int Code; } public class SSL { // 是否加密 public static final int encrypted=0; public static final int not_encrypted=1; // SSL_Message类型 public static final int normal=0; public static final int setup=1; public static final int resp=2; // SSL_RespMessage类型 public static final int success=200; public static final int bad_request=400; public static final int not_authorized=403; public static final int server_error=500; /** * 协商对称密钥 * @param conn * @param pubKey 用户公钥 * @param key 无用参数,内含pubKey * @param serverKey 服务器公钥 * @return 协商成功的对称密钥 */ public static String sslSetup(Conn conn, String pubKey, BC_KeyManager key,BC_KeyManager serverKey){ // 取一个十六位的密钥 String secretKey=String.format("%016d", Math.abs(new Random(System.currentTimeMillis()).nextLong())) .substring(0,16); // 构造SSL_SetupMessage(公钥&密钥) SSL_SetupMessage sm=new SSL_SetupMessage(); sm.Pubkey=pubKey; sm.Secretkey=secretKey; String data; try { data=sm.toJson(); } catch (IllegalAccessException e) { e.printStackTrace(); return null; } // 用公钥去加密它 byte[] encData; try { encData=serverKey.Encrypt(data); } catch (InvalidCipherTextException e) { e.printStackTrace(); return null; } // 构造SSL_Message SSL_Message sslMessage=new SSL_Message(); sslMessage.IsEncrypted=encrypted; sslMessage.MType=setup; sslMessage.Data =encData; String ms=null; try { ms=sslMessage.toJson(); } catch (IllegalAccessException e) { e.printStackTrace(); return null; } System.out.println("test 000: mesdata: "+new String(ms.getBytes(StandardCharsets.UTF_8))); // 将SSL_Message写给服务器(内含:用户公钥、用户对称密钥) if(!conn.writeV2(ms.getBytes(StandardCharsets.UTF_8))){ System.out.println("SSL write error"); return null; } System.out.println("test 111"); // 读取服务器应答信息 byte[] resData=conn.readSSL(); if(resData==null){ System.out.println("SSL readSSL error"); return null; } System.out.println("test 222: "+new String(resData)); System.out.println("secretkey: "+secretKey); // 用对称密钥解密应答信息 byte[] decRes; try { // todo:这里sm4有问题 // decRes="{\"Code\":200}".getBytes(StandardCharsets.UTF_8); decRes=BC_KeyManager.SM4Decrypt(secretKey,resData); } catch (IllegalBlockSizeException | InvalidKeyException | NoSuchProviderException | NoSuchAlgorithmException | BadPaddingException | NoSuchPaddingException e) { e.printStackTrace(); return null; } // 将解密信息转为Java对象 SSL_RespMessage resp=new SSL_RespMessage(); resp.unJson(decRes,resp); // 判断应答信息的code if(resp.Code!=success){ System.out.println("SSL setup failed, the server doesn't accept the request, " + "and the status code is "+resp.Code); return null; } return secretKey; } /** * 使用密钥解密数据 * @param data * @param role * @param secretKey * @return 泛型数组,依次存储:string(对称密钥) int(是否加密) int(code) byte[](解密数据) */ public static ArrayList sslDePacket(byte[] data, int role, String secretKey){ ArrayList result=new ArrayList(); result.add(""); result.add(not_encrypted); result.add(400); result.add(null); // json转java对象 SSL_Message res=new SSL_Message(); res.unJson(data,res); // 没有加密直接返回 200 和源数据res.Data if(res.IsEncrypted==not_encrypted){ return result; }else if(res.IsEncrypted==encrypted) { // 加密 判断role if(role==0){ // todo:根据解析出来的数据中的公钥ID从本地MAP获取公钥 对数据SM4解密 // todo: 这里是server应该事先的处理逻辑 System.out.println("sslDePacket error: role==0"); return result; }else{ // 直接使用传入的密钥 对数据SM4解密 if(secretKey.equals("")){ System.out.println("sslDePacket error: secretKey == \"\""); return result; } byte[] ans; try { ans= BC_KeyManager.SM4Decrypt(secretKey,res.Data); } catch (IllegalBlockSizeException | NoSuchProviderException | InvalidKeyException | NoSuchAlgorithmException | BadPaddingException | NoSuchPaddingException e) { e.printStackTrace(); return result; } if(ans==null){ System.out.println("SSL depacket failed, the secretKey can't use to decrypt the data"); return result; } result.set(1,encrypted); result.set(2,200); result.set(3,ans); return result; } }else{ return result; } } }