diff --git a/min/pid/pib.db b/min/pid/pib.db index 0fcfbf1..75bc44a 100644 Binary files a/min/pid/pib.db and b/min/pid/pib.db differ diff --git a/src/main/java/cn/minbrowser/util/Base64EncodeUtil.java b/src/main/java/cn/minbrowser/util/Base64EncodeUtil.java new file mode 100644 index 0000000..986beb2 --- /dev/null +++ b/src/main/java/cn/minbrowser/util/Base64EncodeUtil.java @@ -0,0 +1,17 @@ +package cn.minbrowser.util; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +/* + * @author wefree + */ +public class Base64EncodeUtil { + public static String Base64PlusEncode(String srcStr){ + String dstStr = "" ; + dstStr = Base64.getMimeEncoder().encodeToString(srcStr.getBytes(StandardCharsets.UTF_8)); + dstStr = dstStr.replaceAll("=","-").replaceAll("/","_") ; + return dstStr; + } +} diff --git a/src/main/java/cn/minbrowser/util/Encryption/EncryptionUtil.java b/src/main/java/cn/minbrowser/util/Encryption/EncryptionUtil.java new file mode 100644 index 0000000..ad98f4c --- /dev/null +++ b/src/main/java/cn/minbrowser/util/Encryption/EncryptionUtil.java @@ -0,0 +1,218 @@ +package cn.minbrowser.util.Encryption; + +import org.apache.commons.codec.digest.DigestUtils; + +import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +public class EncryptionUtil { + // 获取文件md5加密结果 + public static String getFileHash(String path){ + Long startTime = System.currentTimeMillis(); + // File +// String path="E:\\系统镜像\\ubuntu-18.04.3-desktop-amd64.iso"; +// String path="E:\\系统镜像\\UltraISO.9.7.0.3476.exe"; + String res=null; + try { + res= DigestUtils.md5Hex(new FileInputStream(path)); + System.out.println("文件"+path+"加密结果:"+res); + } catch (IOException e) { + e.printStackTrace(); + } + Long endTime=System.currentTimeMillis(); + System.out.println("文件"+path+"加密耗时:"+(endTime-startTime)+"ms"); + return res; + } + + public static String getMD5String(String str) { + try { + str= URLEncoder.encode(str, String.valueOf(StandardCharsets.UTF_8)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + try { + // 生成一个MD5加密计算摘要 + MessageDigest md = MessageDigest.getInstance("MD5"); + // 计算md5函数 + md.update(str.getBytes(StandardCharsets.UTF_8)); + // digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 + // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 + //一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方) + String res = new BigInteger(1, md.digest()).toString(16); +// System.out.println(str + " MD5加密结果: " + res); + return res; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + public static String encryptBasedAES(String content) { +// content= URLEncoder.encode(content, StandardCharsets.UTF_8); + byte[] encrypt=encryptBasedAES(content,"123"); + return ParseSystemUtil.parseByte2HexStr(encrypt); + } + +// public static byte[] encryptBasedAES(String content) { +// return encryptBasedAES(content, "123"); +// } + + /** + * AES加密字符串 + * + * @param content 需要被加密的字符串 + * @param password 加密需要的密码 + * @return 密文 + */ + public static byte[] encryptBasedAES(String content, String password) { +// content= URLEncoder.encode(content, StandardCharsets.UTF_8); +// password= URLEncoder.encode(password, StandardCharsets.UTF_8); + try { + KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者 +// kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出 + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + secureRandom.setSeed(password.getBytes(StandardCharsets.UTF_8)); + kgen.init(128, secureRandom); + //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行 + SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥 + byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回 + SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥 + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + byte[] byteContent = content.getBytes(StandardCharsets.UTF_8); + cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器 + byte[] result = cipher.doFinal(byteContent);// 加密 + return result; + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return null; + } + + public static String decryptBasedAES(String hexStr) { +// hexStr= URLEncoder.encode(hexStr, StandardCharsets.UTF_8); + byte[] byte2 = ParseSystemUtil.parseHexStr2Byte(hexStr); + String s=new String(decryptBasedAES(byte2, "123"),StandardCharsets.UTF_8); +// s=URLEncoder.encode(s,StandardCharsets.UTF_8); + return s; + } + +// public static byte[] decryptBasedAES(byte[] content) { +// return decryptBasedAES(content, "123"); +// } + + /** + * 解密AES加密过的字符串 + * + * @param content AES加密过过的内容 + * @param password 加密时的密码 + * @return 明文 + */ + public static byte[] decryptBasedAES(byte[] content, String password){ +// password=URLEncoder.encode(password,StandardCharsets.UTF_8); + try { + KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者 +// kgen.init(128, new SecureRandom(password.getBytes())); + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + secureRandom.setSeed(password.getBytes(StandardCharsets.UTF_8)); + kgen.init(128, secureRandom); + SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥 + byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥 + SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥 + Cipher cipher = Cipher.getInstance("AES");// 创建密码器 + cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器 + byte[] result = cipher.doFinal(content); + return result; // 明文 + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return null; + } + + // 测试主函数 +// public static void main(String[] args) throws Exception { +// String content = "哈哈哈"; +// System.out.println("需要加密的内容:" + content); +// String enc=encryptBasedAES(content); +// System.out.println("加密后的16进制密文:" + enc); +// String dec=decryptBasedAES(enc); +// System.out.println("解密后的内容:" + dec); +// } + + public static String WghAESEncrypt(String sSrc, String sKey) throws Exception { + if (sKey == null) { + System.out.print("Key为空null"); + return null; + } + // 判断Key是否为16位 + if (sKey.length() != 16) { + System.out.print("Key长度不是16位"); + return null; + } + byte[] raw = sKey.getBytes("utf-8"); + SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式" + cipher.init(Cipher.ENCRYPT_MODE, skeySpec); + byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); + + Base64.Encoder encoder= Base64.getMimeEncoder(); + + return encoder.encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。 + } + // 解密 + public static String WghAESDecrypt(String sSrc, String sKey) throws Exception { + try { + // 判断Key是否正确 + if (sKey == null) { + System.out.print("Key为空null"); + return " "; + } + // 判断Key是否为16位 + if (sKey.length() != 16) { + System.out.print("Key长度不是16位"); + return " "; + } + byte[] raw = sKey.getBytes("utf-8"); + SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, skeySpec); + Base64.Decoder decoder = Base64.getMimeDecoder() ; + + byte[] encrypted1 = decoder.decode(sSrc); + + byte[] original = cipher.doFinal(encrypted1); + String originalString = new String(original, "utf-8"); + return originalString; + } catch (Exception ex) { + System.out.println(ex.toString()); + return " "; + } + } + +} diff --git a/src/main/java/cn/minbrowser/util/Encryption/ParseSystemUtil.java b/src/main/java/cn/minbrowser/util/Encryption/ParseSystemUtil.java new file mode 100644 index 0000000..fa0e608 --- /dev/null +++ b/src/main/java/cn/minbrowser/util/Encryption/ParseSystemUtil.java @@ -0,0 +1,39 @@ +package cn.minbrowser.util.Encryption; + +/** + * 进制转换工具类 + */ +public class ParseSystemUtil { + + /**将二进制转换成16进制 + * @param buf + * @return + */ + public static String parseByte2HexStr(byte buf[]) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < buf.length; i++) { + String hex = Integer.toHexString(buf[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + sb.append(hex.toUpperCase()); + } + return sb.toString(); + } + + /**将16进制转换为二进制 + * @param hexStr + * @return + */ + public static byte[] parseHexStr2Byte(String hexStr) { + if (hexStr.length() < 1) + return null; + byte[] result = new byte[hexStr.length()/2]; + for (int i = 0;i< hexStr.length()/2; i++) { + int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16); + int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16); + result[i] = (byte) (high * 16 + low); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/cn/minbrowser/util/MISUtil/MisUtil.java b/src/main/java/cn/minbrowser/util/MISUtil/MisUtil.java new file mode 100644 index 0000000..7f81298 --- /dev/null +++ b/src/main/java/cn/minbrowser/util/MISUtil/MisUtil.java @@ -0,0 +1,235 @@ +package cn.minbrowser.util.MISUtil; + +import cn.minoa.MainApp; +import javafx.scene.control.Alert; +import net.named_data.jndn.Face; +import net.named_data.jndn.Interest; +import net.named_data.jndn.Name; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.util.Blob; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; + +public class MisUtil { + + private static String gatewayPrefix = null ; + private MainApp mainApp; + public MisUtil(MainApp mainApp_) { + this.mainApp = mainApp_; + } + public static String getGateWayPrefix(String ip, String misIP, int misPort ){ +// Face face = new Face(MainApp.NDNBlockChainIPAddress, MainApp.NDNBlockChainPortAddress); + Face face = new Face(misIP, misPort); + Interest interest = new Interest(); + interest.setName(new Name("/mis/resolve/" + System.currentTimeMillis() )); + interest.setInterestLifetimeMilliseconds(3000); // 设置生存时间为3秒 + interest.setMustBeFresh(true); // 必须是最新鲜的数据 + interest.setApplicationParameters(new Blob(getQueryStr(ip).getBytes())); + System.out.println("the get query string "+getQueryStr(ip)); + gatewayPrefix = null ; + try { + // 将兴趣包发往出去 + face.expressInterest(interest, (interest1, data) -> { + // 处理返回数据 + //long ret = data.getContent();//返回数据 + System.out.println("data getcontent"+data.getContent().toString()); + String resString= data.getContent().toString() ;//new String(data.getContent().buf().array(),StandardCharsets.UTF_8); + JSONObject resObject= null; + try { + resObject = new JSONObject(resString); + System.out.println("the return infomation"+ resObject); + // System.exit(1); + } catch (JSONException e) { + e.printStackTrace(); + } + int resCode = 0; + try { + resCode = resObject.getInt("StatusCode"); + System.out.println("the return rescode"+ resCode); + } catch (JSONException e) { + e.printStackTrace(); + } + + try { + gatewayPrefix = resObject.getString("Message"); + System.out.println("the return message"+ gatewayPrefix); + } catch (JSONException e) { + e.printStackTrace(); + } + + + }, (interest12) -> { + // 超时处理函数 + gatewayPrefix = "" ; + }, (interest13, networkNack) -> { + // 处理无路由情况 + gatewayPrefix = "" ; + }); + for (int i = 0; i < 1000 && gatewayPrefix == null ; i++) { + face.processEvents(); + Thread.sleep(5); + } + } catch (IOException | EncodingException | InterruptedException e) { + e.printStackTrace(); + System.out.println("连接不可达:" +misIP + ":" +misPort ); + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle("启动失败"); + alert.setHeaderText("标识解析失败"); + alert.setContentText("连接不可达:" +misIP + ":" +misPort ); + alert.showAndWait(); + return ""; + } + if(gatewayPrefix == ""){ + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle("启动失败"); + alert.setHeaderText("标识解析失败"); + alert.setContentText("无法从区块链解析到IP("+ip+")对应的服务器标识"); + alert.showAndWait(); + } + return gatewayPrefix ; + } + + public static Boolean isConnected(String ip, int misPort ){ + System.out.println("服务器TCP连接测试"); + SocketChannel sc; + try { + sc = SocketChannel.open(); + sc.socket().connect(new InetSocketAddress(ip,misPort),3000); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + +// // Face face = new Face(MainApp.NDNBlockChainIPAddress, MainApp.NDNBlockChainPortAddress); +// Face face = new Face(misIP, misPort); +// Interest interest = new Interest(); +// interest.setName(new Name("/mis/resolve/" + System.currentTimeMillis() )); +// interest.setInterestLifetimeMilliseconds(3000); // 设置生存时间为3秒 +// interest.setMustBeFresh(true); // 必须是最新鲜的数据 +// interest.setApplicationParameters(new Blob(getQueryStr(ip).getBytes())); +// System.out.println("the get query string "+getQueryStr(ip)); +// gatewayPrefix = null ; +// try { +// // 将兴趣包发往出去 +// face.expressInterest(interest, (interest1, data) -> { +// // 处理返回数据 +// //long ret = data.getContent();//返回数据 +// System.out.println("data getcontent"+data.getContent().toString()); +// String resString= data.getContent().toString() ;//new String(data.getContent().buf().array(),StandardCharsets.UTF_8); +// JSONObject resObject= null; +// try { +// resObject = new JSONObject(resString); +// System.out.println("the return infomation"+ resObject); +// // System.exit(1); +// } catch (JSONException e) { +// e.printStackTrace(); +// } +// int resCode = 0; +// try { +// resCode = resObject.getInt("StatusCode"); +// System.out.println("the return rescode"+ resCode); +// } catch (JSONException e) { +// e.printStackTrace(); +// } +// +// try { +// gatewayPrefix = resObject.getString("Message"); +// System.out.println("the return message"+ gatewayPrefix); +// } catch (JSONException e) { +// e.printStackTrace(); +// } +// +// +// }, (interest12) -> { +// // 超时处理函数 +// gatewayPrefix = "" ; +// }, (interest13, networkNack) -> { +// // 处理无路由情况 +// gatewayPrefix = "" ; +// }); +// for (int i = 0; i < 1000 && gatewayPrefix == null ; i++) { +// face.processEvents(); +// Thread.sleep(5); +// } +// } catch (IOException | EncodingException | InterruptedException e) { +// e.printStackTrace(); +// System.out.println("连接不可达:" +misIP + ":" +misPort ); +// } +// return gatewayPrefix ; + } + + public void checkConnectStatus(){ + new Thread(new Runnable() { + @Override + public void run() { + // System.out.println("checkConnectStatus 1"); + String prefix = ""; + while(mainApp.loginerController == null){ + try { + Thread.sleep(1000); + // System.out.println("checkConnectStatus 2"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + while (!mainApp.isNeedKnowLoginStatus) { + // System.out.println("checkConnectStatus 3"); + String ip = MainApp.NDNBlockChainIPAddress; + Integer port = MainApp.NDNBlockChainPortAddress; + Boolean isConnected = isConnected(ip, port); + + if (!ip.equals(MainApp.NDNBlockChainIPAddress) || !port.equals(MainApp.NDNBlockChainPortAddress)) + continue; + + // 连接失败 + if (!isConnected) { + mainApp.loginerController.setTextVisible(); + // mainApp.loginerController.setButtonDisable(); + } + // 连接成功 + else { + mainApp.loginerController.setTextInvisible(); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // mainApp.loginerController.setButtonEnable(); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + },"checkConnectStatus").start(); + } + + private static String getQueryStr(String mirip){ + JSONObject jsonObject = new JSONObject(); + String commandString = "Resolve"; + String type = "user-act"; + int QueryCode = 2; + String U_identifier ="/vpn-dns/"+mirip; + + try { + jsonObject.put("Type", type); + jsonObject.put("Command", commandString); + jsonObject.put("QueryCode", QueryCode); + jsonObject.put("U_identifier", U_identifier); + + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + return jsonObject.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/cn/minbrowser/util/MISUtil/NDNBlockChainConnectClient.java b/src/main/java/cn/minbrowser/util/MISUtil/NDNBlockChainConnectClient.java new file mode 100644 index 0000000..9b823ed --- /dev/null +++ b/src/main/java/cn/minbrowser/util/MISUtil/NDNBlockChainConnectClient.java @@ -0,0 +1,725 @@ +package cn.minbrowser.util.MISUtil; +// 与区块链建立TCP连接,发送注册请求 + +import cn.minbrowser.MiniMinData.KeyManager; +import javafx.scene.control.Alert; +import net.named_data.jndn.Face; +import net.named_data.jndn.Interest; +import net.named_data.jndn.Name; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.security.KeyChain; +import net.named_data.jndn.security.SigningInfo; +import net.named_data.jndn.security.pib.PibImpl; +import net.named_data.jndn.security.tpm.TpmBackEnd; +import net.named_data.jndn.security.v2.CertificateV2; +import net.named_data.jndn.util.Blob; +import net.named_data.jndn.util.Common; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.*; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +/** + * 与MIS进行数据交互的Client + */ +public class NDNBlockChainConnectClient { + + private String NDNBlockChainIPAddress; + private Integer NDNBlockChainPortAddress; + private String massage=null; + private String loginmessage=null; + private Boolean vcFlag = false; + private int seq=1; + + public void setMassage(String massage) { + massage = massage; + } + + public void setLoginmessage(String loginmessage) { + loginmessage = loginmessage; + } + + public NDNBlockChainConnectClient(String ipAddress, Integer portAddress) { + this.NDNBlockChainIPAddress = ipAddress; + this.NDNBlockChainPortAddress = portAddress; + } + + // 将已在区块链后台注册成功的用户注销掉 + public String deleteUser(String username, String sig) { + String prefix = "/" + username; + // 获取注册数组 + byte[] registerByte = getBlockChainDeleteBuffer(prefix, sig); + System.out.println("delete length: " + registerByte.length); + // 通过TCP连接区块链后台 + Socket blockchainClient; + try { + blockchainClient = new Socket(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("连接不可达:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + return e.getMessage(); + } + System.out.println("已成功建立TCP连接:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress + + "; 远程主机地址:" + blockchainClient.getRemoteSocketAddress()); + try { + OutputStream outToServer = blockchainClient.getOutputStream(); + DataOutputStream out = new DataOutputStream(outToServer); + + out.write(registerByte); + InputStream inFromServer = blockchainClient.getInputStream(); + DataInputStream in = new DataInputStream(inFromServer); + System.out.println("正在等待服务器响应..."); + byte[] res = new byte[4]; + in.read(res); + int resSize = Bytes2Int_LE(res); + System.out.println("返回值长度为:" + resSize); + res = new byte[resSize]; + in.read(res); + System.out.println("返回值内容为:" + new String(res, StandardCharsets.UTF_8)); + System.out.println("服务器响应: "); + blockchainClient.close(); + System.out.println("已关闭此次TCP连接:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); +// System.out.println("服务器响应: " ); + // 解析返回来的数据,如果是200,就返回true + try { + String resString = new String(res, StandardCharsets.UTF_8); + System.out.println("resString: " + resString); + JSONObject resObject = new JSONObject(resString); + int resCode = resObject.getInt("StatusCode"); + String message = resObject.getString("Message"); + if (resCode == 200) { + System.out.println("区块链销户成功:" + username); + return "true"; + } else { + return message; + } + } catch (JSONException e) { + e.printStackTrace(); + return e.getMessage(); + } + } catch (IOException e) { + e.printStackTrace(); + System.out.println("销户时数据交换出错:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + return e.getMessage(); + } + } + + // 添加白名单 + public String addWhiteUser(String phone) { + // 获取注册数组 + byte[] registerByte = getBlockChainWhiteBuffer(phone); + System.out.println("whiteuser length: " + registerByte.length); + // 通过TCP连接区块链后台 + Socket blockchainClient; + try { + blockchainClient = new Socket(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("连接不可达:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + return e.getMessage(); + } + System.out.println("已成功建立TCP连接:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress + + "; 远程主机地址:" + blockchainClient.getRemoteSocketAddress()); + try { + OutputStream outToServer = blockchainClient.getOutputStream(); + DataOutputStream out = new DataOutputStream(outToServer); + + out.write(registerByte); + InputStream inFromServer = blockchainClient.getInputStream(); + DataInputStream in = new DataInputStream(inFromServer); + System.out.println("正在等待服务器响应..."); + byte[] res = new byte[4]; + in.read(res); + int resSize = Bytes2Int_LE(res); + System.out.println("返回值长度为:" + resSize); + res = new byte[resSize]; + in.read(res); + System.out.println("返回值内容为:" + new String(res)); + blockchainClient.close(); + System.out.println("已关闭此次TCP连接:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); +// System.out.println("服务器响应: " ); + // 解析返回来的数据,如果是200,就返回true + try { + String resString = new String(res); + System.out.println("resString: " + resString); + JSONObject resObject = new JSONObject(resString); + int resCode = resObject.getInt("StatusCode"); + String message = resObject.getString("Message"); + if (resCode == 200) { + System.out.println("区块链添加白名单成功:" + phone); + return "true"; + } else { + return message; + } + } catch (JSONException e) { + e.printStackTrace(); + return e.getMessage(); + } + } catch (IOException e) { + e.printStackTrace(); + System.out.println("添加白名单时数据交换出错:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + return e.getMessage(); + } +// return true; + } + + /* // 注册用户 + public String registeNewUser(String username,String phone,String pubkey){ + // 获取注册数组 + byte[] registerByte=getBlockChainRegisterBuffer(username,phone, pubkey); + System.out.println("register length: "+registerByte.length); + // 通过TCP连接区块链后台 + Socket blockchainClient; + try { + blockchainClient=new Socket(NDNBlockChainIPAddress,NDNBlockChainPortAddress); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("连接不可达:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress); + return e.getMessage(); + } + System.out.println("已成功建立TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress + +"; 远程主机地址:"+blockchainClient.getRemoteSocketAddress()); + try { + OutputStream outToServer = blockchainClient.getOutputStream(); + DataOutputStream out = new DataOutputStream(outToServer); + + out.write(registerByte); + InputStream inFromServer = blockchainClient.getInputStream(); + DataInputStream in = new DataInputStream(inFromServer); + System.out.println("正在等待服务器响应..."); + byte[] res = new byte[4]; + in.read(res); + int resSize = Bytes2Int_LE(res); + System.out.println("返回值长度为:"+ resSize); + res = new byte[resSize]; + in.read(res); + System.out.println("返回值内容为:" + new String(res, StandardCharsets.UTF_8)); + System.out.println("服务器响应: " ); + blockchainClient.close(); + System.out.println("已关闭此次TCP连接:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress); +// System.out.println("服务器响应: " ); + // 解析返回来的数据,如果是200,就返回true + try { + String resString=new String(res,StandardCharsets.UTF_8); + System.out.println("resString: "+resString); + JSONObject resObject=new JSONObject(resString); + int resCode=resObject.getInt("StatusCode"); + String message=resObject.getString("Message"); + if(resCode==200){ + System.out.println("区块链注册用户成功:"+username); + return "true"; + }else{ + return message; + } + } catch (JSONException e) { + e.printStackTrace(); + return e.getMessage(); + } + } catch (IOException e) { + e.printStackTrace(); + System.out.println("注册时数据交换出错:"+NDNBlockChainIPAddress+":"+NDNBlockChainPortAddress); + return e.getMessage(); + } + }*/ + + // 注册用户 + // public String registeNewUser(String username, String phone, String pubkey) { + public String registeNewUser(String registerJsonstring) { + // 获取注册数组 +// byte[] registerByte = getBlockChainRegisterBuffer(username, phone, pubkey); +// System.out.println("register length: " + registerByte.length); +// String informationString=new String(registerByte,StandardCharsets.UTF_8); +// System.out.println("resString: "+informationString); + + // 检查连接状态 + Boolean isConnected = MisUtil.isConnected(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + if(!isConnected){ + NotificationUtil.alert(Alert.AlertType.ERROR, + "连接失败", + "服务连接失败", + "无法连接到服务器,请确认服务器IP地址"); + return ""; + } + Face face = new Face(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + Interest interest = new Interest(); + Name name = new Name("/mis/register"); + name.appendSequenceNumber(seq++); + interest.setName(name); + + interest.setInterestLifetimeMilliseconds(3000); // 设置生存时间为3秒 + interest.setMustBeFresh(true); // 必须是最新鲜的数据 + + interest.setApplicationParameters(new Blob(registerJsonstring.getBytes())); + + try { + // 将兴趣包发往出去 + + face.expressInterest(interest, (interest1, data) -> { + // 处理返回数据 + //long ret = data.getContent();//返回数据 + System.out.println(data.getContent().toString()); + try { + //System.out.println(data.getContent().buf().array()); + String resString= data.getContent().toString() ;//new String(data.getContent().buf().array(),StandardCharsets.UTF_8); + + JSONObject resObject=new JSONObject(resString); + + System.out.println("the return infomation"+ resObject); + // System.exit(1); + + //int resCode = resObject.getInt("StatusCode"); + int resCode = resObject.getInt("StatusCode"); + System.out.println("the return rescode"+ resCode); + massage = resObject.getString("Message"); + System.out.println("the return message"+ massage); + if (resCode == 200) { + // System.out.println("区块链用户注册成功:" + username); + massage = "注册成功"; + } else { + System.out.println("resCode!=200:" + resCode); + //flag=false; + // return message; + } + + } catch (JSONException e) { + e.printStackTrace(); + massage = e.getMessage(); + + } + + }, (interest12) -> { + // 超时处理函数 + massage =""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链注册失败"); + alert.setHeaderText("区块链注册失败"); + alert.setContentText("区块链处理超时\n"); + alert.showAndWait(); + }, (interest13, networkNack) -> { + // 处理无路由情况 + massage =""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链注册失败"); + alert.setHeaderText("区块链注册失败"); + alert.setContentText("区块链无路由\n"); + alert.showAndWait(); + }); + for (int i = 0; i < 1000&&massage==null; i++) { + face.processEvents(); + Thread.sleep(5); + } + // if(flag=="") + // return "true"; + } catch (IOException | EncodingException | InterruptedException e) { + e.printStackTrace(); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链注册失败"); + alert.setHeaderText("区块链注册失败"); + alert.setContentText("连接不可达\n"); + alert.showAndWait(); + System.out.println("连接不可达:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + massage = e.getMessage(); + } + return massage; + } + + public Boolean getVerificitionCode(String phoneNumber) { + // string -> json object -> json string + JSONObject jso = new JSONObject(); + try { + jso.put("phoneNumber", phoneNumber); + } catch (JSONException e) { + e.printStackTrace(); + } + String phoneNumberJsonString = jso.toString(); + // ndn interest package + Face face = new Face(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + Interest interest = new Interest(); + Name name = new Name("/mis/verificationCode"); + name.appendSequenceNumber(seq++); + interest.setName(name); + interest.setInterestLifetimeMilliseconds(3000); // 设置生存时间为3秒 + interest.setMustBeFresh(true); // 必须是最新鲜的数据 + interest.setApplicationParameters(new Blob(phoneNumberJsonString.getBytes())); + + // send interest + try { + face.expressInterest(interest, (interest1, data) -> { + // 处理返回数据 + System.out.println(data.getContent().toString()); + try { + String resString = data.getContent().toString(); + JSONObject resObject = new JSONObject(resString); + System.out.println("the return infomation" + resObject); + int resCode = resObject.getInt("StatusCode"); + System.out.println("the return rescode" + resCode); + System.out.println("the return message" + massage); + if (resCode == 200) { + vcFlag = true; + } else { + vcFlag = false; + System.out.println("resCode!=200:" + resCode); + } + + } catch (JSONException e) { + e.printStackTrace(); + } + + }, (interest12) -> { + // 超时处理函数 + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("获取验证码失败"); + alert.setHeaderText("获取验证码失败"); + alert.setContentText("区块链处理超时\n"); + alert.showAndWait(); + }, (interest13, networkNack) -> { + // 处理无路由情况 + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("获取验证码失败"); + alert.setHeaderText("获取验证码失败"); + alert.setContentText("区块链无路由\n"); + alert.showAndWait(); + }); + for (int i = 0; i < 1000 && vcFlag == false; i++) { + face.processEvents(); + Thread.sleep(5); + } + } catch (IOException | EncodingException | InterruptedException e) { + e.printStackTrace(); + } + return vcFlag; + } + // 用户登录 + public String loginNewUser(String loginJsonString) { + + // 检查连接状态 + Boolean isConnected = MisUtil.isConnected(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + if(!isConnected){ + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("连接失败"); + alert.setHeaderText("服务器连接失败"); + alert.setContentText("无法连接到服务器,请确认服务器IP地址"); + alert.showAndWait(); + return ""; + } + + + System.out.println("the login Json in ndn"+loginJsonString); + Face face = new Face(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + Interest interest = new Interest(); + interest.setName(new Name("/mis/login")); + interest.setInterestLifetimeMilliseconds(1000); // 设置生存时间为3秒 + interest.setMustBeFresh(true); // 必须是最新鲜的数据 + interest.setApplicationParameters(new Blob(loginJsonString.getBytes())); + + // new Thread(new Runnable() { + // @Override + // public void run() { + // try { + // Thread.sleep(3000); + // System.out.println("do shutdown function"); + // face.shutdown(); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } + // } + // }).start(); + + + try { + // 将兴趣包发往出去 + face.expressInterest(interest, (interest1, data) -> { + // 处理返回数据 + //long ret = data.getContent();//返回数据 + System.out.println(data.getContent().toString()); + String resString = data.getContent().toString() ;//new String(data.getContent().buf().array(),StandardCharsets.UTF_8); + loginmessage = resString; + System.out.println("the return LOGIN RESTRING"+ loginmessage); + + }, (interest12) -> { + // 超时处理函数 + loginmessage=""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("区块链登录超时\n"); + alert.showAndWait(); + }, (interest13, networkNack) -> { + // 处理无路由情况 + loginmessage=""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("区块链无路由\n"); + alert.showAndWait(); + }); + for (int i = 0; i < 1000&&loginmessage==null; i++) { + face.processEvents(); + Thread.sleep(5); + } + // if(flag=="") + // return "true"; + } catch (IOException | EncodingException | InterruptedException e) { + e.printStackTrace(); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("连接不可达\n"); + alert.showAndWait(); + System.out.println("连接不可达:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + loginmessage = e.getMessage(); + } + return loginmessage; + } + + public String loginAuthentication(String loginJsonString){ + Face face = new Face(NDNBlockChainIPAddress, NDNBlockChainPortAddress); + Interest interest = new Interest(); + interest.setName(new Name("/mis/authentication")); + interest.setInterestLifetimeMilliseconds(3000); // 设置生存时间为3秒 + interest.setMustBeFresh(true); // 必须是最新鲜的数据 + interest.setApplicationParameters(new Blob(loginJsonString.getBytes())); + try { + // 将兴趣包发往出去 + + face.expressInterest(interest, (interest1, data) -> { + // 处理返回数据 + //long ret = data.getContent();//返回数据 + System.out.println(data.getContent().toString()); + String resString= data.getContent().toString() ;//new String(data.getContent().buf().array(),StandardCharsets.UTF_8); + loginmessage = resString; + System.out.println("the return LOGIN RESTRING"+ loginmessage); + + }, (interest12) -> { + // 超时处理函数 + loginmessage=""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("区块链登录超时\n"); + alert.showAndWait(); + }, (interest13, networkNack) -> { + // 处理无路由情况 + loginmessage=""; + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("区块链无路由\n"); + alert.showAndWait(); + }); + for (int i = 0; i < 1000&&loginmessage==null; i++) { + face.processEvents(); + Thread.sleep(5); + } + // if(flag=="") + // return "true"; + } catch (IOException | EncodingException | InterruptedException e) { + e.printStackTrace(); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("区块链登录失败"); + alert.setHeaderText("区块链登录失败"); + alert.setContentText("连接不可达\n"); + alert.showAndWait(); + System.out.println("连接不可达:" + NDNBlockChainIPAddress + ":" + NDNBlockChainPortAddress); + loginmessage = e.getMessage(); + } + return loginmessage; + } + private byte[] getBlockChainRegisterBuffer(String username,String phone, String pubkey) { + String registerString=getBlockChainRegisterJsonString(username,phone, pubkey); + System.out.println("json: "+registerString); + int jsonLen = registerString.getBytes(StandardCharsets.UTF_8).length; + System.out.println("json len: "+jsonLen); + byte[] registerByte=new byte[jsonLen+4]; +// System.arraycopy(intToBytesLittle(jsonLen),0, +// registerByte,0,4); + System.arraycopy(intToBytesLittle(jsonLen),0, + registerByte,0,4); + System.arraycopy(registerString.getBytes(StandardCharsets.UTF_8), + 0,registerByte,4,jsonLen); + return registerByte; + } + + private byte[] getBlockChainWhiteBuffer(String phone) { + String registerString=getBlockChainWhiteUserJsonString(phone); + System.out.println("json: "+registerString); + int jsonLen = registerString.getBytes().length; + System.out.println("json len: "+jsonLen); + byte[] registerByte=new byte[jsonLen+4]; + System.arraycopy(intToBytesLittle(jsonLen),0, + registerByte,0,4); + System.arraycopy(registerString.getBytes(StandardCharsets.UTF_8), + 0,registerByte,4,jsonLen); + return registerByte; + } + + private byte[] getBlockChainDeleteBuffer(String prefix,String sig) { + String registerString=getBlockChainDeleteUserJsonString(prefix,sig); + System.out.println("json: "+registerString); + int jsonLen = registerString.getBytes().length; + System.out.println("json len: "+jsonLen); + byte[] registerByte=new byte[jsonLen+4]; + System.arraycopy(intToBytesLittle(jsonLen),0, + registerByte,0,4); + System.arraycopy(registerString.getBytes(StandardCharsets.UTF_8), + 0,registerByte,4,jsonLen); + return registerByte; + } + + /** + * 以小端模式将int转成byte[] + * + * @param value + * @return + */ + public static byte[] intToBytesLittle(int value) { + byte[] src = new byte[4]; + src[3] = (byte) ((value >> 24) & 0xFF); + src[2] = (byte) ((value >> 16) & 0xFF); + src[1] = (byte) ((value >> 8) & 0xFF); + src[0] = (byte) (value & 0xFF); + return src; + } + + /** + * 以大端模式将int转成byte[] + * + * @param value + * @return + */ + public static byte[] intToBytesBig(int value) { + byte[] src = new byte[4]; + src[0] = (byte) ((value >> 24) & 0xFF); + src[1] = (byte) ((value >> 16) & 0xFF); + src[2] = (byte) ((value >> 8) & 0xFF); + src[3] = (byte) (value & 0xFF); + return src; + } + + /** + * 转换byte数组为int(小端) + * @return + * @note 数组长度至少为4,按小端方式转换,即传入的bytes是小端的,按这个规律组织成int + */ + public int Bytes2Int_LE(byte[] bytes){ + if(bytes.length < 4) + return -1; + int iRst = (bytes[0] & 0xFF); + iRst |= (bytes[1] & 0xFF) << 8; + iRst |= (bytes[2] & 0xFF) << 16; + iRst |= (bytes[3] & 0xFF)<< 24; + + return iRst; + } + + private String getBlockChainDeleteUserJsonString(String prefix,String sig) { + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("Type", "user-act"); + jsonObject.put("Command", "Destroy"); + jsonObject.put("Prefix",prefix); + jsonObject.put("Timestamp",""); + jsonObject.put("Sig",sig); + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + return jsonObject.toString(); + } + + public static String signBuf(String prefix, CertificateV2 certificateV2){ + // 构建msg + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("Type", "user-act"); + jsonObject.put("Command", "Destroy"); + jsonObject.put("Prefix",prefix); + jsonObject.put("Timestamp",""); + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + String msg=jsonObject.toString(); + ByteBuffer byteBuffer=ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));// 这句是C++没有的 + try { + SigningInfo signingInfo = new SigningInfo(); + signingInfo.setSigningIdentity(certificateV2.getIdentity()); + Blob blob= KeyManager.INSTANCE.getKeyChain().sign(byteBuffer,signingInfo); +// String sig=blob.toHex(); + String sig= Common.base64Encode(blob.getImmutableArray(), false); +// String sig= Common.base64Encode(signature.getSignature().getImmutableArray()); +// String sig1=signature.getSignature().toHex(); + System.out.println("sig: "+sig); + return sig; + } catch (PibImpl.Error | KeyChain.Error | TpmBackEnd.Error e) { + e.printStackTrace(); + return ""; + } + } + + private String getBlockChainWhiteUserJsonString(String phone) { + JSONObject jsonObject = new JSONObject(); + String typeString = "whiteUser"; + String commandString = "addWhiteUser"; + String RealNameString = "王锋"; + Integer GenderInteger=0; + String IDCardString=""; + try { + jsonObject.put("Type", typeString); + jsonObject.put("Command", commandString); + jsonObject.put("RealName",RealNameString); + jsonObject.put("Phone",phone); + jsonObject.put("Gender",GenderInteger); + jsonObject.put("IDCard",IDCardString); + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + return jsonObject.toString(); + } + + // 从前端界面获得登录数据并转换成json格式 + private String getBlockChainRegisterJsonString(String username,String phone, String pubkey) { + JSONObject jsonObject = new JSONObject(); + String typeString = "user-act"; + String commandString = "Registry"; + String pubkeyString = pubkey; + String prefixString="/"+username; + Integer level=0; + String timestamp=""; + String IDCard=""; + String realname=""; + String aboutMe=""; + String face=""; + String print=""; + String iris=""; + String other=""; + String sig=""; + try { + jsonObject.put("Type", typeString); + jsonObject.put("Command", commandString); + jsonObject.put("Pubkey", pubkeyString); + jsonObject.put("Prefix",prefixString); + jsonObject.put("Level",level); + jsonObject.put("Timestamp",timestamp); + jsonObject.put("Username",username); + jsonObject.put("Realname",realname); + jsonObject.put("Phone",phone); + jsonObject.put("IDcard",IDCard); + jsonObject.put("AboutMe",aboutMe); + jsonObject.put("Face",face); + jsonObject.put("Print",print); + jsonObject.put("Iris",iris); + jsonObject.put("Other",other); + jsonObject.put("Sig",sig); + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + return jsonObject.toString(); + } + +// public static void main(String[] args) { +// NDNBlockChainConnectClient cli = new NDNBlockChainConnectClient(); +// cli.loginNewUser(""); +// } +} diff --git a/src/main/java/cn/minbrowser/util/MISUtil/NotificationUtil.java b/src/main/java/cn/minbrowser/util/MISUtil/NotificationUtil.java new file mode 100644 index 0000000..0025369 --- /dev/null +++ b/src/main/java/cn/minbrowser/util/MISUtil/NotificationUtil.java @@ -0,0 +1,33 @@ +package cn.minbrowser.util.MISUtil; + +import cn.minoa.MainApp; +import javafx.scene.control.Alert; + +import java.awt.*; + +public class NotificationUtil { + public static void notify(String title, String content){ + String osName = OSUtil.osName; + // macOS + if(osName.contains("mac")){ + String[] cmd = new String[]{"osascript", "-e", "display notification \"" + content + "\" with title \""+ title +"\""}; + BashScript.run(cmd); + } + + // windows or others + else{ + MainApp.trayIcon.displayMessage(title,content, TrayIcon.MessageType.NONE); + } + } + + + public static void alert(Alert.AlertType type, String title, String header, String content){ + Alert alert = new Alert(type); + alert.setTitle(title); + alert.setHeaderText(header); + alert.setContentText(content); + alert.showAndWait(); + } +} + + diff --git a/src/main/java/cn/minbrowser/util/MISUtil/RSACrypto.java b/src/main/java/cn/minbrowser/util/MISUtil/RSACrypto.java new file mode 100644 index 0000000..c5f9783 --- /dev/null +++ b/src/main/java/cn/minbrowser/util/MISUtil/RSACrypto.java @@ -0,0 +1,330 @@ +package cn.minbrowser.util.MISUtil; + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.io.*; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.X509EncodedKeySpec; + +//import org.apache.commons.io.IOUtils; +//import org.apache.commons.*; +//import java.util.*; + +// RSA算法实现 +// 原博文:https://blog.csdn.net/super_cui/article/details/70821268 +// 字符串转公钥:https://blog.csdn.net/petib_wangwei/article/details/37601081 + +public class RSACrypto { + private final static String RSA = "RSA"; + public static PublicKey uk; + // public static PrivateKey rk=get; + + /** */ + /** + * RSA最大加密明文大小 + */ + private static final int MAX_ENCRYPT_BLOCK = 245; + + /** */ + /** + * RSA最大解密密文大小 + */ + private static final int MAX_DECRYPT_BLOCK = 128; + // 忽略首行、末行 + private static String getKey(String filename) throws IOException { + String strKeyPEM = ""; + BufferedReader br = new BufferedReader(new FileReader(filename)); + String line=br.readLine(); + String nextline=""; + while ((line = br.readLine()) != null){ + strKeyPEM+=nextline; + nextline=br.readLine(); + if(nextline!=null){ + strKeyPEM += line ; + } + } + br.close(); + return strKeyPEM; + } + + +//private static byte[] encrypt(String text, PublicKey pubRSA) throws Exception{ +// Cipher cipher = Cipher.getInstance(RSA); +// cipher.init(Cipher.ENCRYPT_MODE, pubRSA); +// return cipher.doFinal(text.getBytes()); +//} + + + // public static byte[] encryptByPublicKey(String data) throws Exception { +// byte[] keyBytes = Base64.getDecoder().decode(data); +// X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); +// KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); +// Key publicK = keyFactory.generatePublic(x509KeySpec); + public static String encrypt2(String data) { + + String filepath = "./mis_rsa_public.pem"; + File file = new File(filepath); + + + RSAPublicKey publicKey = null; + try { + publicKey = getPublicKey(file.getAbsolutePath()); + } catch (IOException e) { + e.printStackTrace(); + } catch (GeneralSecurityException e) { + e.printStackTrace(); + } + // 对数据加密 + try { + Cipher cipher = Cipher.getInstance(RSA); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), publicKey.getModulus().bitLength())); +// int inputLen = data.getBytes().length; + } catch (Exception e) { + throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e); + } + } + +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// int offSet = 0; +// byte[] cache; +// int i = 0; +// // 对数据分段加密 +// while (inputLen - offSet > 0) { +// if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { +// cache = cipher.doFinal(data.getBytes(), offSet, MAX_ENCRYPT_BLOCK); +// } else { +// cache = cipher.doFinal(data.getBytes(), offSet, inputLen - offSet); +// } +// out.write(cache, 0, cache.length); +// i++; +// offSet = i * MAX_ENCRYPT_BLOCK; +// } +// byte[] encryptedData = out.toByteArray(); +// out.close(); +// return encryptedData; +// } + private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){ + int maxBlock = 0; + if(opmode == Cipher.DECRYPT_MODE){ + maxBlock = keySize / 8; + }else{ + maxBlock = keySize / 8 - 11; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + byte[] buff; + int i = 0; + try{ + while(datas.length > offSet){ + if(datas.length-offSet > maxBlock){ + buff = cipher.doFinal(datas, offSet, maxBlock); + }else{ + buff = cipher.doFinal(datas, offSet, datas.length-offSet); + } + out.write(buff, 0, buff.length); + i++; + offSet = i * maxBlock; + } + }catch(Exception e){ + throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e); + } + byte[] resultDatas = out.toByteArray(); + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + // IOUtils.closeQuietly(out); + return resultDatas; + } + + // 加密字符串 +// public static String encrypt2(String text) { +// //使用默认公钥 +// String filepath="./ndn/mis_rsa_public.pem"; +// File file=new File(filepath); +// +// +// RSAPublicKey publicKey= null; +// try { +// publicKey = getPublicKey(file.getAbsolutePath()); +// } catch (IOException e) { +// e.printStackTrace(); +// } catch (GeneralSecurityException e) { +// e.printStackTrace(); +// } +// try { +// +// +// String restring = new String(Base64.getEncoder().encode(encryptByPublicKey(text,publicKey))); +// System.out.println("the encrypt information"+restring); +// return restring; +// +// // return new String(Base64.getEncoder().encode(encrypt(text,publicKey))); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } + + public static RSAPublicKey getPublicKey(String filename) throws IOException, GeneralSecurityException { + String publicKeyPEM = getKey(filename); + return getPublicKeyFromString(publicKeyPEM); + } + + public static RSAPublicKey getPublicKeyFromString(String key) throws IOException, GeneralSecurityException { + String publicKeyPEM = key; +// publicKeyPEM = publicKeyPEM.replace("-----BEGIN RSA PUBLIC KEY-----", ""); +// publicKeyPEM = publicKeyPEM.replace("-----END RSA PUBLIC KEY-----", ""); +// System.out.println("size: "+publicKeyPEM.getBytes().length); +// System.out.println("string: "+publicKeyPEM); +// String publicKeyPEM= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3UIWR510Jlwk6y287DfW" + +// "WpsCxafpVr2QLeqAaR04qOaaaqXuhZbUoaxgS2HjVNje9XXiZOArLXGJLKwhfUpr" + +// "YwpSIfX6DNWhHUKcwYNca2dkzO10NXPzY7SLgDP9yYyyIV42S/QCCGZ7ku7en/Ve" + +// "R/x3CIAOchoBSt6ZRh7iGwl0s5zwVTPF3is4W+46vUECkmbi8HYRjSCEvdAqo7B9" + +// "74vNb8tCrwmhztQ3+IdImukSF5/QXMCuaUKLz9CNBZ8pUl45HruG/YxNeJXIC9MV" + +// "G1pNZ6D4pBwychwLoM16qjH8/dxZnaIvK8ru09cFNYTowBUOma8u9dpQsMD4+U8O" + +// "tQIDAQAB"; + byte[] encoded = Base64.decodeBase64(publicKeyPEM); + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded)); +// RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new PKCS8EncodedKeySpec(encoded)); + return pubKey; + } + + +// private static PublicKey getPubKey() { +// String pubKey= "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3UIWR510Jlwk6y287DfW" + +// "WpsCxafpVr2QLeqAaR04qOaaaqXuhZbUoaxgS2HjVNje9XXiZOArLXGJLKwhfUpr" + +// "YwpSIfX6DNWhHUKcwYNca2dkzO10NXPzY7SLgDP9yYyyIV42S/QCCGZ7ku7en/Ve" + +// "R/x3CIAOchoBSt6ZRh7iGwl0s5zwVTPF3is4W+46vUECkmbi8HYRjSCEvdAqo7B9" + +// "74vNb8tCrwmhztQ3+IdImukSF5/QXMCuaUKLz9CNBZ8pUl45HruG/YxNeJXIC9MV" + +// "G1pNZ6D4pBwychwLoM16qjH8/dxZnaIvK8ru09cFNYTowBUOma8u9dpQsMD4+U8O" + +// "tQIDAQAB"; +// return getPubKey(pubKey); +// } +// +// private static PublicKey getPubKey(String pubKey) { +// PublicKey publicKey = null; +// try { +// java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec( +// Base64.getDecoder().decode(pubKey)); +// // RSA对称加密算法 +// java.security.KeyFactory keyFactory; +// keyFactory = java.security.KeyFactory.getInstance(RSA); +// // 取公钥匙对象 +// publicKey = keyFactory.generatePublic(bobPubKeySpec); +// } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { +// e.printStackTrace(); +// } +// return publicKey; +// } + + + +// public static String encrypt(String text,String pubKey) { +// //先将公钥生成出来 +// PublicKey publicKey=getPubKey(pubKey); +// try { +// return byte2hex(encrypt(text, publicKey)); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } + + public static String byte2hex(byte[] b) { + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = Integer.toHexString(b[n] & 0xFF); + if (stmp.length() == 1) + hs += ("0" + stmp); + else + hs += stmp; + } + return hs.toUpperCase(); + } + + public static byte[] hex2byte(byte[] b) { + if ((b.length % 2) != 0) + throw new IllegalArgumentException("长度不是偶数"); + + byte[] b2 = new byte[b.length / 2]; + + for (int n = 0; n < b.length; n += 2) { + String item = new String(b, n, 2); + b2[n / 2] = (byte) Integer.parseInt(item, 16); + } + return b2; + } + +// public static void generateKey() throws Exception { +// KeyPairGenerator gen = KeyPairGenerator.getInstance(RSA); +// gen.initialize(512, new SecureRandom()); +// KeyPair keyPair = gen.generateKeyPair(); +// uk = keyPair.getPublic(); +// rk = keyPair.getPrivate(); +// } + +// public final static String encrypt2(String text) { +// try { +// return byte2hex(encrypt(text, uk)); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } + +// public final static String decrypt(String data) { +// try { +//// System.out.println("the data is "+data); +//// System.out.println("the data byte is"+data.getBytes()); +//// // System.out.println("the data byte is-"+decrypt(data)); +//// System.out.println("the data byte is-"+Base64.getDecoder().decode(data.getBytes())); +//// return new String(Base64.getDecoder().decode(decrypt(data.getBytes()))); +// Cipher cipher = Cipher.getInstance("RSA"); +// cipher.init(Cipher.DECRYPT_MODE, rk); +// return new String(cipher.doFinal(org.apache.commons.codec.binary.Base64.decodeBase64(data)), "UTF-8"); +// +// // return new String(Base64.getDecoder().decode(decrypt(hex2byte(data.getBytes())))); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } + +// private static byte[] decrypt(byte[] src) throws Exception { +// Cipher cipher = Cipher.getInstance(RSA); +// cipher.init(Cipher.DECRYPT_MODE, rk); +// return cipher.doFinal(src); +// } + + + + + + //just for test +// public static void main(String args[]) { +// try { +// // RSACrypto.generateKey(); +//// String filepath="D:\\wefree\\MIN-VPN\\src\\main\\java\\cn\\minoa\\view\\login\\mis_rsa_pubic.pem";//注意filepath的内容; +//// String filepath="./ndn/mis_rsa_public.pem"; +//// File file=new File(filepath); +//// uk=getPublicKey(file.getAbsolutePath()); +//// uk=getPublicKey("D:\\wefree\\MIN-VPN\\src\\main\\java\\cn\\minoa\\view\\login\\mis_rsa_pubic.pem"); +// String cipherText = RSACrypto.encrypt2("123456"); +// System.out.println("密文是:" + cipherText); +// // String plainText = RSACrypto.decrypt(cipherText); +// // System.out.println("明文是:" + plainText); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +} +// diff --git a/src/main/java/cn/minbrowser/view/login/LoginHTMLController.java b/src/main/java/cn/minbrowser/view/login/LoginHTMLController.java new file mode 100644 index 0000000..ad138a6 --- /dev/null +++ b/src/main/java/cn/minbrowser/view/login/LoginHTMLController.java @@ -0,0 +1,11 @@ +package cn.minbrowser.view.login; + +/* + * @author wefree + */ +/** + * 为login.html做数据传输 + */ +public class LoginHTMLController { + +} diff --git a/src/main/java/cn/minbrowser/view/login/LoginHandler.java b/src/main/java/cn/minbrowser/view/login/LoginHandler.java new file mode 100644 index 0000000..0a0da66 --- /dev/null +++ b/src/main/java/cn/minbrowser/view/login/LoginHandler.java @@ -0,0 +1,106 @@ +package cn.minbrowser.view.login; + +/* + * @author wefree + */ + +import cn.minbrowser.MiniMinData.KeyManager; +import cn.minbrowser.util.Base64EncodeUtil; +import cn.minbrowser.util.Encryption.EncryptionUtil; +import cn.minbrowser.util.MISUtil.NDNBlockChainConnectClient; +import cn.minbrowser.util.MISUtil.RSACrypto; +import net.named_data.jndn.security.KeyChain; +import net.named_data.jndn.security.pib.Pib; +import net.named_data.jndn.security.pib.PibImpl; +import net.named_data.jndn.security.tpm.Tpm; +import net.named_data.jndn.security.tpm.TpmBackEnd; +import net.named_data.jndn.security.v2.CertificateV2; +import org.json.JSONObject; + +/** + * 处理登录MIS的逻辑 + */ +public class LoginHandler { + public static boolean handleLogin(String username,String password){ + // 先编码用户名 + String usernameEncode= Base64EncodeUtil.Base64PlusEncode(username); + + // 登录之前先查看本地是否有该用户拥有的证书 + String keyChainNameString="/"+usernameEncode; + try { + if(!KeyManager.INSTANCE.isInKeyChain(keyChainNameString)){ + System.out.println("登录失败。本地没有该密钥:"+username); + return false; + } + } catch (Pib.Error | KeyChain.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error error) { + System.out.println("登录失败。密钥解析错误"); + return false; + } + + // 本地寻找到了正确的证书,就将发送兴趣包时用的证书由默认证书替换为该证书 + try { + KeyManager.INSTANCE.initKeyChain(keyChainNameString); + } catch (Pib.Error | PibImpl.Error | Tpm.Error | TpmBackEnd.Error | CertificateV2.Error | KeyChain.Error error) { + System.out.println("证书替换失败。密钥解析错误"); + return false; + } + + // 与MIS交互,进行登录验证 + String loginJsonString = getLoginJsonString(usernameEncode,password); + NDNBlockChainConnectClient ndnBlockChainConnectClient = new NDNBlockChainConnectClient("121.15.171.91",6363); + String resString = ndnBlockChainConnectClient.loginNewUser(RSACrypto.encrypt2(loginJsonString)); + // 解析MIS返回的信息 + boolean flag=false; + System.out.println("the login restring "+resString); + JSONObject jsonObject; + Integer resCode = null; + String loginmessage; + try { + jsonObject = new JSONObject(resString); + System.out.println("mis: the return LOGIN IN CHECK PASS infomation"+ jsonObject); + resCode = jsonObject.getInt("StatusCode"); + System.out.println("mis: the return rescode"+ resCode); + loginmessage = jsonObject.getString("Message"); + System.out.println("mis: the return message"+ loginmessage); + }catch (Exception e){ + e.printStackTrace(); + System.out.println("登录失败。mis-json解析错误"); + } + System.out.println("mis: the return rescode second"+ resCode); + if (resCode == 200) { + System.out.println("mis: login 200"); + flag = true; + } else { + System.out.println("登录失败。mis-resCode!=200:" + resCode); + } + return flag; + } + + /** + * 将登录数据并转换成json格式 + * @param username 使用Base64编码后的用户名 + * @param password 明文密码 + * @return + */ + private static String getLoginJsonString(String username,String password) { + JSONObject jsonObject = new JSONObject(); + String commandString = "Login"; + String type ="user-act"; + String time ="1238237238723287378"; + String userNameString = username; + String passWordString = password; + String prefix ="/"+userNameString; + // 对密码进行哈希加密 + passWordString= EncryptionUtil.getMD5String(passWordString); + try { + jsonObject.put("Type", type); + jsonObject.put("Command", commandString); + jsonObject.put("Prefix", prefix); + jsonObject.put("Password", passWordString); + jsonObject.put("Timestamp", time); + } catch (Exception e) { + System.out.println("exception: " + e.getMessage()); + } + return jsonObject.toString(); + } +}