zoukankan      html  css  js  c++  java
  • 2018-2019-2 20175218 实验五《网络编程与安全》实验报告

    2018-2019-2 20175218 实验五《网络编程与安全》实验报告

    姓名 陈敬勇
    班级 1752
    学号 20175218
    实验序号 实验五
    实验名称 网络编程与安全

    一、网络编程与安全-1

    1、实验要求

    两人一组结对编程:

    1. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
    2. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
    3. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
    4. 上传测试代码运行结果截图和码云链接

    2、实验代码

    (一)MyDC.java>>核心代码

        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(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(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>>核心代码

            try
            {
                Scanner in = new Scanner(System.in);
    
                do
                {
                    MyDC evaluator = new MyDC();
                    System.out.println ("Enter a valid postfix expression: ");
                    expression = in.nextLine();
    
                    result = evaluator.evaluate (expression);
                    System.out.println();System.out.println ("That expression equals " + result);
    
                    System.out.print ("Evaluate another expression [Y/N]? ");
                    again = in.nextLine();
                    System.out.println();
                }
                while (again.equalsIgnoreCase("y"));
            }
    
    

    (三)MyBC.java>>核心代码

            while (t.hasMoreTokens()){    //依次遍历元素,转为后缀表达式
                String temp;
                String c;
                c=t.nextToken();
                if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            sta.push("(");
                            break;
                        }
                        str = str + temp + " ";
                    }
                    sta.push(c);
                } else if (c.equals("*")|| c.equals("÷")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                            sta.push(temp);
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                    sta.push(c);
                } else if (c.equals("(")) {     //遇到“(”直接入栈
                    sta.push(c);
                } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                } else                       //遇到数字,直接存入数组
                {
                    str = str + c + " ";
                }
            }
    
    

    (四)Calculate.java>>核心代码

            MyDC a = new MyDC();
            MyBC b = new MyBC();
            String str;
            int result;
            System.out.println("输入算式:");
            Scanner reader = new Scanner(System.in);
            str = reader.nextLine();
            str = b.result(str);
            result = a.evaluate(str);
            System.out.println("答案为:"+result);
    
    

    3、实验截图

    1、MyDC测试代码截图

    2、Calculate计算代码运行截图

    4、码云链接

    MyDC.java

    MyDCTest.java

    MyBC.java

    Calculate.java

    二、网络编程与安全-2

    1、实验要求

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

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

    2、实验代码

    (一)Server.java(服务器端)>>核心代码

            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 d=new MyDC();
                answer=d.evaluate(s);
                out.writeUTF(answer+"");
                Thread.sleep(500);
            }
    
    

    (二)Client.java(客户端)>>核心代码

            try{  mysocket=new Socket("127.1.0.0",2010);
                in=new DataInputStream(mysocket.getInputStream());
                out=new DataOutputStream(mysocket.getOutputStream());
                System.out.println("请输入算式:");
                Scanner scanner=new Scanner(System.in);
                String str=scanner.nextLine();
                MyBC b=new MyBC();
                str=b.result(str);
                out.writeUTF(str);
                String  s=in.readUTF();   //in读取信息,堵塞状态
                System.out.println("客户收到服务器的回答:"+s);
                Thread.sleep(500);
            }
            catch(Exception e) {
                System.out.println("服务器已断开"+e);
            }
    
    

    (三)MyDC.java>>核心代码

        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(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(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;
        }
    
    

    (四)MyBC.java>>核心代码

            while (t.hasMoreTokens()){    //依次遍历元素,转为后缀表达式
                String temp;
                String c;
                c=t.nextToken();
                if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            sta.push("(");
                            break;
                        }
                        str = str + temp + " ";
                    }
                    sta.push(c);
                } else if (c.equals("*")|| c.equals("÷")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                            sta.push(temp);
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                    sta.push(c);
                } else if (c.equals("(")) {     //遇到“(”直接入栈
                    sta.push(c);
                } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                } else                       //遇到数字,直接存入数组
                {
                    str = str + c + " ";
                }
            }
    
    

    3、实验截图

    (一)服务器端运行

    (二)客户端运行并输入算式

    (三)服务器端收到客户提问

    4、码云链接

    Server.java

    Client.java

    MyDC.java

    MyBC.java

    三、网络编程与安全-3

    1、实验要求

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

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

    2、实验代码

    (一)ServerOne.java(服务器端)>>核心代码

            try{  File f=new File("key1.dat");
                InputStream in = new FileInputStream(f);
                while((n=in.read(a,0,100))!=-1) {
                    key=key+new String (a,0,n);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }*/
            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 key = in.readUTF();
                String s=in.readUTF(); // in读取信息,堵塞状态
                System.out.println("服务器收到的信息:"+s);
                String clear=Encoder.AESDncode(key,s);
                MyDC d=new MyDC();
                System.out.println("服务器收到客户的提问:"+clear);
                int answer=d.evaluate(clear);
                out.writeUTF(answer+"");
                Thread.sleep(500);
            }
    
    

    (二)ClientOne.java(客户端)>>核心代码

            try {
                File f = new File("key1.dat");
                InputStream in = new FileInputStream(f);
                while ((n = in.read(a, 0, 100)) != -1) {
                    key = key + new String(a, 0, n);
                }
                in.close();
            } catch (IOException e) {
                System.out.println("File read Error" + e);
            }
            Socket mysocket;
            DataInputStream in = null;
            DataOutputStream out = null;
            System.out.println("请输入算式:");
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();//输入算式
            MyBC b = new MyBC();
            str = b.result(str);
            String secret=Encoder.AESEncode(key,str);//客户端进行加密
    
            try {
                mysocket = new Socket("127.1.0.0", 2010);
                in = new DataInputStream(mysocket.getInputStream());
                out = new DataOutputStream(mysocket.getOutputStream());
                out.writeUTF(key);
                out.writeUTF(secret);
                String s = in.readUTF();   //in读取信息,堵塞状态
                System.out.println("客户收到服务器的回答:" + s);
                Thread.sleep(500);
            } 
    
    

    (三)Encoder.java(加解密)>>核心代码

    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.ENCRYPT_MODE, key);
                //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
                byte [] byte_encode=content.getBytes("utf-8");
                //9.根据密码器的初始化方式--加密:将数据加密
                byte [] byte_AES=cipher.doFinal(byte_encode);
                //10.将加密后的数据转换为字符串
                //这里用Base64Encoder中会找不到包
                //解决办法:
                //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
                String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
                //11.将字符串返回
                return AES_encode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            //如果有错就返加nulll
            return null;
        }
        /*
         * 解密
         * 解密过程:
         * 1.同加密1-4步
         * 2.将加密后的字符串反纺成byte[]数组
         * 3.将加密内容解密
         */
    
    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.DECRYPT_MODE, key);
                //8.将加密并编码后的内容解码成字节数组
                byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
                /*
                 * 解密
                 */
                byte [] byte_decode=cipher.doFinal(byte_content);
                String AES_decode=new String(byte_decode,"utf-8");
                return AES_decode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
    
    

    (四)Skey_AES.java(AES调用代码)>>核心代码

        public static void main(String args[]) throws Exception{
            KeyGenerator kg=KeyGenerator.getInstance("AES");
            kg.init(128);
            SecretKey k=kg.generateKey( );
            FileOutputStream  f=new FileOutputStream("key1.dat");
            ObjectOutputStream b=new  ObjectOutputStream(f);
            b.writeObject(k);
        }
    
    

    (五)MyBC.java>>核心代码

            while (t.hasMoreTokens()){    //依次遍历元素,转为后缀表达式
                String temp;
                String c;
                c=t.nextToken();
                if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            sta.push("(");
                            break;
                        }
                        str = str + temp + " ";
                    }
                    sta.push(c);
                } else if (c.equals("*")|| c.equals("÷")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                            sta.push(temp);
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                    sta.push(c);
                } else if (c.equals("(")) {     //遇到“(”直接入栈
                    sta.push(c);
                } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                } else                       //遇到数字,直接存入数组
                {
                    str = str + c + " ";
                }
            }
    
    

    (六)MyDC.java>>核心代码

        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(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(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;
        }
    
    

    3、实验截图

    (一)服务器端运行

    (二)客户端运行并输入算式

    (三)服务器端收到客户提问

    4、码云链接

    ServerOne.java

    ClientOne.java

    Encoder.java

    Skey_AES.java

    MyDC.java

    MyBC.java

    四、网络编程与安全-4

    1、实验要求

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

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

    2、实验代码

    (一)Key_DH.java>>核心代码

        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 main(String args[ ]) 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(args[0]);
            ObjectOutputStream b1=new  ObjectOutputStream(f1);
            b1.writeObject(pbk);
            // 保存私钥
            FileOutputStream  f2=new FileOutputStream(args[1]);
            ObjectOutputStream b2=new  ObjectOutputStream(f2);
            b2.writeObject(prk);
        }
    } 
    

    (二)KeyAgree.java>>核心代码

            FileInputStream f1=new FileInputStream("Apub.dat");
            ObjectInputStream b1=new ObjectInputStream(f1);
            PublicKey  pbk=(PublicKey)b1.readObject( );
            //读取自己的DH私钥
            FileInputStream f2=new FileInputStream("Bpri.dat");
            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();
            for(int i=0;i<sb.length;i++){
                System.out.print(sb[i]+",");
            }
    
    

    (三)ServerTwo.java(服务器端)>>核心代码

            try{  File f=new File("Sharekey.dat");
                InputStream in = new FileInputStream(f);
                while((n=in.read(a,0,100))!=-1) {
                    sharekey=sharekey+new String (a,0,n);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
    
            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 keyone =in.readUTF();//读取被DH算法加密的密钥
                String truekey = Encoder.AESDncode(sharekey,keyone);//使用共享密钥对被加密的原密钥解密。
                String secret =in.readUTF(); // in读取信息,堵塞状态
                System.out.println("服务器收到的信息:"+secret);
                String clear = Encoder.AESDncode(truekey,secret);//使用原密钥解密表达式
                MyDC d=new MyDC();
                int answer=d.evaluate(clear);
                out.writeUTF(answer+"");
                System.out.println("服务器提供的解密:"+clear);
    
    
                Thread.sleep(500);
            }
            
    

    (四)ClientTwo.java(客户端)>>核心代码

            try{  File f=new File("key1.dat");
                InputStream in = new FileInputStream(f);
                while((n1=in.read(a1,0,100))!=-1) {
                    key1=key1+new String (a1,0,n1);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
            String sharekey="";
            int n=-1;
            byte [] a=new byte[128];
            try{  File f=new File("Sharekey.dat");
                InputStream in = new FileInputStream(f);
                while((n=in.read(a,0,100))!=-1) {
                    sharekey=sharekey+new String (a,0,n);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
            Socket mysocket;
            DataInputStream in=null;
            DataOutputStream out=null;
            System.out.println("请输入算式:");
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();//输入算式
            MyBC b=new MyBC();
            str=b.result(str);
            String secret=Encoder.AESEncode(key1, str);//客户端对表达式进行加密
            key1 = Encoder.AESEncode(sharekey,key1);//客户端对密钥进行DH加密
            try{  mysocket=new Socket("127.1.0.0",2010);
                in=new DataInputStream(mysocket.getInputStream());
                out=new DataOutputStream(mysocket.getOutputStream());
                out.writeUTF(key1);
                out.writeUTF(secret);
                String  s=in.readUTF();   //in读取信息,堵塞状态
                System.out.println("客户收到服务器的回答:"+s);
                Thread.sleep(50000);
            }
    
    

    (五)MyBC.java>>核心代码

            while (t.hasMoreTokens()){    //依次遍历元素,转为后缀表达式
                String temp;
                String c;
                c=t.nextToken();
                if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            sta.push("(");
                            break;
                        }
                        str = str + temp + " ";
                    }
                    sta.push(c);
                } else if (c.equals("*")|| c.equals("÷")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                            sta.push(temp);
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                    sta.push(c);
                } else if (c.equals("(")) {     //遇到“(”直接入栈
                    sta.push(c);
                } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                } else                       //遇到数字,直接存入数组
                {
                    str = str + c + " ";
                }
            }
    
    

    (六)MyDC.java>>核心代码

        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(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(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;
        }
    
    

    (七)Encoder.java(加解密)>>核心代码

    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.ENCRYPT_MODE, key);
                //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
                byte [] byte_encode=content.getBytes("utf-8");
                //9.根据密码器的初始化方式--加密:将数据加密
                byte [] byte_AES=cipher.doFinal(byte_encode);
                //10.将加密后的数据转换为字符串
                //这里用Base64Encoder中会找不到包
                //解决办法:
                //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
                String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
                //11.将字符串返回
                return AES_encode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            //如果有错就返加nulll
            return null;
        }
        /*
         * 解密
         * 解密过程:
         * 1.同加密1-4步
         * 2.将加密后的字符串反纺成byte[]数组
         * 3.将加密内容解密
         */
    
    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.DECRYPT_MODE, key);
                //8.将加密并编码后的内容解码成字节数组
                byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
                /*
                 * 解密
                 */
                byte [] byte_decode=cipher.doFinal(byte_content);
                String AES_decode=new String(byte_decode,"utf-8");
                return AES_decode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
    
    

    3、实验截图

    (一)服务器端运行

    (二)客户端运行并输入算式

    (三)服务器端收到信息并提供解密

    4、码云链接

    Key_DH.java

    KeyAgree.java

    ServerTwo.java

    ClientTwo.java

    MyDC.java

    MyBC.java

    Encoder.java

    五、网络编程与安全-5

    1、实验要求

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

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

    2、实验代码

    (一)DigestPass.java>>核心代码

            MessageDigest m=MessageDigest.getInstance("MD5");
            m.update(str.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);
    
    

    (二)ServerThree.java(服务器端)>>核心代码

            try{  File f=new File("Sharekey.dat");
                InputStream in = new FileInputStream(f);
                while((n=in.read(a,0,100))!=-1) {
                    sharekey=sharekey+new String (a,0,n);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
    
            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 keyone =in.readUTF();//读取被DH算法加密的密钥
                String truekey = Encoder.AESDncode(sharekey,keyone);//使用共享密钥对被加密的原密钥解密。
                String secret =in.readUTF(); // in读取信息,堵塞状态
                System.out.println("服务器收到的信息:"+secret);
                String mdClient=in.readUTF();
                System.out.println("客户端提供的MD5为:"+ mdClient);
                String clear = Encoder.AESDncode(truekey,secret);//使用原密钥解密表达式
                MyDC d=new MyDC();
                int answer=d.evaluate(clear);
                if((mdClient.equals(DigestPass.MD5(clear)))==true) {//判断MD5值是否相等,若相等,则返回答案
                    System.out.println("MD5值匹配");
                    System.out.println("服务器提供的解密:" + clear);
                    System.out.println("服务器解出密文的MD5为:" + DigestPass.MD5(clear));
                    out.writeUTF(answer + "");
                }
                Thread.sleep(500);
            }
    
    

    (三)ClientThree.java(客户端)>>核心代码

            try{  File f=new File("key1.dat");
                InputStream in = new FileInputStream(f);
                while((n1=in.read(a1,0,100))!=-1) {
                    key1=key1+new String (a1,0,n1);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
            String sharekey="";
            int n=-1;
            byte [] a=new byte[128];
            try{  File f=new File("Sharekey.dat");
                InputStream in = new FileInputStream(f);
                while((n=in.read(a,0,100))!=-1) {
                    sharekey=sharekey+new String (a,0,n);
                }
                in.close();
            }
            catch(IOException e) {
                System.out.println("File read Error"+e);
            }
            Socket mysocket;
            DataInputStream in=null;
            DataOutputStream out=null;
            System.out.println("请输入算式:");
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();//输入算式
            MyBC b=new MyBC();
            str=b.result(str);
            String secret=Encoder.AESEncode(key1, str);//客户端对表达式进行加密
            String md=DigestPass.MD5(str);//客户端提供的MD5
            key1 = Encoder.AESEncode(sharekey,key1);//客户端对密钥进行DH加密
            try{  mysocket=new Socket("127.1.0.0",2010);
                in=new DataInputStream(mysocket.getInputStream());
                out=new DataOutputStream(mysocket.getOutputStream());
                out.writeUTF(key1);
                out.writeUTF(secret);
                out.writeUTF(md);
                String  s=in.readUTF();   //in读取信息,堵塞状态
                System.out.println("客户收到服务器的回答:"+s);
                Thread.sleep(50000);
            }
    
    

    (四)MyBC.java>>核心代码

            while (t.hasMoreTokens()){    //依次遍历元素,转为后缀表达式
                String temp;
                String c;
                c=t.nextToken();
                if (c.equals("+") || c.equals("-")) {   //遇到优先级最低的“+”、“-”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            sta.push("(");
                            break;
                        }
                        str = str + temp + " ";
                    }
                    sta.push(c);
                } else if (c.equals("*")|| c.equals("÷")) {   //遇到优先级高的“*”、“/”,弹出“(”之前的“*”、“/”
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(") || temp.equals("+") || temp.equals("-")) {
                            sta.push(temp);
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                    sta.push(c);
                } else if (c.equals("(")) {     //遇到“(”直接入栈
                    sta.push(c);
                } else if (c.equals(")")) {     //遇到“)”,弹出“(”之前的所有元素
                    while (sta.size() != 0) {
                        temp = sta.pop();
                        if (temp.equals("(")) {
                            break;
                        } else {
                            str = str + temp + " ";
                        }
                    }
                } else                       //遇到数字,直接存入数组
                {
                    str = str + c + " ";
                }
            }
    
    

    (五)MyDC.java>>核心代码

        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(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(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;
        }
    
    

    (六)Encoder.java(加解密)>>核心代码

    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.ENCRYPT_MODE, key);
                //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
                byte [] byte_encode=content.getBytes("utf-8");
                //9.根据密码器的初始化方式--加密:将数据加密
                byte [] byte_AES=cipher.doFinal(byte_encode);
                //10.将加密后的数据转换为字符串
                //这里用Base64Encoder中会找不到包
                //解决办法:
                //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
                String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
                //11.将字符串返回
                return AES_encode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            //如果有错就返加nulll
            return null;
        }
        /*
         * 解密
         * 解密过程:
         * 1.同加密1-4步
         * 2.将加密后的字符串反纺成byte[]数组
         * 3.将加密内容解密
         */
    
    
            try {
                //1.构造密钥生成器,指定为AES算法,不区分大小写
                KeyGenerator keygen=KeyGenerator.getInstance("AES");
                //2.根据ecnodeRules规则初始化密钥生成器
                //生成一个128位的随机源,根据传入的字节数组
                keygen.init(128, new SecureRandom(encodeRules.getBytes()));
                //3.产生原始对称密钥
                SecretKey original_key=keygen.generateKey();
                //4.获得原始对称密钥的字节数组
                byte [] raw=original_key.getEncoded();
                //5.根据字节数组生成AES密钥
                SecretKey key=new SecretKeySpec(raw, "AES");
                //6.根据指定算法AES自成密码器
                Cipher cipher=Cipher.getInstance("AES");
                //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
                cipher.init(Cipher.DECRYPT_MODE, key);
                //8.将加密并编码后的内容解码成字节数组
                byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
                /*
                 * 解密
                 */
                byte [] byte_decode=cipher.doFinal(byte_content);
                String AES_decode=new String(byte_decode,"utf-8");
                return AES_decode;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
    
    

    (七)Key_DH.java>>核心代码

        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 main(String args[ ]) 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(args[0]);
            ObjectOutputStream b1=new  ObjectOutputStream(f1);
            b1.writeObject(pbk);
            // 保存私钥
            FileOutputStream  f2=new FileOutputStream(args[1]);
            ObjectOutputStream b2=new  ObjectOutputStream(f2);
            b2.writeObject(prk);
        }
    } 
    

    (八)KeyAgree.java>>核心代码

            FileInputStream f1=new FileInputStream("Apub.dat");
            ObjectInputStream b1=new ObjectInputStream(f1);
            PublicKey  pbk=(PublicKey)b1.readObject( );
            //读取自己的DH私钥
            FileInputStream f2=new FileInputStream("Bpri.dat");
            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();
            for(int i=0;i<sb.length;i++){
                System.out.print(sb[i]+",");
            }
    
    

    3、实验截图

    (一)服务器端运行

    (二)客户端运行并输入算式

    (三)服务器端收到信息并匹配MD5后解密

    4、码云链接

    DigestPass.java

    ServerThree.java

    ClientThree.java

    Key_DH.java

    KeyAgree.java

    MyDC.java

    MyBC.java

    Encoder.java

    六、实验中遇到的问题及解决方法

    问题一

    在IDEA中,运行代码时,会有找不到一些文件的情况,但是并不影响程序运行

    解决方法

    因为没有影响到程序运行,并且在虚拟机里也能够成功实现,所以就暂时没有解决好这个问题

    七、代码托管

    实验五代码码云链接

    八、实验感想

    对于这次实验,总的来说,综合性比较高,在临近学期末,来做对Java学习很有帮助。特别的是还联系到了其他科目,让我们在学习Java的同时,还兼顾到了其他科目,对我们有着很大的帮助。通过这次实验,我也更加知道了结对编程的重要性,如果这个实验只要我自己一个人做,那么肯定是非常非常困难的,幸好有搭档帮助,这样,最终才完成了这个实验,希望在以后的实验中能够利用好伙伴的力量结伴做出更好的实验。

  • 相关阅读:
    java 获取最近三个月的月初和月末日期
    java 字符串与十六进制互转
    @Validated 参数校验及配置
    mybatis 存取Oracle数据库中Blob类型数据
    Java下载服务器文件到前端
    Java实现Oracle拷贝数据插入到MySQL
    保利、绿地用移动质检3.0管进度、质量,让快周转又快又好!
    未造先知,匠心协同-BIM全过程总咨询实践案例赏析-2021版
    大数据资产管理总体框架概述
    “数据资产全生命周期管理”你要知道的九大问题
  • 原文地址:https://www.cnblogs.com/cjy-123/p/10930760.html
Copyright © 2011-2022 走看看