我是靠谱客的博主 饱满小蘑菇,最近开发中收集的这篇文章主要介绍20175221曾祥杰 实验五《网络编程与安全》实验五《网络编程与安全》,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

实验五《网络编程与安全》

实验报告封面

课程:Java程序设计 班级:1752班 姓名:曾祥杰 学号:20175221

指导教师:娄嘉鹏 实验日期:2019年5月26日

实验时间:13:10 - 15:25 实验序号:21

实验名称:网络编程与安全

实验步骤

  • 第一部分

  • 要求:

  • 两人一组结对编程:

  • 0. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA

  • 1. 结对实现中缀表达式转后缀表达式的功能 MyBC.java

  • 2. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java

  • 3. 上传测试代码运行结果截图和码云链接

  • 相关原理:

  • 栈 (Stack)是一种只允许在表尾插入和删除的线性表,有先进后出(FILO),后进先出(LIFO)的特点。允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom)。栈的一个应用是用来对四则运算表达式进行求值。
  • 表达式 Exp = S1 + OP + S2 (S1 ,S2是两个操作数,OP为运算符)有三种标识方法:

  • OP + S1 + S2  为前缀表示法
  • S1 + OP + S2  为中缀表示法
  • S1 + S2 + OP  为后缀表示法
  • Java中有Stack类,以及一些方法:
  • empty()

  • push()

  • pop()
  • 具体操作

  • 我们可以使用栈来实现dc 。对逆波兰式求值时,不需要再考虑运算符的优先级,只需从左到右扫描一遍后缀表达式即可。求值伪代码如下:

  • 1.设置一个操作数栈,开始栈为空;
    2.从左到右扫描后缀表达式,遇操作数,进栈;
    3.若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕。
    4.此时,栈中仅有一个元素,即为运算的结果。
  • MyBC.java

  • import java.util.*;
    /**
    * @author 20175221 Zxj
    */
    public class MyBC { private Stack<String> stack; private List<String> list; private String information; private String Information = ""; public MyBC() { stack = new Stack<String>();//设立一个栈,存放运算符 list = new ArrayList<String>();//创建一个表,存放操作数及运算符  } public void conversion(String exp) { //中缀转后缀  String element ; StringTokenizer tokenizer = new StringTokenizer(exp); while (tokenizer.hasMoreTokens()) { //当tokenizer有下一个值时,进行循环,并把值赋给element element = tokenizer.nextToken(); if (element.equals("(")) { //若是左括号,入栈  stack.push(element); } else if (element.equals("+") || element.equals("-")) { //若是“+”或“-”,继续判断栈是否为空 if (!stack.empty()) { //若栈非空,判断栈顶元素 if (stack.peek().equals("(")) { //若栈顶为“(”,运算符入栈  stack.push(element); } else { //否则先把栈顶元素移除,加到表中,再将运算符入栈  list.add(stack.pop()); stack.push(element); } } else { //若栈为空,运算符入栈  stack.push(element); } } else if (element.equals("*") || element.equals("/")) { //若是“*”或“/”,继续判断栈是否为空 if (!stack.empty()) { //若栈非空,判断栈顶元素是什么 if (stack.peek().equals("*") || stack.peek().equals("/")) { //若栈顶为“*”或“/”,先把栈顶元素移除,加到表中,再将运算符入栈  list.add(stack.pop()); stack.push(element); } else { //若栈顶为其他,运算符直接入栈  stack.push(element); } } else { //若栈为空,运算符直接入栈  stack.push(element); } } else if (element.equals(")")) { //若遇到“)”,开始循环 while (true) { //先把栈顶元素移除并赋给temp String temp = stack.pop(); if (!temp.equals("(")) { //若temp不为“(”,则加到表  list.add(temp); } else { //若temp为“(”,退出循环 break; } } } else { //若为操作数,进入列表  list.add(element); } } while (!stack.empty()) { //将栈中元素取出,加到列表中,直到栈为空  list.add(stack.pop()); } ListIterator<String> List = list.listIterator(); //返回此列表元素的列表迭代器 while (List.hasNext()) { //将迭代器中的元素依次取出,并加上空格作为分隔符 Information += List.next() + " "; List.remove(); } information = Information; } public String getInformation() { return information; } }

 

  • MyDC.java

  • import java.util.*;
    public class MyDC {
    private final char ADD = '+';
    private final char SUBTRACT = '-';
    private final char MUTIPLY = '*';
    private final char DIVIDE = '/';
    private Stack<Integer> stack;
    public MyDC(){
    stack = new Stack<Integer>();
    }
    public int evaluate(String exp){
    int op1,op2,result = 0;
    String element;
    StringTokenizer tokenizer = new StringTokenizer(exp);
    while(tokenizer.hasMoreTokens()){
    element = tokenizer.nextToken();
    if(isOperator(element)){
    op2 = (stack.pop().intValue());
    op1 = (stack.pop().intValue());
    result = evalSingleOp(element.charAt(0),op1,op2);
    stack.push(new Integer(result));
    }
    else {
    stack.push(new Integer((Integer.parseInt(element))));
    }
    }
    return result;
    }
    private boolean isOperator(String element){
    return (element.equals("+")||element.equals("-")||element.equals("*")||element.equals("/"));
    }
    private int evalSingleOp(char operation,int op1,int op2) {
    int result = 0;
    switch (operation){
    case ADD:
    result = op1+op2;
    break;
    case SUBTRACT:
    result = op1-op2;
    break;
    case MUTIPLY:
    result = op1*op2;
    break;
    case DIVIDE:
    result = op1/op2;
    }
    return result;
    }
    }

     

  • MyDCTest.java

  • import java.util.*;
    public class MyDCTester {
    public static void main(String[] args) {
    int result;
    String exp;
    MyBC bc = new MyBC();
    MyDC dc = new MyDC();
    System.out.println("请输入中缀表达式:");
    Scanner in = new Scanner(System.in);
    exp = in.nextLine();
    bc.conversion(exp);
    System.out.println("后缀表达式为:n"+bc.getInformation());
    result = dc.evaluate(bc.getInformation());
    System.out.println("计算结果为:n"+result);
    }
    }

     

  • 运行如下:
  • 第二部分

  • 要求:

  •  结对编程:1人负责客户端,一人负责服务器

  • 0. 注意责任归宿,要会通过测试证明自己没有问题

  • 1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP

  • 2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器

  • 3. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端

  • 4. 客户端显示服务器发送过来的结果

  • 5. 上传测试结果截图和码云链接

  • 相关原理:

  • 套接字是一个网络连接的端点。在java中,使用java.net.Socket对象来表示一个套接字。
  • 客户端套接字 Socket clientSocket = new Socket("服务器IP地址",端口号) 
  • 服务器端套接字 SeverSocket severForClient = new SeverSocket(端口号) 
  • 使用 close() 关闭套接字链接
  • 具体操作:

  • 我和 20175120 结对编程,我负责客户端
  • 首先查看自己电脑的IP地址:
  • Address.java

  •  

    import java.net.*;
    public class Address {
    public static void main(String[] args) throws UnknownHostException {
    InetAddress net = InetAddress.getLocalHost();
    System.out.println(net.toString());
    }
    }


     

  • Client.java

  • import java.io.*;
    import java.net.*;
    public class Client {
    public static void main(String args[]) {
    System.out.println("20175221 正在启动...");//向服务器端发送信息
    Socket mysocket;//创建客户端Socket
    DataInputStream in = null;
    DataOutputStream out = null;
    try {
    mysocket = new Socket("169.254.245.151", 2010);//客户端指向服务器地址和端口
    in = new DataInputStream(mysocket.getInputStream());
    out = new DataOutputStream(mysocket.getOutputStream());
    System.out.println("请输入中缀表达式:");//向本机的2010端口发出客户请求
    String string = new BufferedReader(new InputStreamReader(System.in)).readLine();
    MyBC conv = new MyBC();
    conv.conversion(string);
    String string1 = conv.getInformation();
    out.writeUTF(string1);
    String reply = in.readUTF();//in读取信息,堵塞状态
    System.out.println("20175221 收到 20175120 的回答:n" + reply);// 从Server读入字符串,并打印
    Thread.sleep(2000);
    } catch (Exception e) {
    System.out.println("20175120 已掉线" + e);//输出异常
    
    }
    }
    }

     

  • Server.java

  •  

    import java.io.*;
    import java.net.*;
    public class Server {
    public static void main(String[] args) throws IOException {
    int reply;
    ServerSocket serverForClient = null;
    Socket socketOnServer = null;
    DataOutputStream out = null;
    DataInputStream in = null;
    try {
    serverForClient = new ServerSocket(2010);
    } catch (IOException e1) {
    System.out.println(e1);
    }
    try {
    System.out.println("等待 20175221 呼叫...");
    socketOnServer = serverForClient.accept(); //堵塞状态,除非20175221呼叫
    in = new DataInputStream(socketOnServer.getInputStream());
    out = new DataOutputStream(socketOnServer.getOutputStream());
    String information = in.readUTF(); // in读取信息,堵塞状态
    System.out.println("20175120 收到 20175221 的提问:" + information);
    MyDC mydc = new MyDC();
    reply = mydc.evaluate(information);
    out.writeUTF(reply + "");
    Thread.sleep(2000);
    } catch (Exception e) {
    System.out.println("20175221 已掉线" + e);
    }
    }
    }

     

  • 运行如下:
  • 第三部分

  • 要求:

  • 加密结对编程:1人负责客户端,一人负责服务器
  • 0. 注意责任归宿,要会通过测试证明自己没有问题
  • 1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  • 2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
  • 3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  • 4. 客户端显示服务器发送过来的结果
  • 5. 上传测试结果截图和码云链接
  • 相关原理:

  • 由于老师曾经在课上就让我们练习过用DES加解密自己的学号姓名,所以相较AES密码算法,DES比较熟悉,因此我们选择DES。
  • DES算法参考娄老师的博客“Java 密码学算法”
  • 实现DES加密主要有以下几个步骤:
  • 对称密钥的生成和保存;
  • 使用对称密钥进行加密和解密;
  • 从文件中获取加密时使用的密钥,使用密钥进行解密。
  • 具体操作:

  • 编程思路:
  • 1.获取密钥生成器

  •  KeyGenerator kg=KeyGenerator.getInstance("DESede"); 
  • 2.初始化密钥生成器
  •  kg.init(168); 
  • 3. 生成密钥
  •  SecretKey k=kg.generateKey( ); 
  • 4.通过对象序列化方式将密钥保存在文件中
  • FileOutputStream f=new FileOutputStream("key1.dat");
    ObjectOutputStream b=new ObjectOutputStream(f); b.writeObject(k);

 

  • 我依旧负责的是客户端, Client.java 在刚才的基础上增加了使用DES算法加密的部分,实现DES的加密
  • Client.java

  • import javax.crypto.Cipher;
    import java.io.*;
    import java.net.Socket;
    import java.security.Key;
    import java.util.Scanner;
    public class Client {
    public static void main(String args[]) {
    Socket mysocket;
    MyBC mybc = new MyBC();
    DataInputStream in = null;
    DataOutputStream out = null;
    Scanner scanner = new Scanner(System.in);
    String string;
    try {
    mysocket = new Socket("169.254.245.151", 5221);
    in = new DataInputStream(mysocket.getInputStream());
    out = new DataOutputStream(mysocket.getOutputStream());
    System.out.println("20175221 正在启动...");
    FileInputStream f = new FileInputStream("key1.dat");
    ObjectInputStream b = new ObjectInputStream(f);
    Key key = (Key) b.readObject();
    Cipher cp = Cipher.getInstance("DESede");
    cp.init(Cipher.ENCRYPT_MODE, key);
    System.out.println("请输入中缀表达式:");
    string = scanner.nextLine();
    mybc.conversion(string);
    String string1 = mybc.getInformation();
    byte ptext[] = string1.getBytes("UTF-8");
    byte ctext[] = cp.doFinal(ptext);
    System.out.println("加密后的后缀表达式:");
    for (int i = 0; i < ctext.length; i++) {
    System.out.print(ctext[i] + ",");
    }
    System.out.println("");
    out.writeUTF(ctext.length + "");
    for (int i = 0; i < ctext.length; i++) {
    out.writeUTF(ctext[i] + "");
    }
    String s = in.readUTF();
    System.out.println("20175221 收到 20175120 的回应:n" + s);
    } catch (Exception e) {
    System.out.println("20175120 已掉线..." + e);
    }
    }
    }

     

  • Server.java

  • import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class Server {
    public static void main(String args[]) {
    MyDC mydc = new MyDC();
    ServerSocket serverForClient = null;
    Socket socketOnServer = null;
    DataOutputStream out = null;
    DataInputStream in = null;
    try {
    serverForClient = new ServerSocket(5221);
    } catch (IOException e1) {
    System.out.println(e1);
    }
    try {
    System.out.println("等待 20175221 下达命令...");
    socketOnServer = serverForClient.accept(); //堵塞状态,除非 20175221 呼叫
    System.out.println("20175221 终于连接上了");
    out = new DataOutputStream(socketOnServer.getOutputStream());
    in = new DataInputStream(socketOnServer.getInputStream());
    String str = in.readUTF(); // in读取信息,堵塞状态
    byte ctext[] = new byte[Integer.parseInt(str)];
    for (int i = 0;i<Integer.parseInt(str);i++) {
    String temp = in.readUTF();
    ctext[i] = Byte.parseByte(temp);
    }
    // 获取密钥
    FileInputStream f = new FileInputStream("keykb1.dat");
    int num = f.available();
    byte[] keykb = new byte[num];
    f.read(keykb);
    SecretKeySpec k = new SecretKeySpec(keykb, "DESede");
    // 解密
    Cipher cp = Cipher.getInstance("DESede");
    cp.init(Cipher.DECRYPT_MODE, k);
    byte[] ptext = cp.doFinal(ctext);
    System.out.println("");
    // 显示明文
    String p = new String(ptext,"UTF8");
    String s = mydc.evaluate(p)+"";
    System.out.println("解密后的后缀表达式:n" + p);
    System.out.println("开始计算后缀表达式:n" + p);
    System.out.println("后缀表达式的值为:n" + s);
    out.writeUTF(mydc.evaluate(p)+"");
    System.out.println("20175120 正在将值传给 20175221...");
    } catch (Exception e) {
    System.out.println("20175221 已掉线..." + e);
    }
    }
    }


     

  • 运行如下:

  • 第四部分
  • 要求:

  • 密钥分发结对编程:1人负责客户端,一人负责服务器
  • 0. 注意责任归宿,要会通过测试证明自己没有问题
  • 1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  • 2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
  • 3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  • 4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  • 5. 客户端显示服务器发送过来的结果
  • 6. 上传测试结果截图和码云链接
  • 相关原理:

  • DH算法大致分为以下两步:
  • 1.创建DH公钥和私钥;
  • 2.创建共享密钥。
  • 具体操作:

  • Client.java

  • import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.*;
    import java.net.Socket;
    import java.security.Key;
    import java.util.Scanner;
    public class Client {
    public static void main(String args[]) { MyBC mybc = new MyBC(); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; Scanner scanner = new Scanner(System.in); String str; try { mysocket = new Socket("169.254.245.151", 5221); System.out.println("20175221 正在启动..."); in = new DataInputStream(mysocket.getInputStream()); out = new DataOutputStream(mysocket.getOutputStream()); System.out.println("请输入中缀表达式:"); str = scanner.nextLine(); Key_DH.DH("Cpub.dat","Cpri.dat"); FileInputStream fp = new FileInputStream("Cpub.dat"); ObjectInputStream bp = new ObjectInputStream(fp); Key kp = (Key) bp.readObject(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(kp); byte[] kb = baos.toByteArray(); out.writeUTF(kb.length + ""); for (int i = 0; i < kb.length; i++) { out.writeUTF(kb[i] + ""); } Thread.sleep(1000); int len = Integer.parseInt(in.readUTF()); byte np[] = new byte[len]; for (int i = 0;i<len;i++) { String temp = in.readUTF(); np[i] = Byte.parseByte(temp); } ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np)); Key k2 = (Key)ois.readObject();; FileOutputStream f2 = new FileOutputStream("Spub.dat"); ObjectOutputStream b2 = new ObjectOutputStream(f2); b2.writeObject(k2); KeyAgree.DH("Spub.dat","Cpri.dat"); FileInputStream f = new FileInputStream("sb.dat"); byte[] keysb = new byte[24]; f.read(keysb); System.out.println("公共密钥:"); for (int i = 0;i<24;i++) { System.out.print(keysb[i]+","); } System.out.println(""); SecretKeySpec k = new SecretKeySpec(keysb, "DESede"); Cipher cp = Cipher.getInstance("DESede"); cp.init(Cipher.ENCRYPT_MODE, k); mybc.conversion(str); String str1 = mybc.getInformation(); byte ptext[] = str1.getBytes("UTF-8"); byte ctext[] = cp.doFinal(ptext); System.out.println("已加密后缀表达式:"); for (int i = 0; i < ctext.length; i++) { System.out.print(ctext[i] + ","); } System.out.println(""); out.writeUTF(ctext.length + ""); for (int i = 0; i < ctext.length; i++) { out.writeUTF(ctext[i] + ""); } String s = in.readUTF(); //in读取信息,堵塞状态 System.out.println("20175221 收到 20175120 的回应:" + s); } catch (Exception e) { System.out.println("20175120 已掉线..." + e); } } }
    • Server.java

    • import javax.crypto.Cipher;
      import javax.crypto.spec.SecretKeySpec;
      import java.io.*;
      import java.net.ServerSocket;
      import java.net.Socket;
      import java.security.Key;
      public class Server {
      public static void main(String args[]) {
      MyDC mydc = new MyDC();
      ServerSocket serverForClient = null;
      Socket socketOnServer = null;
      DataOutputStream out = null;
      DataInputStream in = null;
      try {
      serverForClient = new ServerSocket(5221);
      } catch (IOException e1) {
      System.out.println(e1);
      }
      try {
      System.out.println("等待 20175221 下达命令...");
      socketOnServer = serverForClient.accept(); //堵塞状态,除非 20175221 呼叫
      System.out.println("20175221 终于连接上了!");
      out = new DataOutputStream(socketOnServer.getOutputStream());
      in = new DataInputStream(socketOnServer.getInputStream());
      Key_DH.DH("Spub.dat","Spri.dat");
      int len = Integer.parseInt(in.readUTF());
      byte np[] = new byte[len];
      for (int i = 0;i<len;i++) {
      String temp = in.readUTF();
      np[i] = Byte.parseByte(temp);
      }
      ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np));
      Key k2 = (Key)ois.readObject();
      FileOutputStream f2 = new FileOutputStream("Cpub.dat");
      ObjectOutputStream b2 = new ObjectOutputStream(f2);
      b2.writeObject(k2);
      FileInputStream fp = new FileInputStream("Spub.dat");
      ObjectInputStream bp = new ObjectInputStream(fp);
      Key kp = (Key) bp.readObject();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(kp);
      byte[] kb = baos.toByteArray();
      out.writeUTF(kb.length + "");
      for (int i = 0; i < kb.length; i++) {
      out.writeUTF(kb[i] + "");
      }
      KeyAgree.DH("Cpub.dat","Spri.dat");
      String leng = in.readUTF(); // in读取信息,堵塞状态
      byte ctext[] = new byte[Integer.parseInt(leng)];
      for (int i = 0;i<Integer.parseInt(leng);i++) {
      String temp = in.readUTF();
      ctext[i] = Byte.parseByte(temp);
      }
      // 获取密钥
      FileInputStream f = new FileInputStream("sb.dat");
      byte[] keysb = new byte[24];
      f.read(keysb);
      System.out.println("公共密钥:");
      for (int i = 0;i<24;i++) {
      System.out.print(keysb[i]+",");
      }
      System.out.println("");
      SecretKeySpec k = new SecretKeySpec(keysb, "DESede");
      // 解密
      Cipher cp = Cipher.getInstance("DESede");
      cp.init(Cipher.DECRYPT_MODE, k);
      byte[] ptext = cp.doFinal(ctext);
      System.out.println("");
      // 显示明文
      String p = new String(ptext,"UTF8");
      String s = mydc.evaluate(p)+"";
      System.out.println("解密后的后缀表达式:" + p);
      System.out.println("开始计算后缀表达式: " + p);
      System.out.println("后缀表达式的值为:"+ s);
      out.writeUTF(mydc.evaluate(p)+"");
      System.out.println("20175120 正在将值传给 20175221...");
      } catch (Exception e) {
      System.out.println("20175221 已掉线..." + e);
      }
      }
      }


       

      • 运行如下

      • 第五部分

      • 要求:

      • 完整性校验结对编程:1人负责客户端,一人负责服务器
      • 0. 注意责任归宿,要会通过测试证明自己没有问题
      • 1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
      • 2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
      • 3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
      • 4. 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
      • 5. 客户端显示服务器发送过来的结果
      • 6. 上传测试结果截图和码云链接
      • 相关原理:                        

      • 可以使用Java计算指定字符串的消息摘要

      •  update() 可以将原始数据传递给该对象

      •  digest() 可以得到消息摘要    

      • 具体操作:

      • Client.java

      • import javax.crypto.Cipher;
        import javax.crypto.spec.SecretKeySpec;
        import java.io.*;
        import java.net.Socket;
        import java.security.Key;
        import java.util.Scanner;
        public class Client {
        public static void main(String args[]) {
        MyBC mybc = new MyBC();
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        Scanner scanner = new Scanner(System.in);
        String str;
        try {
        mysocket = new Socket("169.254.245.151", 5221);
        System.out.println("20175221 正在启动...");
        in = new DataInputStream(mysocket.getInputStream());
        out = new DataOutputStream(mysocket.getOutputStream());
        System.out.println("请输入中缀表达式:");
        str = scanner.nextLine();
        Key_DH.DH("Cpub.dat","Cpri.dat");
        FileInputStream fp = new FileInputStream("Cpub.dat");
        ObjectInputStream bp = new ObjectInputStream(fp);
        Key kp = (Key) bp.readObject();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(kp);
        byte[] kb = baos.toByteArray();
        out.writeUTF(kb.length + "");
        for (int i = 0; i < kb.length; i++) {
        out.writeUTF(kb[i] + "");
        }
        Thread.sleep(1000);
        int len = Integer.parseInt(in.readUTF());
        byte np[] = new byte[len];
        for (int i = 0;i<len;i++) {
        String temp = in.readUTF();
        np[i] = Byte.parseByte(temp);
        }
        ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (np));
        Key k2 = (Key)ois.readObject();;
        FileOutputStream f2 = new FileOutputStream("Spub.dat");
        ObjectOutputStream b2 = new ObjectOutputStream(f2);
        b2.writeObject(k2);
        KeyAgree.DH("Spub.dat","Cpri.dat");
        FileInputStream f = new FileInputStream("sb.dat");
        byte[] keysb = new byte[24];
        f.read(keysb);
        System.out.println("公共密钥:");
        for (int i = 0;i<24;i++) {
        System.out.print(keysb[i]+",");
        }
        System.out.println("");
        SecretKeySpec k = new SecretKeySpec(keysb, "DESede");
        Cipher cp = Cipher.getInstance("DESede");
        cp.init(Cipher.ENCRYPT_MODE, k);
        mybc.conversion(str);
        String str1 = mybc.getInformation();
        byte ptext[] = str1.getBytes("UTF-8");
        String ptextMd5 = DigestPass.DP(str1);
        System.out.println("明文的MD5值为:n"+ptextMd5);
        byte ctext[] = cp.doFinal(ptext);
        System.out.println("加密后的后缀表达式:");
        for (int i = 0; i < ctext.length; i++) {
        System.out.print(ctext[i] + ",");
        }
        System.out.println("");
        out.writeUTF(ctext.length + "");
        for (int i = 0; i < ctext.length; i++) {
        out.writeUTF(ctext[i] + "");
        }
        out.writeUTF(ptextMd5);
        String s = in.readUTF();
        //in读取信息,堵塞状态
        System.out.println("20175221 收到 20175120 的回应:n" + s);
        } catch (Exception e) {
        System.out.println("20175120 已掉线..." + e);
        }
        }
        }

         

      • Server.java

      • import javax.crypto.Cipher;
        import javax.crypto.spec.SecretKeySpec;
        import java.io.*;
        import java.net.ServerSocket;
        import java.net.Socket;
        import java.security.Key;
        public class Server {
        public static void main(String args[]) {
        MyDC mydc = new MyDC();
        ServerSocket serverForClient = null;
        Socket socketOnServer = null;
        DataOutputStream out = null;
        DataInputStream in = null;
        try {
        serverForClient = new ServerSocket(5221);
        } catch (IOException e1) {
        System.out.println(e1);
        }
        try {
        System.out.println("等待 20175221 呼叫...");
        socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫
        System.out.println("20175221 终于连接上了!");
        out = new DataOutputStream(socketOnServer.getOutputStream());
        in = new DataInputStream(socketOnServer.getInputStream());
        Key_DH.DH("Spub.dat","Spri.dat");
        int len = Integer.parseInt(in.readUTF());
        byte np[] = new byte[len];
        for (int i = 0;i<len;i++) {
        String temp = in.readUTF();
        np[i] = Byte.parseByte(temp);
        }
        ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream(np));
        Key k2 = (Key)ois.readObject();;
        FileOutputStream f2 = new FileOutputStream("Cpub.dat");
        ObjectOutputStream b2 = new ObjectOutputStream(f2);
        b2.writeObject(k2);
        FileInputStream fp = new FileInputStream("Spub.dat");
        ObjectInputStream bp = new ObjectInputStream(fp);
        Key kp = (Key) bp.readObject();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(kp);
        byte[] kb = baos.toByteArray();
        out.writeUTF(kb.length + "");
        for (int i = 0; i < kb.length; i++) {
        out.writeUTF(kb[i] + "");
        }
        KeyAgree.DH("Cpub.dat","Spri.dat");
        String leng = in.readUTF(); // in读取信息,堵塞状态
        byte ctext[] = new byte[Integer.parseInt(leng)];
        for (int i = 0;i<Integer.parseInt(leng);i++) {
        String temp = in.readUTF();
        ctext[i] = Byte.parseByte(temp);
        }
        String check = in.readUTF();
        // 获取密钥
        FileInputStream f = new FileInputStream("sb.dat");
        byte[] keysb = new byte[24];
        f.read(keysb);
        System.out.println("公共密钥:");
        for (int i = 0;i<24;i++) {
        System.out.print(keysb[i]+",");
        }
        System.out.println("");
        SecretKeySpec k = new SecretKeySpec(keysb, "DESede");
        // 解密
        Cipher cp = Cipher.getInstance("DESede");
        cp.init(Cipher.DECRYPT_MODE, k);
        byte[] ptext = cp.doFinal(ctext);
        System.out.println("");
        // 显示明文
        String p = new String(ptext, "UTF8");
        String s = mydc.evaluate(p)+"";
        String pMd5 = DigestPass.DP(p);
        System.out.println("解密得到明文的MD5值:n"+pMd5);
        if (pMd5.equals(check)){
        System.out.println("已验证与 20175221 的MD5值一致");
        System.out.println("计算后缀表达式: n" + p);
        out.writeUTF(mydc.evaluate(p)+"");
        System.out.println("后缀表达式的值为:n"+ s);
        }
        else {
        System.out.println("警告!!! MD5值不一致!你是不是背叛了 20175221!");
        }
        } catch (Exception e) {
        System.out.println("20175221 已掉线..." + e);
        }
        }
        }

         

      • 运行如下:
      •  
  • 码云链接

实验体会:

  • 此次实验的内容是网络编程,同时要求两人结对完成。基本上所有的实验点都与客户端和服务器有关,我主要负责客户端,我的搭档负责服务器。这就要求我们俩要配合默契,不能有一个人没有完成指定的任务,否则就达不到实验点的要求。
  • 在这次实验之前,虽然有看过一些Java网络编程理论的内容。但等我真正自己动手操作时,发现其实还是有许多与预想不一样的地方,这就是慢慢修改,考验耐心的时刻,但很庆幸我挺了过来。
  • 在和搭档一起做实验的过程中,我们也复习了网络编程和密码学算法的相关知识,参考了书上代码和以及娄老师的博客---Java 密码学算法,我们着实在这个过程中学到了很多新的内容。
  • 这次结对编程,相当于减轻了一半的工作量。为了给这次实验增添一些乐趣,我们也是尽可能把一些语言丰富。
  • 这是Java的最后一次实验,我收获颇丰,感激这一段学习Java的时间。

 

步骤耗时百分比
需求分析10min5%
设计40min20%
代码实现100min50%
测试30min15%
分析总结20min10%

 参考资料

  • Java 密码学算法

转载于:https://www.cnblogs.com/zxja/p/10925619.html

最后

以上就是饱满小蘑菇为你收集整理的20175221曾祥杰 实验五《网络编程与安全》实验五《网络编程与安全》的全部内容,希望文章能够帮你解决20175221曾祥杰 实验五《网络编程与安全》实验五《网络编程与安全》所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部