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

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

    实验要求

    • 完成云班课中的检查点,也可以先完成实验报告,直接提交。注意不能只有截图,要有知识点,原理,遇到的问题和解决过程等说明。
    • 实验报告中一个检查点要有多张截图。发表实验报告博客,标题“学期(如2018-2019-2) 学号(如20175300) 实验五《网络编程与安全》实验报告”

    实验步骤

    实验一
    实验要求

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

    实验代码:

    (1)MyDC.java代码

    import java.util.*;
    
    public class MyDC {
        private final char ADD = '+';
        private final char SUBTRACT = '-';
        private final char MUTIPLY = '*';
        private final char DIVIDE = '/';
        private Stack<Integer> stack;
    
        public MyDC() {
            stack = new Stack<Integer>();
        }
    
        public int evaluate(String 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;
        }
    }
    

    (2)MyBC.java代码

    import java.util.*;
    public class MyBC {
        public static String infixToSuffix(String infix) {
            return null;
        }
    
        public String result(String s) {
            Stack<String> sta = new Stack<String>();   //新建栈
            String str = "";
            StringTokenizer t=new StringTokenizer(s);
            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 + " ";
                }
            }
            while (sta.size()!=0){     //弹出栈中剩余的元素
                str=str+sta.pop()+" ";
            }
            return str;
        }
    }
    

    (3)MyDCTest.java代码

    import java.util.Scanner;
    
    public class MyDCTest  {
    
        public static void main (String[] args) {
    
            String expression, again;
    
            int result;
    
            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"));
            }
            catch (Exception IOException)
            {
                System.out.println("Input exception reported");
            }
        }
    }
    
    实验结果

    实验二
    实验要求

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

    实验代码:

    (1)Server.java代码

    import java.io.*;
    import java.net.*;
    public class Server {
        public static void main(String args[]) {
            int answer;
            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 d=new MyDC();
                answer=d.evaluate(s);
                String s1=String.valueOf(answer);
                out.writeUTF(s1);
                Thread.sleep(500);
            }
            catch(Exception e) {
                System.out.println("客户已断开"+e);
            }
        }
    }
    

    (2)Client.java代码

    import java.io.*;
    import java.net.*;
    import java.lang.*;
    import java.util.Scanner;
    
    public class Client {
        public static void main(String args[]) {
            Socket mysocket;
            DataInputStream in=null;
            DataOutputStream out=null;
            try{  mysocket=new Socket("192.168.1.110",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);
            }
        }
    }
    
    实验结果


    实验三
    实验要求

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

    实验代码

    (1)Client2.java代码

    import java.io.*;
    import java.net.*;
    import java.lang.*;
    import java.util.Scanner;
    
    public class Client2 {
        public static void main(String args[]) throws Exception {
            String key = "";
            int n = -1;
            byte[] a = new byte[128];
    
            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);
            } catch (Exception e) {
                System.out.println("服务器已断开" + e);
            }
        }
    }
    

    (2)Server2.java代码

    import java.io.*;
    import java.net.*;
    import java.security.Key;
    
    public class Server2 {
        public static void main (String args[]) throws Exception {
            /*String key="";
            int n=-1;
            byte [] a=new byte[128];
            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读取信息,堵塞状态
                FileInputStream f=new FileInputStream("key1.dat");
                ObjectInputStream b=new ObjectInputStream(f);
                Key k=(Key)b.readObject( );
                byte[ ] kb=k.getEncoded( );
                FileOutputStream  f2=new FileOutputStream("keykb1.dat");
                f2.write(kb);
                // 打印密钥编码中的内容
                for(int i=0;i<kb.length;i++){
                    System.out.print(kb[i]+",");
                }
                System.out.println();
                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);
            }
            catch(Exception e) {
                System.out.println("客户已断开"+e);
            }
        }
    }
    

    (3)Encoder.java代码(加解密代码)

    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    /*
     * AES对称加密和解密
     */
    public class Encoder {
        /*
         * 加密
         * 1.构造密钥生成器
         * 2.根据ecnodeRules规则初始化密钥生成器
         * 3.产生密钥
         * 4.创建和初始化密码器
         * 5.内容加密
         * 6.返回字符串
         */
        public static String AESEncode(String encodeRules,String content){
            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.将加密内容解密
         */
        public static String AESDncode(String encodeRules,String content){
            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();
            }
    
            //如果有错就返加nulll
            return null;
        }
    
    }
    
    

    (4)Skey_AES.java代码

    import java.io.*;
    import javax.crypto.*;
    public class Skey_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);
        }
    }
    
    实验结果


    实验四
    实验要求

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

    实验代码

    (1)Key_DH代码

    import java.io.*;
    import java.math.*;
    import java.security.*;
    import java.security.spec.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;
    import javax.crypto.interfaces.*;
    
    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 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("Serverpub.dat");
            ObjectOutputStream b1=new  ObjectOutputStream(f1);
            b1.writeObject(pbk);
            FileOutputStream  f2=new FileOutputStream("Clientpub.dat");
            ObjectOutputStream b2=new  ObjectOutputStream(f2);
            b2.writeObject(pbk);
            // 保存私钥
            FileOutputStream  f3=new FileOutputStream("Clientpri.dat");
            ObjectOutputStream b3=new  ObjectOutputStream(f3);
            b3.writeObject(prk);
            FileOutputStream  f4=new FileOutputStream("Serverpri.dat");
            ObjectOutputStream b4=new  ObjectOutputStream(f4);
            b4.writeObject(prk);
        }
    }
    
    

    (2)KeyAgree代码

    import java.io.*;
    import java.security.*;
    import javax.crypto.*;
    import javax.crypto.spec.*;
    
    public class KeyAgree{
        public KeyAgree(){}
        public static SecretKeySpec KeyAgree(String a,String b) throws Exception{
            // 读取对方的DH公钥
            FileInputStream f1=new FileInputStream(a);
            ObjectInputStream b1=new ObjectInputStream(f1);
            PublicKey  pbk=(PublicKey)b1.readObject( );
    //读取自己的DH私钥
            FileInputStream f2=new FileInputStream(b);
            ObjectInputStream b2=new ObjectInputStream(f2);
            PrivateKey  prk=(PrivateKey)b2.readObject( );
            // 执行密钥协定
            KeyAgreement ka=KeyAgreement.getInstance("DH");
            ka.init(prk);
            ka.doPhase(pbk,true);
            //生成共享信息
            byte[ ] s=ka.generateSecret();
            byte []sb = new byte[24];
            System.arraycopy(s, 0, sb, 0, 24);
            System.out.println("共享秘钥:");
            for(int i=0;i<sb.length;i++){
                System.out.print(sb[i]+" ");
            }
            System.out.println();
            SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
            return k;
        }
    }
    

    (3)Server3代码(服务端)

    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import java.io.*;
    import java.net.*;
    public class Server3 {
        public static void main(String[] args) {
            ServerSocket serverForClient = null;
            Socket socketOnServer = null;
            DataOutputStream out = null;
            DataInputStream in = null;
            MyDC myDC = new MyDC();
            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 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);
                }
                //获取密钥
                String keylength = in.readUTF();
                byte []ckey = new byte[Integer.parseInt(keylength)];
                for(int i=0; i<Integer.parseInt(keylength); i++){
                    String temp = in.readUTF();
                    ckey[i] = Byte.parseByte(temp);
                }
                //密钥解密
                SecretKeySpec k1 = KeyAgree.KeyAgree("Clientpub.dat","Serverpri.dat");
                Cipher cp=Cipher.getInstance("DESede");
                cp.init(Cipher.DECRYPT_MODE, k1);
                byte []pkey=cp.doFinal(ckey);
                //密文解密
                SecretKeySpec k=new  SecretKeySpec(pkey,"DESede");
                cp.init(Cipher.DECRYPT_MODE, k);
                byte []ptext=cp.doFinal(ctext);
                String suffix = new String(ptext,"UTF8");
                System.out.println("服务器提供的解密"+suffix);
                out.writeUTF(myDC.evaluate(suffix)+"");
                Thread.sleep(500);
            }catch (Exception e){
                System.out.println("客户已断开");
            }
        }
    }
    

    (4)Client3代码(客户端)

    import javax.crypto.spec.*;
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class Client3 {
        public static void main(String[] args) {
            Scanner inn = new Scanner(System.in);
            Socket mysocket;
            DataInputStream in = null;
            DataOutputStream out = null;
            try {
                mysocket = new Socket("127.1.0.0", 2010);
                in = new DataInputStream(mysocket.getInputStream());
                out = new DataOutputStream(mysocket.getOutputStream());
                KeyGenerator kg = KeyGenerator.getInstance("DESede");
                kg.init(168);
                SecretKey k = kg.generateKey();
                byte[] kb = k.getEncoded();
                System.out.println("请输入中缀表达式:");
                String infix = inn.nextLine();
                MyBC myBC1 = new MyBC();
                String suffix = MyBC.infixToSuffix(infix);
                System.out.println(suffix);
                //中缀表达式加密
                Cipher cp = Cipher.getInstance("DESede");
                cp.init(Cipher.ENCRYPT_MODE, k);
                byte ptext[] = suffix.getBytes("UTF8");
                byte ctext[] = cp.doFinal(ptext);
                out.writeUTF(ctext.length + "");
                for (int i = 0; i < ctext.length; i++) {
                    out.writeUTF(ctext[i] + "");
                }
                //对密钥进行加密
                KeyAgree keyAgree = new KeyAgree();
                SecretKeySpec k1 = keyAgree.KeyAgree("Serverpub.dat","Clientpri.dat");
                cp.init(Cipher.ENCRYPT_MODE, k1);
                byte ckey[] = cp.doFinal(kb);
                out.writeUTF(ckey.length + "");
                for (int i = 0; i < ckey.length; i++) {
                    out.writeUTF(ckey[i] + "");
                }
                String result = in.readUTF();
                System.out.println("收到客户回答" + result);
                Thread.sleep(500);
            } catch (Exception e) {
                System.out.println("服务器已断开" + e);
            }
        }
    }
    
    实验结果


    这个实验存在一些问题还没有完全弄懂,没有办法将密钥存入文件中在运行时再读入,其中给出的文件也没有办法生成。

    实验五
    实验要求

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

    实验代码

    (1)DigestPass代码

    import java.security.*;
    public class DigestPass{
        static String MD5(String str) throws Exception{
            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);
            }
            return result;
        }
    }
    

    (2)Server4代码(服务端)

    import java.io.*;
    import java.net.*;
    public class Server4 {
        public static void main(String args[]) throws  IOException{
            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);
            }
    
            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);
            }
            catch(Exception e) {
                System.out.println("客户已断开"+e);
            }
        }
    }
    

    (3)Client4代码(客户端)

    import java.io.*;
    import java.net.*;
    import java.util.Scanner;
    
    public class Client4 {
        public static void main(String args[]) throws Exception {
            String key1="";
            int n1=-1;
            byte [] a1=new byte[128];
            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);
            }
            catch(Exception e) {
                System.out.println("服务器已断开"+e);
            }
        }
    }
    
    实验结果


  • 相关阅读:
    1144 The Missing Number (20分)
    1145 Hashing
    1146 Topological Order (25分)
    1147 Heaps (30分)
    1148 Werewolf
    1149 Dangerous Goods Packaging (25分)
    TypeReference
    Supervisor安装与配置()二
    谷粒商城ES调用(十九)
    Found interface org.elasticsearch.common.bytes.BytesReference, but class was expected
  • 原文地址:https://www.cnblogs.com/hujidong42/p/10953370.html
Copyright © 2011-2022 走看看