Java笔记-加密应用在网络通信中的使用 淡淡的烟草味﹌ 2022-09-05 04:20 145阅读 0赞 逻辑是这样的: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxNzg0NDI3NjE_size_16_color_FFFFFF_t_70][] 逻辑解释: 1.OpenSSL生成RSA私钥和公钥,公钥存客户端,私钥存服务端; 2.客户端与服务端的DH分别生成自己的公钥和私钥,并且使用相同的公钥和私钥算法; 3.首先客户端把DH生成的公钥使用RSA加密,通过HTTP协议,发送到服务端,服务端把先解密RSA,然后把自己DH模块的公钥发给客户端; 4.客户端和服务端都拿到了对方的公钥,再与自己的私钥,通过密钥公式,算出AES加密密钥。后面发送数据时都通过AES加密。 程序运行截图如下: ![20210817085658294.png][] 关键源码如下: 服务端(IDEA普通Java项目): Main.java package cn.it1995; import cn.it1995.http.HttpCallback; import cn.it1995.http.HttpServer; import cn.it1995.tool.AES; import cn.it1995.tool.DH; import cn.it1995.tool.DataSecret; import cn.it1995.tool.RSA; import java.io.UnsupportedEncodingException; import java.util.Map; public class Main { private static final String PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjuN97tkBc0QcKGU9oXydaQN7q" + "wZnThxTOmdIc8O1yuA9FrDZpZ3Sz908vTqM/YPZkOUaYrGwsBO7FeQovoX7nQPKu" + "YQpRDqt7OKzhwPavyynH0Jz38PDyCBw45zwl4Ux8BtsggTrGVxAqNjO4KkuyL1QS" + "8amn4Fzl1CBre8Y0gQIDAQAB"; private static final String PRI_KEY = "MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAKO433u2QFzRBwoZ" + "T2hfJ1pA3urBmdOHFM6Z0hzw7XK4D0WsNmlndLP3Ty9Ooz9g9mQ5RpisbCwE7sV5" + "Ci+hfudA8q5hClEOq3s4rOHA9q/LKcfQnPfw8PIIHDjnPCXhTHwG2yCBOsZXECo2" + "M7gqS7IvVBLxqafgXOXUIGt7xjSBAgMBAAECgYAgp0uzcdsOaAY+ZmPnDitcHdoX" + "+jsC7EsjFZzJduf03G73V2yWwzKMfkPFzKpUhrM9tAq3gpQkh2tT6Vs1usEDbrDd" + "e08Cc3D5YWK7HuTfO3kkJTSNOK0JfuT1UQaTjCmDQWWjPmYbu6UN0UDv4Mo26dgl" + "cp9h0wlaPsSFN3O97QJBANgj+4i7ABAdbTuUfq6Tcr38E7wYSFTUeL5jTd4sO636" + "+KJ6zx4uTXAmxnt9OdIY1ihLRqDh8VbiorqOelGf6iMCQQDB6jZver3mTMe6ntSY" + "hx3JWOCDM3ULkPvOWGrAcRsNKjyIuo37taXa7fuqmVQQq9MJYikJfilMhkgwkV/X" + "ihcLAkBsOvBskj9A0ottJzmcT4dIbR6wtHQbzl078NwAIaQsxZyVN+vY0BTE0RXY" + "pmc6tmcevDr8uscv28Liqg/EKdCDAkAjL9C44djblUsYvgFtu/bXtlzm8ctnUeOf" + "ScP1L5DtDqD1XoStDAUQeOaVykTK0aL1rO4tXss3q5Yl2fs+LTyJAj8f7N5kzw08" + "9S5OWCHoEm5UOeAvjFh//cjXi6lyqetBW3w17muZ2OumUAbKJXksyzmT6/QRpkX3" + "S0w/tqdJXLs="; private static final String HANDHAKE = "handshake"; public static void main(String[] args) throws UnsupportedEncodingException { // String content = "123456"; // String encrypted = RSA.encrypt(content, PUB_KEY); // System.out.println(encrypted); // System.out.println(RSA.decrypt(encrypted, PRI_KEY)); //查密钥 // DH dhC = new DH(); // DH dhS = new DH(); // // int publicKeyC = dhC.getPublicKey(); // int publicKeyS = dhS.getPublicKey(); // // byte[] secretC = dhC.getSecretKey(publicKeyS); // byte[] secretS = dhS.getSecretKey(publicKeyC); // // System.out.println("client's secrete is : "); // for(byte i : secretC){ // // System.out.print(i + " "); // } // System.out.println("\nserver's secrete is : "); // for(byte i : secretS){ // // System.out.print(i + " "); // } // AES aes = new AES(); // byte[] encrypted = aes.encrypt(content); // System.out.println(new String(encrypted)); // byte[] decrypt = aes.decrypt(encrypted); // System.out.println(new String(decrypt)); // System.out.println("start http server"); HttpServer server = new HttpServer(new HttpCallback() { private DH mDh = new DH(); private AES mAes = new AES(); @Override public byte[] onResponse(String request) { if(isHandshake(request)){ //握手 Map<String, String> header = HttpServer.getHeader(request); String handshake = header.get(HANDHAKE); System.out.println("Handshake为:" + handshake); int dhPubKey = Integer.valueOf(RSA.decrypt(handshake, PRI_KEY)); //设置为AES密钥 mAes.setKey(mDh.getSecretKey(dhPubKey)); System.out.println("解密后,客户端dhPubKey:" + dhPubKey); return DataSecret.int2Byte(mDh.getPublicKey()); } byte[] result = mAes.encrypt("Hello World"); return result; } }); server.startHttpServer(); } private static boolean isHandshake(String request){ return (request != null && request.contains(HANDHAKE)); } } DH.java package cn.it1995.tool; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; public class DH { private static final int dhP = 45; private static final int dhG = 9; private int mPriKey; //构造函数随机私钥 public DH(){ Random r = new Random(); mPriKey = r.nextInt(20); System.out.println("dh priKey is : " + mPriKey); } //公钥计算公式计算出公钥 public int getPublicKey(){ return (int) (Math.pow(dhG, mPriKey) % dhP); } //使用对方公钥与自己私钥生成密钥 //在把结果转256字节,AES密钥需要128字节或256字节 public byte[] getSecretKey(long publicKey){ int buf = (int) (Math.pow(publicKey, mPriKey) % dhP); return sha256(buf); } //转换成byte[256]类型,作为AES密钥 private byte[] sha256(int data){ try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(DataSecret.int2Byte(data)); return messageDigest.digest(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return new byte[]{-1}; } } HttpServer.java package cn.it1995.http; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class HttpServer { private boolean mRunning; private HttpCallback mCallback; public HttpServer(HttpCallback Callback) { this.mCallback = Callback; } public void startHttpServer(){ if(mRunning){ return; } mRunning = true; try { ServerSocket serverSocket = new ServerSocket(80); while (mRunning){ Socket accept = serverSocket.accept(); ExecutorService threadPool = Executors.newCachedThreadPool(); threadPool.execute(new HttpThread(accept, mCallback)); } } catch (IOException e) { e.printStackTrace(); } } public static Map<String, String> getHeader(String request){ Map<String, String> header = new HashMap<>(); BufferedReader reader = new BufferedReader(new StringReader(request)); //逐行解析 try{ String line = reader.readLine(); while (line != null && !line.trim().isEmpty()){ int p = line.indexOf(":"); if(p >= 0){ header.put(line.substring(0, p).trim().toLowerCase(), line.substring(p + 1).trim()); } line = reader.readLine(); } } catch (Exception e){ e.printStackTrace(); } return header; } } HttpThread.java package cn.it1995.http; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; public class HttpThread implements Runnable{ private Socket mSocket; private HttpCallback mCallback; public HttpThread(Socket socket, HttpCallback httpCallback){ mSocket = socket; mCallback = httpCallback; } @Override public void run() { try { BufferedReader reader = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); String content; StringBuffer request = new StringBuffer(); while((content = reader.readLine()) != null && !content.trim().isEmpty()){ request.append(content).append("\n"); } System.out.println("request:\n" + request); byte[] response = new byte[0]; if(mCallback != null){ response = mCallback.onResponse(request.toString()); } String responseFirstLine = "HTTP/1.1 200 OK \r\n"; String responseHead = "Content-type:" + "text/html" + "\r\n"; OutputStream outputStream = mSocket.getOutputStream(); outputStream.write(responseFirstLine.getBytes()); outputStream.write(responseHead.getBytes()); outputStream.write("\r\n".getBytes()); outputStream.write(response); mSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } 客户端(Android项目): MainActivity.java package com.example.myclient; import android.os.Bundle; import com.example.myclient.http.HttpRequest; import com.example.myclient.tool.AES; import com.example.myclient.tool.DH; import com.example.myclient.tool.RSA; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import java.io.IOException; import java.io.UnsupportedEncodingException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; public class MainActivity extends AppCompatActivity { private static final String PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjuN97tkBc0QcKGU9oXydaQN7q" + "wZnThxTOmdIc8O1yuA9FrDZpZ3Sz908vTqM/YPZkOUaYrGwsBO7FeQovoX7nQPKu" + "YQpRDqt7OKzhwPavyynH0Jz38PDyCBw45zwl4Ux8BtsggTrGVxAqNjO4KkuyL1QS" + "8amn4Fzl1CBre8Y0gQIDAQAB"; private static final String URL = "http://192.168.20.59/"; private byte[] mAesKey; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); final HttpRequest request = new HttpRequest(URL); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(mAesKey == null || mAesKey.length <= 0){ final DH dh = new DH(); int pubKey = dh.getPublicKey(); Log.d("test", "dh 公钥为:" + dh.getPublicKey()); try { request.handshake(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("error", "onFailure: 握手失败"); } @Override public void onResponse(Call call, Response response) throws IOException { byte[] pubKey = response.body().bytes(); mAesKey = dh.getSecretKey(pubKey); Log.d("success", "success: 握手成功aes密钥为:" + new String(mAesKey)); } }, RSA.encrypt(String.valueOf(pubKey), PUB_KEY)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else { request.request(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e("error", "请求失败"); } @Override public void onResponse(Call call, Response response) throws IOException { byte[] bytes = response.body().bytes(); AES aes = new AES(mAesKey); String content = new String(aes.decrypt(bytes)); Log.e("success", "请求成功:" + content); } }); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } } 源码打包下载地址: [https://github.com/fengfanchen/Java/tree/master/AES%26RSA%26DHDemo][https_github.com_fengfanchen_Java_tree_master_AES_26RSA_26DHDemo] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxNzg0NDI3NjE_size_16_color_FFFFFF_t_70]: /images/20220829/572dadb92ade4870b491b5b4a3623dc7.png [20210817085658294.png]: /images/20220829/a94d0299c30242db8e9561bde8cbb842.png [https_github.com_fengfanchen_Java_tree_master_AES_26RSA_26DHDemo]: https://github.com/fengfanchen/Java/tree/master/AES%26RSA%26DHDemo
相关 在Java中处理网络通信异常的策略 在Java中处理网络通信异常,通常需要考虑以下几个策略: 1. **异常捕获**: 使用`try-catch`块来捕获可能发生的异常。Java网络编程中常见的异常包括`IOE 超、凢脫俗/ 2024年11月11日 13:24/ 0 赞/ 6 阅读
相关 在Java中如何处理网络通信中的超时问题 在Java中,处理网络通信的超时问题通常需要使用Java的Socket或者URLConnection等类。以下是一个基本的例子: ```java import java.io 川长思鸟来/ 2024年10月17日 04:51/ 0 赞/ 29 阅读
相关 在Java中如何进行网络通信? 在Java中,网络通信主要通过java.net包中的类来实现。以下是一些常见的网络通信方式: 1. **Socket通信**:这是最基础的网络通信方式。客户端创建一个Sock ╰半橙微兮°/ 2024年10月14日 02:24/ 0 赞/ 54 阅读
相关 如何在Java中实现网络通信的常见问题 在网络通信中,Java提供了多种方式来解决常见的问题。以下是几个主要问题及对应的解决方案: 1. **建立连接**: - 使用Socket API:`ServerSoc 喜欢ヅ旅行/ 2024年09月10日 22:03/ 0 赞/ 59 阅读
相关 【Java应用】使用网络编程进行 socket 通信 一、网络编程和socket通信 1.1 什么是网络编程 网络编程指的是编写应用程序来实现计算机网络之间数据交换的过程。网络编程可以帮助我们构建分布式系统,实现客户端 缺乏、安全感/ 2024年03月26日 19:42/ 0 赞/ 96 阅读
相关 Java笔记-加密应用在网络通信中的使用 逻辑是这样的: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV 淡淡的烟草味﹌/ 2022年09月05日 04:20/ 0 赞/ 146 阅读
相关 混合加密算法在网络数据传输中的应用研究 <table> <tbody> <tr> <td align="left" style="font-size:24px; font-weight:bo 比眉伴天荒/ 2022年08月27日 07:56/ 0 赞/ 190 阅读
相关 移动蜂窝网络在应用中的使用监测 APP应用在使用网络时,可以设置网络类型:关闭、WLAN、WLAN与蜂窝移动网络 示例代码主要功能在于监测是否开启了蜂窝移动网络,`kCTCellularDataNotRe 布满荆棘的人生/ 2022年02月27日 03:19/ 0 赞/ 378 阅读
相关 在Java中使用AES加密 本文转载[https://blog.csdn.net/z69183787/article/details/82746686][https_blog.csdn.net_z6918 客官°小女子只卖身不卖艺/ 2021年10月29日 09:20/ 0 赞/ 335 阅读
还没有评论,来说两句吧...