博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20165223 实验五 网络编程与安全
阅读量:4468 次
发布时间:2019-06-08

本文共 19014 字,大约阅读时间需要 63 分钟。

实验五 网络编程与安全

目录

一、实验报告封面

北京电子科技学院(BESTI)

实 验 报 告

课程 Java程序设计 班级 1652班
姓名 蔡霓 学号 20165223
成绩 指导教师 娄嘉鹏
实验日期 2018年5月28日 实验密级 非密级
预习程度 已预习 实验时间 13:45 - 15:25
必修/选修 选修 实验序号

实验名称:Android开发基础

二、具体实验内容

(一)网络编程与安全-1

两人一组结对编程:

0.参考

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

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

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

(1)实验步骤

  • 编写实现中缀表达式转后缀表达式的功能代码 MyBC.java
  • 编写实现后缀表达式求值功能的代码 MyDC.java
  • 编写测试代码 MyDCTester.javaMyBCTest.java

(2)实验代码

详见码云链接:

  • MyBC.java
import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.stream.Collectors;import java.lang.String;import org.junit.Test;public class MyBC{    private static final Map
basic = new HashMap
(); static { basic.put('-', 1); basic.put('+', 1); basic.put('*', 2); basic.put('/', 2); basic.put('(', 0); } //中缀表达式 转 后缀表达式 public static String toSuffix(String infix){ List
queue = new ArrayList
(); List
stack = new ArrayList
(); char[] charArr = infix.trim().toCharArray(); String standard = "*/+-()"; char ch = '&'; int len = 0; for (int i = 0; i < charArr.length; i++) { ch = charArr[i]; if(Character.isDigit(ch)) { len++; }else if(Character.isLetter(ch)) { len++; }else if(ch == '.'){ len++; }else if(Character.isSpaceChar(ch)) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } continue; }else if(standard.indexOf(ch) != -1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } if(ch == '(') { stack.add(ch); continue; } if (!stack.isEmpty()) { int size = stack.size() - 1; boolean flag = false; while (size >= 0 && ch == ')' && stack.get(size) != '(') { queue.add(String.valueOf(stack.remove(size))); size--; flag = true; } while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) { queue.add(String.valueOf(stack.remove(size))); size--; } } if(ch != ')') { stack.add(ch); } else { stack.remove(stack.size() - 1); } } if(i == charArr.length - 1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1))); } int size = stack.size() - 1; while (size >= 0) { queue.add(String.valueOf(stack.remove(size))); size--; } } } return queue.stream().collect(Collectors.joining(" ")); }}
  • MyDC.java
import javax.xml.bind.annotation.XmlType;import java.lang.Integer;import java.util.StringTokenizer;import java.util.Stack;public class MyDC{    /** constant for addition symbol */    private final String ADD="+";    /** constant for subtraction symbol */    private final String SUBTRACT="-";    /** constant for multiplication symbol */    private final String MULTIPLY="*";    /** constant for division symbol */    private final String DIVIDE="/";    /** the stack */    private Stack
stack; public MyDC(){ stack=new Stack
(); } public int evaluate(String expr) { int op1,op2,result=0; String token; StringTokenizer tokenizer=new StringTokenizer(expr); while(tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); //如果是运算符,调用isOperator if (isOperator(token)) { //从栈中弹出操作数2 op2 = stack.pop(); //从栈中弹出操作数1 op1 = stack.pop(); //根据运算符和两个操作数调用evalSingleOp计算result; result = evalSingleOp(token, op1, op2); //计算result入栈; stack.push(result); } else//如果是操作数 { stack.push(Integer.parseInt(token)); //操作数入栈; } } return result; } private boolean isOperator(String token) { return(token.equals("+")||token.equals("-")|| token.equals("*")||token.equals("/")); } private int evalSingleOp(String 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; default: break; } return result; }}

(3)实验截图

1047360-20180603145105441-988787519.png

(二)网络编程与安全-2

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

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

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

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

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

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

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

(1)实验步骤

  • 编写服务器端与客户端链接代码
  • 客户端输入中缀表达式,调用MyBC.java转为后缀表达式
  • 服务器接收后缀表达式,调用MyDC.java计算结果值并返回到客户端

(2)实验代码

详见码云链接:

  • 服务器端:Service.java
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class Service {    public static void main(String[] args) throws IOException{        Service socketService = new Service();        socketService.oneServer();    }    public  void oneServer(){        try{            ServerSocket server=null;            try{                server=new ServerSocket(5223); //客户端链接端口                System.out.println("服务器启动成功!");            }catch(Exception e) {                System.out.println("没有启动监听!"+e);            }            Socket socket=null;            try{                socket=server.accept();            }catch(Exception e) {                System.out.println("Error."+e);            }            String line,line2;            BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));            PrintWriter writer=new PrintWriter(socket.getOutputStream());            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));            line2=in.readLine();            System.out.println("客户端:"+line2);            MyDC f = new MyDC();            System.out.printf("%d",f.evaluate(line2));            writer.println(Integer.toString(f.evaluate(line2)));            line=br.readLine();            while(!line.equals("end")){                writer.println(line);                writer.flush();                System.out.println("服务器:"+Integer.toString(f.evaluate(in.readLine())));                System.out.println("客户端:"+in.readLine());                line=br.readLine();            }            writer.close();            in.close();            socket.close();            server.close();        }catch(Exception e) {            System.out.println("Error."+e);        }    }}
  • 客户端:Client.java
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;import java.net.URL;public class Client {    public static void main(String[] args) throws IOException {        try {            //服务器的IP地址与所选端口(IP地址通过命令行指令ipconfig查出)            Socket socket = new Socket("10.1.1.234", 5223);            System.out.println("客户端启动成功!");            System.out.println("请输入中缀表达式:");            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));            PrintWriter write = new PrintWriter(socket.getOutputStream());            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));            String expression;            MyBC bc = new MyBC();            expression = br.readLine();            String input =new String();            input = bc.toSuffix("1+(4*2)/2+5+4*3-4");            while (!expression.equals("end")) {                write.println(input);                write.println(expression);                write.flush();                System.out.println("转化的后缀表达式为:" + input);                System.out.println("服务器返回值为:" + in.readLine());                expression = br.readLine();            }            write.close();            in.close();            socket.close();        } catch (Exception e) {            System.out.println("无法监听:" + e);        }    }}

(3)实验截图

1047360-20180603150456208-1454788166.png

(三)网络编程与安全-3

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

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

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

2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器

3.服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端

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

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

(1)实验步骤

  • 前期基本步骤同上一提交点
  • 编写加解密代码AES.JAVA
  • 在客户端输入中缀表达式,调用MyBC.java转后缀表达式,再调用AES.JAVA的加密部分转加密密文
  • 服务器接收到密文,调用AES.JAVA的解密部分对密文解密,再调用MyDC.java对解密明文计算值,返回客户端

(2)实验代码

详见码云链接:

  • AES.java
import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public class AES {    //初始向量    public static final String VIPARA = "aabbccddeeffgghh";    //编码方式    public static final String bm = "UTF-8";    //私钥    private static final String ASE_KEY="aabbccddeeffgghh";    /**     * 加密     */    public static String encrypt(String cleartext) {        try {            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());            SecretKeySpec key = new SecretKeySpec(ASE_KEY.getBytes(), "AES");            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");            cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);            byte[] encryptedData = cipher.doFinal(cleartext.getBytes(bm));            return new BASE64Encoder().encode(encryptedData);        } catch (Exception e) {            e.printStackTrace();            return "";        }    }    /**     * 解密     */    public static String decrypt(String encrypted) {        try {            byte[] byteMi = new BASE64Decoder().decodeBuffer(encrypted);            IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());            SecretKeySpec key = new SecretKeySpec(                    ASE_KEY.getBytes(), "AES");            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");            cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);            byte[] decryptedData = cipher.doFinal(byteMi);            return new String(decryptedData, bm);        } catch (Exception e) {            e.printStackTrace();            return "";        }    }}
  • 服务器端新增部分:Service2.java
......            String line,line2;            BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));            PrintWriter writer=new PrintWriter(socket.getOutputStream());            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));            line2=in.readLine();            System.out.println("客户端:"+line2);            //创建对象aes,并调用 AES 类中的解密方法            AES aes = new AES();            String line3 = new String();            line3 = aes.decrypt(line2);                        //调用 MyDC 类计算值            MyDC f = new MyDC();            System.out.printf("%d",f.evaluate(line3));            writer.println(Integer.toString(f.evaluate(line3)));            line=br.readLine();            ......
  • 客户端新增部分:Client2.java
......            MyBC bc = new MyBC();            expression = br.readLine();            String input =new String();            String input2 = new String();            input = bc.toSuffix("1+(4*2)/2+5+4*3-4");            //创建对象aes,并调用 AES 类中的加密方法            AES aes = new AES();            input2 = aes.encrypt(input);            while (!expression.equals("end")) {                write.println(input2);                write.println(expression);                write.flush();                System.out.println("aes加密的后缀表达式为:" + input2);                System.out.println("服务器返回值为:" + in.readLine());                expression = br.readLine();            }            ......

(3)实验截图

1047360-20180603151752802-305014833.png

(四)网络编程与安全-4

密钥分发结对编程:1人负责客户端,一人负责服务器

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

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

2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器

3.客户端和服务器用DH算法进行3DES或AES算法的密钥交换

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

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

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

(1)实验步骤

  • 前期操作与前一提交点一致
  • 在实验提交点3的基础上再添加密钥交换算法DHCode.java
  • 客户端和服务器用DH算法进行AES算法的密钥交换

(2)实验代码

详见码云链接:

  • 生成密钥对:HQKeyPair.java
import java.security.KeyPair;/** * 生成密钥对 */public class HQKeyPair{    private byte[] privateKey;    private byte[] publicKey;    public HQKeyPair()    {    }    public HQKeyPair(KeyPair keyPair)    {        this.privateKey = keyPair.getPrivate().getEncoded();        this.publicKey = keyPair.getPublic().getEncoded();    }    public HQKeyPair(byte[] privateKey, byte[] publicKey)    {        this.privateKey = privateKey;        this.publicKey = publicKey;    }    public byte[] getPrivateKey()    {        return privateKey;    }    public void setPrivateKey(byte[] privateKey)    {        this.privateKey = privateKey;    }    public byte[] getPublicKey()    {        return publicKey;    }    public void setPublicKey(byte[] publicKey)    {        this.publicKey = publicKey;    }}
  • DH算法实现:DHCode.java
import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.PrivateKey;import java.security.PublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;import javax.crypto.Cipher;import javax.crypto.KeyAgreement;import javax.crypto.SecretKey;import javax.crypto.interfaces.DHPrivateKey;import javax.crypto.interfaces.DHPublicKey;import javax.crypto.spec.DHParameterSpec;import javax.crypto.spec.SecretKeySpec;public abstract class DHCoder {    /**     * 非对称加密密钥算法     */    private static final String KEY_ALGORITHM = "DH";    /**     * 选择AES算法     */    private static final String SELECT_ALGORITHM = "AES";    /**     * 密钥长度     */    private static final int KEY_SIZE = 512;    //公钥    private static final String PUBLIC_KEY = "DHPublicKey";    //私钥    private static final String PRIVATE_KEY = "DHPrivateKey";    /**     * 初始化甲方密钥     */    public static Map
initKey() throws Exception{ //实例化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化密钥对生成器 keyPairGenerator.initialize(KEY_SIZE); //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //甲方公钥 DHPublicKey publicKey = (DHPublicKey)keyPair.getPublic(); //甲方私钥 DHPrivateKey privateKey = (DHPrivateKey)keyPair.getPrivate(); //将密钥对存储在Map中 Map
keyMap = new HashMap
(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 初始化乙方密钥 */ public static Map
initKey(byte[] key) throws Exception{ //解析甲方公钥 //转换公钥材料 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key); //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //产生公钥 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); //由甲方公钥构建乙方密钥 DHParameterSpec dhParameterSpec = ((DHPublicKey)pubKey).getParams(); //实例化密钥对生成器 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化密钥对生成器 keyPairGenerator.initialize(KEY_SIZE); //产生密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //乙方公钥 DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic(); //乙方私约 DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate(); //将密钥对存储在Map中 Map
keyMap = new HashMap
(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 加密 */ public static byte[] encrypt(byte[] data, byte[] key) throws Exception{ //生成本地密钥 SecretKey secretKey = new SecretKeySpec(key, SELECT_ALGORITHM); //数据加密 Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 解密 */ public static byte[] decrypt(byte[] data, byte[] key) throws Exception{ //生成本地密钥 SecretKey secretKey = new SecretKeySpec(key, SELECT_ALGORITHM); //数据揭秘 Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 构建密钥 */ public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws Exception{ //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //初始化公钥 //密钥材料转换 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey); //产生公钥 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); //初始化私钥 //密钥材料转换 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey); //产生私钥 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); //实例化 KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory.getAlgorithm()); //初始化 keyAgree.init(priKey); keyAgree.doPhase(pubKey, true); //生成本地密钥 SecretKey secretKey = keyAgree.generateSecret(SELECT_ALGORITHM); return secretKey.getEncoded(); } /** * 私钥 */ public static byte[] getPrivateKey(Map
keyMap) throws Exception{ Key key = (Key) keyMap.get(PRIVATE_KEY); return key.getEncoded(); } /** * 公钥 */ public static byte[] getPublicKey(Map
keyMap) throws Exception{ Key key = (Key) keyMap.get(PUBLIC_KEY); return key.getEncoded(); }}

(3)实验截图

1047360-20180603152044144-1545201313.png

(五)网络编程与安全-5

完整性校验结对编程:1人负责客户端,一人负责服务器

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

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

2.客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器

3.客户端和服务器用DH算法进行3DES或AES算法的密钥交换

4.服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端

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

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

(1)实验步骤

  • 前期操作与前一提交点一致
  • 客户端用AES算法加密后缀表达式,把密文和明文的MD5値发送给服务器
  • 客户端和服务器用DH算法进行AES算法的密钥交换
  • 服务器解密后,计算明文的MD5值,与客户端的MD5值对比

(2)实验代码

详见码云链接:

  • MD5.java
import java.security.MessageDigest;/** * 求MD5值 */public class MD5 {    public final static String[] hashValueString = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};    public static String byteToString(byte[] hashValueBytes){        String result = "";        for(int i=0;i
0 ? hashValueInt : hashValueInt+256; int high = hashValueInt / 16; //byte 的高4位 int low = hashValueInt % 16; //byte 的低4位 result += hashValueString[high] + hashValueString[low]; } return result; } public static void byteToNum(byte[] hashValueBytes){ } public static String GetMd5Code(String str) throws Exception { String md5Value = ""; MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashValueBytes = md.digest(str.getBytes()); //返回值为存放hash 值的byte 数组 md5Value = byteToString(hashValueBytes); return md5Value; }}

(3)实验截图

1047360-20180603204722289-1047635995.png

三、实验总结

遇到的问题

在实验2~5点中,使用Socket实现客户端/服务器功能时需要提供服务器端的IP地址,查询资料后了解到有两种查看方式,这里使用了命令行输入指令ipconfig查询IPv4地址。也可以在电脑的“网络和共享中心”→“WLAN连接”→“详细信息”中查询IPv4地址。

法一:

1047360-20180603182518784-1177969425.png

1047360-20180603182451557-2042728370.png

法二:

1047360-20180603182548446-2115140104.png

参考资料

四、PSP时间

实验步骤 耗时 百分比
题目分析 1h 10%
思路设计 2h 20%
代码实现 5h 50%
调试测试 1h 10%
实验总结 1h 10%

转载于:https://www.cnblogs.com/moddy13162201/p/9129209.html

你可能感兴趣的文章
2019-7-27 考试总结
查看>>
easyui的验证
查看>>
进程操作
查看>>
实验6 流类库与I/O
查看>>
OO第四次博客作业
查看>>
chineseChess
查看>>
(转)highcharts详解-直线
查看>>
luogu P2713 罗马游戏
查看>>
DevExpress控件使用小结 z
查看>>
输出、输入 、重定向
查看>>
bzoj 3343: 教主的魔法
查看>>
Play学习 - 体验网页模板
查看>>
iOS des加密
查看>>
openstack-云计算概述
查看>>
javascript的作用域以及闭包现象
查看>>
线程处理
查看>>
DB2日期和时间常用汇总
查看>>
JAVA运算符
查看>>
信号基础知识
查看>>
HTML转义字符大全
查看>>