zoukankan      html  css  js  c++  java
  • 实验五 网络编程与安全


    课程:Java程序设计 班级:1752班 姓名:李得琛 学号:20175206
    指导教师:娄嘉鹏
    实验日期:2019年5月29日
    实验序号:实验五
    实验名称:网络编程与安全

    实验五 网络编程与安全-1

    两人一组结对编程:
    0. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA

    1. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
    2. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
    3. 上传测试代码运行结果截图和码云链接

    实验步骤

    栈 (Stack)是一种只允许在表尾插入和删除的线性表,有先进后出(FILO),后进先出(LIFO)的特点。允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom)
    OP + S1 + S2 为前缀表示法
    S1 + OP + S2 为中缀表示法
    S1 + S2 + OP 为后缀表示法
    在这里面我们主要讨论中缀转后缀
    部分中转后代码:

    public String ChangeOrder() {
            Stack store = new Stack();     //创建一个存储字符的栈
            for (int i = 0; i < C.length(); i++) {
                char op = C.charAt(i);     //将索引值为i处的字符的值返回
                if (op >= '0' && op <= '9') {
                    End = End + op;
                } else if (op == '(') {
                    store.push(op);
                } else if (op == '+' || op == '-' || op == '*' || op == '÷'|| op == '/') {
                    End = End + " ";
                    if (store.empty()) {
                        store.push(op);
                    } else if (compareValue(op) > compareValue((char) store.peek()))    //比较运算符优先级
                    {
                        store.push(op);
                    } else {
                        End = End + String.valueOf(store.pop());
                        i--;
                    }
                } else if (op == ')') {
                    while ((char) store.peek() != '(') {
                        End = End + " " + String.valueOf(store.pop());
                    }
                    store.pop();
                }
            }
            while (!store.empty()) {
                End = End + " " + String.valueOf(store.pop());
            }
            return End;
        }
    

    计算器运算:

    public class action {
        int numerator = 1 ;   //分子
        int denominator = 1; //分母
        void setNumerator(int a) {  //设置分子
            int c=f(Math.abs(a),denominator);  //计算最大公约数
            numerator = a/c;
            denominator = denominator/c;
            if(numerator<0&&denominator<0) {
                numerator = -numerator;
                denominator = -denominator;
            }
        }
        void setDenominator(int b) {  //设置分母
            int c=f(numerator,Math.abs(b));  //计算最大公约数
            numerator = numerator/c;
            denominator = b/c;
            if(numerator<0&&denominator<0) {
                numerator = -numerator;
                denominator = -denominator;
            }
        }
        int getNumerator() {
            return numerator;
        }
        int getDenominator() {
            return denominator;
        }
        int f(int a,int b) { //求a和b的最大公约数
            if(a==0) {
                return 1;
            }
            if(a<b) {
                int c=a;
                a=b;
                b=c;
            }
            int r=a%b;
            while(r!=0) {
                a=b;
                b=r;
                r=a%b;
            }
            return b;
        }
        action add(action r) {  //加法运算
            int a=r.getNumerator();
            int b=r.getDenominator();
            int newNumerator=numerator*b+denominator*a; //计算出新分子
            int newDenominator=denominator*b;           //计算出新分母
            action result=new action();
            result.setNumerator(newNumerator);
            result.setDenominator(newDenominator);
            return result;
        }
        action sub(action r) {  //减法运算
            int a=r.getNumerator();
            int b=r.getDenominator();
            int newNumerator=numerator*b-denominator*a;
            int newDenominator=denominator*b;
            action result=new action();
            result.setNumerator(newNumerator);
            result.setDenominator(newDenominator);
            return result;
        }
        action muti(action r) { //乘法运算
            int a=r.getNumerator();
            int b=r.getDenominator();
            int newNumerator=numerator*a;
            int newDenominator=denominator*b;
            action result=new action();
            result.setNumerator(newNumerator);
            result.setDenominator(newDenominator);
            return result;
        }
        action div(action r)  { //除法运算
            int a=r.getNumerator();
            int b=r.getDenominator();
            int newNumerator=numerator*b;
            int newDenominator=denominator*a;
            action result=new action();
            if(a==0) {
                System.out.println("该算式无解");
                result.setNumerator(0);
            }
            else {
                result.setNumerator(newNumerator);
                result.setDenominator(newDenominator);
            }
            return result;
        }
    }
    
    

    后缀调用:

    import java.util.StringTokenizer;
    import java.util.Stack;
    
    public class MyDC {
        String q;
        Stack stack;
    
        public MyDC() {
            stack = new Stack();
        }
    
        void set(String question) {   //输入后续排列的字符串
            q = question;
        }
    
    
        public action get() {
            action op1 = new action();
            action op2 = new action();
            action result = new action();
            result.setNumerator(0);
            StringTokenizer token = new StringTokenizer(q, " ");
            String temp;
            while (token.hasMoreTokens()) {
                temp = token.nextToken();
                if (Isop(temp) == 1)//遇到操作符,弹出栈顶的两个数进行运算
                {
                    op2 = (action) stack.pop();
                    op1 = (action) stack.pop();//弹出最上面两个操作数
                    result = cal(temp.charAt(0), op1, op2);//根据运算符进行运算
                    stack.push(result);//将计算结果压栈
                } else {
                    action num = new action();
                    num.setNumerator(Integer.parseInt(temp));
                    stack.push(num);//操作数入栈
                }
            }
            return result;
        }
    
        action cal(char op, action a, action b) {           //对栈顶弹出的两个数进行运算
            action c = new action();
            switch (op) {
                case '+':
                    c = a.add(b);
                    break;
                case '-':
                    c = a.sub(b);
                    break;
                case '*':
                    c = a.muti(b);
                    break;
                case '÷':
                case '/':
                    if(b.getNumerator()==0) {
                        System.out.println("生成的算式计算时出现了分母为0的情况!");
                        System.exit(0);
                    }
                    else {
                        c = a.div(b);
                        break;
                    }
                default:
                    System.out.println("Wrong!");
            }
            return c;
        }
    
        int Isop(String op) {       //判断是不是运算符
            if (op.equals("+") || op.equals("-") || op.equals("*") || op.equals("÷") || op.equals("/")) {
                return 1;
            } else {
                return 0;
            }
        }
    }
    

    测试程序BCTEST.java

    import java.util.*;
    
    public class BCTEST {
        public static void main(String[] args) {
            String question = "";
            String question1 = "";
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入题目:");
            question = scanner.nextLine();
            MyBC change = new MyBC();
            change.ChangeString(question);
            question1 = change.ChangeOrder();
            System.out.println(question1);
            MyDC getanswer = new MyDC();
            getanswer.set(question1);
            action answer = getanswer.get();
            int a = answer.getNumerator();
            int b = answer.getDenominator();
            float result = (float)a/b;
            System.out.println("结果为(保留两位小数):");
            System.out.println(String.format("%.2f",result));
        }
    }
    

    实验截图

    后缀:

    中转后:

    中转后带括号:

    实验五 网络编程与安全-2

    结对编程:1人负责客户端,一人负责服务器
    0. 注意责任归宿,要会通过测试证明自己没有问题!

    1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
    3. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    4. 客户端显示服务器发送过来的结果
    5. 上传测试结果截图和码云链接

    实验步骤

    在这里面先建立客户端和服务器之间的连接,鉴于是一台电脑同做服务器与客户端,那么IP地址填写本机客户端即可,否则将填写所在用户机IP地址

    首先需要查明IP地址,本次用于作为客户端IP地址为192.168.1.239,如下面截图所示

    因需要实现Java Socket的功能,我们使用命令mysocket = new Socket();来输入客户端IP以及其接口

    客户端调用中转后mybc,服务器调用mydc

    传输数据后即可看到结果,先启动服务器,在启动客户端。

    代码部分如下:

    调用部分:

      try {
                socketOnServer = serverForClient.accept();
                out = new DataOutputStream(socketOnServer.getOutputStream());
                in = new DataInputStream(socketOnServer.getInputStream());
                while(true) {
                    question = in.readUTF(); // in读取信息,堵塞状态
                    System.out.println("服务器收到客户传递的后缀表达式为:" + question);
                    MyDC getanswer = new MyDC();
                    getanswer.set(question);
                    action answer = getanswer.get();
                    int a = answer.getNumerator();
                    int b = answer.getDenominator();
                    float result = (float) a / b;
                    System.out.println("计算出的结果为"+String.format("%.2f",result));
                    out.writeUTF(String.format("%.2f",result));
                    Thread.sleep(500);
                }
            } 
    

    传输部分:

      String IP = scanner.nextLine();
                InetAddress  address=InetAddress.getByName(IP);
                mysocket = new Socket(address, 2010);
                in=new DataInputStream(mysocket.getInputStream());
                out=new DataOutputStream(mysocket.getOutputStream());
    

    实验截图

    查询IP:

    服务器:

    客户端:

    实验五 网络编程与安全-3

    加密结对编程:1人负责客户端,一人负责服务器
    0. 注意责任归宿,要会通过测试证明自己没有问题

    1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
    3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    4. 客户端显示服务器发送过来的结果
    5. 上传测试结果截图和码云链接

    实验步骤

    继承上述步骤,将输入的表达式进行加密传输 ,双方均可看到密钥及数据,本次使用DES进行加密

    调用DES加密进行处理

    DES加密格式代码:

     SecretKeySpec k = new SecretKeySpec(kb, "DESede");
                    Cipher cp = Cipher.getInstance("DESede");
                    cp.init(Cipher.DECRYPT_MODE, k);
                    String clength = in.readUTF();
                    byte ctext[] = new byte[Integer.parseInt(clength)];
                    for (int i = 0;i<Integer.parseInt(clength);i++) {
                        String temp = in.readUTF();
                        ctext[i] = Byte.parseByte(temp);
    

    即可看到结果

    实验截图

    服务器:

    客户端:

    实验五 网络编程与安全-4

    密钥分发结对编程:1人负责客户端,一人负责服务器
    0. 注意责任归宿,要会通过测试证明自己没有问题

    1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
    3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
    4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    5. 客户端显示服务器发送过来的结果
    6. 上传测试结果截图和码云链接

    实验步骤

    继承实验三,使用DH算法将DES算法的密钥进行交换,服务器收到后解密,调用后缀进行计算,把结果返回客户端

    在这里使用了DH算法

    DH算法

    1、初始化发送方的密钥
    2、初始化接受方的密钥
    3、密钥构建
    4、加密和解密
    
    

    DH代码:

    (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
    

    生成一系列的dat文件在这里是一堆乱码,就不在这里表达了。

    实验截图

    服务器:

    客户端:

    实验五 网络编程与安全-5

    完整性校验结对编程:1人负责客户端,一人负责服务器
    0. 注意责任归宿,要会通过测试证明自己没有问题

    1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
    2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
    3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
    4. 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
    5. 客户端显示服务器发送过来的结果
    6. 上传测试结果截图和码云链接

    实验步骤

    MD5:

    MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
    
    MD5算法具有以下特点:
    
    压缩性:任意长度的数据,算出的MD5值长度都是固定的。
    容易计算:从原数据计算出MD5值很容易。
    抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
    强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
    
    

    使用MD5对DES进行加解密的过程,与DH过程类似

    MD5代码:

    public class MD5{
        public static String MD5(String str) throws Exception{
            String x=str;
            MessageDigest m=MessageDigest.getInstance("MD5");
            m.update(x.getBytes("UTF8"));
            byte s[ ]=m.digest( );
            String result="";
            for (int i=0; i<s.length; i++){
                result+=Integer.toHexString((0x000000ff & s[i]) |
                        0xffffff00).substring(6);
            }
            return result;
        }
    }
    

    实验截图

    服务器:

    客户端:

    .

    参考资料

    数据结构应用

    java密码学算法

    代码链接

    20175206李得琛

    总结分析

    步骤 耗时 百分比
    需求分析 10min 12.5%
    设计 15min 18.75%
    代码实现 30min 37.5%
    测试 5min 6.25%
    分析总结 20min 25%
  • 相关阅读:
    华为手机内核代码的编译及刷入教程【通过魔改华为P9 Android Kernel 对抗反调试机制】
    AndroidStudio升级到4.0之后,出现Warning: Default Activity not found解决办法
    Python解决gensim加载doc2vec或work2vec向量训练模型文件太慢甚至无法访问的情况
    layui 上传插件控制上传文件个数(换个角度思考问题)
    CDN访问异常重定向
    sql 语句优化
    swipper全屏垂直滚动获取高度问题
    tp6.0相对于tp5.1的变化
    项目打包文件ipa包瘦身
    load和initialize的区别
  • 原文地址:https://www.cnblogs.com/ldc175206/p/10922026.html
Copyright © 2011-2022 走看看