20175208 实验五 网络编程与安全
实验步骤:
任务一:
- 两人一组结对编程
- 结对实现中缀表达式转后缀表达式的功能 MyBC.java
- 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
实验过程
- 之前结队编程做过一样的题目,所以就肥肠简单啦
- 为什么要将中缀表达式转为后缀表达式
- 中缀表达式,虽然符合我们的数学计算习惯,但是并不符合计算机运算的方式
- 后缀表达式严格按照从左到右进行计算的模式 符合计算机运行方式而中缀表达式需要计算机遇到符号后向后扫描一位 若为括号或优先级更高的操作符还需要向后继续扫描
- 后缀表达式的定义
- 后缀表达式(又称为逆波兰reverse polish)就是不需要括号就可以实现调整运算顺序的一种技法。
- 比如:
ab+cde+**
,改为中缀表达式其实是(a+b)*((d+e)*c)
- 后缀表达式不含括号
- 中缀转后缀
- 重要的数据结构----栈
- 如果读入操作数,则直接放入输出字符串;如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶,并确定栈顶运算符的优先级比放入的运算符的优先级低;如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串
- 如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低
- 如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串
- 后缀表达式的计算
- 从左到右扫描后缀表达式
- 如果遇到操作数,将其压入栈中
- 如果遇到操作符,则从栈中弹出两个操作数,计算结果然后把结果入栈直到遍历完后缀表达式,则计算完成
- 此时的栈顶元素即为计算结果。
实验代码:
MyBC:
import java.util.*; import java.lang.String; public class MyBC { private int priority(char c){ if(c == '*' || c== '/') return 2; else if(c == '+' || c== '-') return 1; else return 0; } private boolean leftPirority(Character c1,char c2){ if(c1 == null) return false; return priority(c1)>=priority(c2); } private boolean isNumber(char c){ if('0' <= c && c<='9') return true; return false; } private boolean isLeftBracket(char c){ if(c == '(') return true; return false; } private boolean isRightBracket(char c){ if(c == ')') return true; return false; } private boolean isOperator(char c){ if(c == '+' || c == '-' || c == '*' ||c == '/') return true; return false; } public String parse(String str){ class Stack<S>{ private LinkedList<S> list = new LinkedList<S>(); public void push(S t){ list.addLast(t); } public S pop(){ return list.removeLast(); } public S top(){ return list.peekLast(); } public boolean isEmpty(){ return list.isEmpty(); } } Stack<Character> stack = new Stack<>(); StringBuilder string = new StringBuilder(); char[] cs = str.toCharArray(); for(int i=0; i<cs.length; ++i){ char c = cs[i]; if( isNumber(c)){ string.append(c); }else if( isLeftBracket(c)){ stack.push(c); }else if( isOperator(c)){ while( leftPirority(stack.top(), c)){ string.append( stack.pop()); } stack.push(c); }else if( isRightBracket(c)){ while( !isLeftBracket( stack.top())){ string.append(stack.pop()); } stack.pop(); } } while( !stack.isEmpty()){ string.append(stack.pop()); } return string.toString(); } }
MyDC:
import java.util.StringTokenizer; import java.util.Stack; public class MyDC { /** * constant for addition symbol */ private final char ADD = '+'; /** * constant for subtraction symbol */ private final char SUBTRACT = '-'; /** * constant for multiplication symbol */ private final char MULTIPLY = '*'; /** * constant for division symbol */ private final char DIVIDE = '/'; /** * the stack */ private Stack<Integer> stack; public MyDC() { stack = new Stack<Integer>(); } public int evaluate(String expr) { int op1, op2, result = 0; String token; StringTokenizer tokenizer = new StringTokenizer(expr); while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); if (isOperator(token)) { op2 = (stack.pop()).intValue(); op1 = (stack.pop()).intValue(); result = evalSingleOp(token.charAt(0), op1, op2); stack.push(new Integer(result)); } else stack.push(new Integer(Integer.parseInt(token))); } return result; } private boolean isOperator(String token) { return (token.equals("+") || token.equals("-") || token.equals("*") || token.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 MULTIPLY: result = op1 * op2; break; case DIVIDE: result = op1 / op2; } return result; } }
MyBCTester:
import java.util.Scanner; import java.lang.String; public class MyBCTester { public static void main (String[] args) { String expression, again; String result_1; int result_2; try { Scanner in = new Scanner(System.in); do { MyBC bc = new MyBC(); System.out.println ("请输入一个中缀表达式: "); expression = in.nextLine(); result_1 = bc.parse(expression); System.out.println(); String[] b = result_1.split(""); String x = ""; for(int i=0;i<b.length;i++){ x=x+b[i]+" "; } System.out.println("后缀表达式为: " + x); MyDC dc = new MyDC(); result_2 = dc.evaluate (x); System.out.println ("That expression equals " + result_2); System.out.print ("Evaluate another expression [Y/N]? "); again = in.nextLine(); System.out.println(); } while (again.equalsIgnoreCase("y")); } catch (Exception IOException) { System.out.println("Input exception reported"); } } }
实验截图:
任务二:
- 结对编程:1人负责客户端,一人负责服务器
- 注意责任归宿,要会通过测试证明自己没有问题
- 基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
- 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 客户端显示服务器发送过来的结果
实验代码:
Client2:
import java.io.*; import java.net.*; public class Client2 { public static void main(String args[]) { System.out.println("客户端启动..."); //while (true) { Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket("192.168.188.1", 2010); in = new DataInputStream(mysocket.getInputStream()); out = new DataOutputStream(mysocket.getOutputStream()); System.out.println("请输入:"); String str = new BufferedReader(new InputStreamReader(System.in)).readLine(); MyBC turner = new MyBC(); turner.conversion(str); String str1 = turner.getMessage(); out.writeUTF(str1); String s = in.readUTF(); //in读取信息,堵塞状态// System.out.println("客户收到服务器的回答:" + s); Thread.sleep(500); } catch (Exception e) { System.out.println("服务器已断开" + e); } } } }
Server2:
import java.io.*; import java.net.*; public class Server2 { public static void main(String[] args) throws IOException { int answer; //while (true) { 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("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 out = new DataOutputStream(socketOnServer.getOutputStream()); in = new DataInputStream(socketOnServer.getInputStream()); String s = in.readUTF(); // in读取信息,堵塞状态 System.out.println("服务器收到客户的提问:" + s); MyDC myDC = new MyDC(); answer = myDC.evaluate(s); out.writeUTF(answer + ""); Thread.sleep(500); } catch (Exception e) { System.out.println("客户已断开" + e); } //} } }
实验截图:
任务三:
- 加密结对编程:1人负责客户端,一人负责服务器
- 注意责任归宿,要会通过测试证明自己没有问题
- 基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用DES或AES算法加密后通过网络把密文发送给服务器
- 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
- 客户端显示服务器发送过来的结果
实验代码:
- gistfile
import javax.crypto.Cipher; import java.io.*; import java.net.Socket; import java.security.Key; import java.util.Scanner; public class Client3 { 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 str; try { mysocket = new Socket("192.168.188.1", 5208); in = new DataInputStream(mysocket.getInputStream()); out = new DataOutputStream(mysocket.getOutputStream()); System.out.println("客户端启动..."); 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("请输入中缀表达式:"); str = scanner.nextLine(); mybc.conversion(str); String str1 = mybc.getMessage(); 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] + ""); //System.out.print(); } String s = in.readUTF(); //in读取信息,堵塞状态 System.out.println("客户收到服务器的回应:" + s); } catch (Exception e) { System.out.println("服务器已断开" + e); } } }
- SDec
import java.io.*; import javax.crypto.*; import javax.crypto.spec.*; public class SDec { public static String decipher(String s) throws Exception { // 获取密文 FileInputStream f = new FileInputStream("SEnc.dat"); int num = f.available(); byte[] ctext = new byte[num]; f.read(ctext); // 获取密钥 FileInputStream f2 = new FileInputStream("keykb1.dat"); int num2 = f2.available(); byte[] keykb = new byte[num2]; f2.read(keykb); SecretKeySpec k = new SecretKeySpec(keykb, "DESede"); // 解密 Cipher cp = Cipher.getInstance("DESede"); cp.init(Cipher.DECRYPT_MODE, k); byte[] ptext = cp.doFinal(ctext); // 显示明文 String p = new String(ptext, "UTF8"); System.out.println(p); return p; } }
- SEnc
import javax.crypto.Cipher; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.security.Key; public class SEnc { public String Cipher(String s) throws Exception { FileInputStream f = new FileInputStream("key1.dat"); ObjectInputStream b = new ObjectInputStream(f); Key k = (Key) b.readObject(); Cipher cp = Cipher.getInstance("DESede"); cp.init(Cipher.ENCRYPT_MODE, k); byte ptext[] = s.getBytes("UTF8"); System.out.println("密文为:"); for (int i = 0; i < ptext.length; i++) { System.out.print(ptext[i] + ","); } System.out.println(""); byte ctext[] = cp.doFinal(ptext); String cipher = ""; for (int i = 0; i < ctext.length; i++) { cipher = cipher + ctext[i]; } FileOutputStream f2 = new FileOutputStream("SEnc.dat"); f2.write(ctext); return cipher; } }
- Server3
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server3 { 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(5208); } catch (IOException e1) { System.out.println(e1); } try { System.out.println("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 System.out.println("客户已连接"); out = new DataOutputStream(socketOnServer.getOutputStream()); in = new DataInputStream(socketOnServer.getInputStream()); 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 f2 = new FileInputStream("keykb1.dat"); int num2 = f2.available(); byte[] keykb = new byte[num2]; f2.read(keykb); SecretKeySpec k = new SecretKeySpec(keykb, "DESede"); // 解密 Cipher cp = Cipher.getInstance("DESede"); cp.init(Cipher.DECRYPT_MODE, k); byte[] ptext = cp.doFinal(ctext); /*for (int i = 0; i < ptext.length; i++) { System.out.print(ptext[i] + ","); } */ System.out.println(""); // 显示明文 String p = new String(ptext,"UTF8"); System.out.println("被解密的后缀表达式:" + p); System.out.println("计算后缀表达式" + p); out.writeUTF(mydc.evaluate(p)+""); } catch (Exception e) { System.out.println("客户已断开" + e); } } }
实验截图:
任务四:
- Client4
import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.net.Socket; import java.security.Key; import java.util.Optional; import java.util.Scanner; public class Client4 { 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("192.168.188.1", 5208); System.out.println("客户端启动..."); 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.getMessage(); 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("客户收到服务器的回应:" + s); } catch (Exception e) { System.out.println("服务器已断开" + e); } } }
- KeyAgree
import javax.crypto.KeyAgreement; import javax.crypto.spec.SecretKeySpec; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.security.PrivateKey; import java.security.PublicKey; public class KeyAgree{ public static void DH(String s1,String s2) throws Exception{ // 读取对方的DH公钥 FileInputStream f1=new FileInputStream(s1); ObjectInputStream b1=new ObjectInputStream(f1); PublicKey pbk=(PublicKey)b1.readObject( ); //读取自己的DH私钥 FileInputStream f2=new FileInputStream(s2); ObjectInputStream b2=new ObjectInputStream(f2); PrivateKey prk=(PrivateKey)b2.readObject( ); // 执行密钥协定 KeyAgreement ka=KeyAgreement.getInstance("DH"); ka.init(prk); ka.doPhase(pbk,true); //生成共享信息 byte[ ] sb=ka.generateSecret(); FileOutputStream fsb = new FileOutputStream("sb.dat"); fsb.write(sb); } }
- Key_DH
import javax.crypto.spec.DHParameterSpec; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; public class Key_DH{ private static final byte skip1024ModulusBytes[] = { (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD, (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4, (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B, (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D, (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C, (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C, (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6, (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0, (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B, (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB, (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D, (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD, (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43, (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C, (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C, (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C, (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40, (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C, (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72, (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03, (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29, (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C, (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB, (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B, (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08, (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D, (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C, (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22, (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB, (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55, (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 }; // The SKIP 1024 bit modulus private static final BigInteger skip1024Modulus = new BigInteger(1, skip1024ModulusBytes); // The base used with the SKIP 1024 bit modulus private static final BigInteger skip1024Base = BigInteger.valueOf(2); public static void DH(String s1,String s2) throws Exception{ DHParameterSpec DHP= new DHParameterSpec(skip1024Modulus,skip1024Base); KeyPairGenerator kpg= KeyPairGenerator.getInstance("DH"); kpg.initialize(DHP); KeyPair kp=kpg.genKeyPair(); PublicKey pbk=kp.getPublic(); PrivateKey prk=kp.getPrivate(); // 保存公钥 FileOutputStream f1=new FileOutputStream(s1); ObjectOutputStream b1=new ObjectOutputStream(f1); b1.writeObject(pbk); // 保存私钥 FileOutputStream f2=new FileOutputStream(s2); ObjectOutputStream b2=new ObjectOutputStream(f2); b2.writeObject(prk); } }
- Server4
import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.security.Key; public class Server4 { 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(5318); } catch (IOException e1) { System.out.println(e1); } try { System.out.println("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 System.out.println("客户已连接"); 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"); System.out.println("被解密的后缀表达式:" + p); System.out.println("计算后缀表达式" + p); out.writeUTF(mydc.evaluate(p)+""); } catch (Exception e) { System.out.println("客户已断开" + e); } } }
实验截图:
任务五:
- 完整性校验结对编程:1人负责客户端,一人负责服务器
- 注意责任归宿,要会通过测试证明自己没有问题
- 基于Java Socket实现客户端/服务器功能,传输方式用TCP
- 客户端让用户输入中缀表达式,然后把中缀表达式调用
MyBC.java
的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器 - 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
- 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用
MyDC.java
的功能计算后缀表达式的值,把结果发送给客户端 - 客户端显示服务器发送过来的结果
实验代码:
- Client5
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 Client5 { 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("192.168.188.1", 5208); System.out.println("客户端启动..."); 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(500); 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.getMessage(); byte ptext[] = str1.getBytes("UTF-8"); String ptextMd5 = DigestPass.DP(str1); System.out.println("明文的MD5值:"+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("客户收到服务器的回应:" + s); } catch (Exception e) { System.out.println("服务器已断开" + e); } } }
- Server5
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 Server5 { 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(5318); } catch (IOException e1) { System.out.println(e1); } try { System.out.println("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 System.out.println("客户已连接"); 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 pMd5 = DigestPass.DP(p); System.out.println("被解密明文的MD5值:"+pMd5); if (pMd5.equals(check)){ System.out.println("和客户端的MD5值一致"); System.out.println("计算后缀表达式" + p); out.writeUTF(mydc.evaluate(p)+""); } else { System.out.println("警告:和客户端的MD5值不一致!"); } } catch (Exception e) { System.out.println("客户已断开" + e); } } }
实验截图:
码云连接:https://gitee.com/zhangjiahua20175208/codes
实验感悟:
本次实验考察的是网络编程与安全,基于四则运算来进行的,与以前进行的实验有相同部分,可以参考以前的代码,所以这次实验并不是很困难。两人结对的方式也让实验可以互帮互助,减轻实验的压力,客服端/服务器功能在学习的时候并不是很牢固,通过这次的实验,在应用上有了更好地掌握。