20202302 《数据结构与面向对象程序设计》实验四报告

课程:《程序设计与数据结构》
班级: 2023
姓名:吉相融
学号:20202302
实验教师:王志强
实验日期:2021年10月22日
必修/选修: 必修

1.实验内容

一)Java Socket编程

1.学习蓝墨云上教材《Java和Android编程》“第16章 输入/输出 ”和“第22章 网络”,学习JavaSocket编程
2.结对编程。结对伙伴A编写客户端SocketClient.java,结对伙伴B编写服务器端。
3.截图加学号水印上传蓝墨云,代码push到码云,并撰写实验报告。

(二)Java和密码学

参考 http://www.cnblogs.com/rocedu/p/6683948.html

以结对的方式完成Java密码学相关内容的学习(帖子中所有代码和相关知识点需要学习)。提交学习成果码云链接和代表性成果截图,要有学号水印。

(三)编写有理数/复数计算器

结对编程,结对伙伴A编写有理数计算器。结对伙伴B编写复数计算器。截图加水印上传蓝墨云,代码push码云。

(四)远程有理数计算器

结对编程,结对伙伴A编程实现客户端,结对伙伴B实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴B(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端A,A收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。

(五)远程复数计算器

结对编程,结对伙伴B编程实现客户端,结对伙伴A实现服务器端。
客户端通过键盘输入一个有理数计算的公式(例如:1/4 + 1/6 = ),并把该公式以字符串的形式发送给伙伴A(服务器端),服务器端根据字符串计算出结果为5/12,并把结果返回给客户端B,B收到结果后输出结果。截图加水印上传蓝墨云,代码push码云。
注意实验四(4)和实验四(5),一个人不能仅实现客户端,必须实现一个客户端和服务器,否则两个实验均不得分!!!

2.实验过程及结果

本次实验我(20202302)与张焘同学(20202329)组队完成

 

实验4.1 Java Socket编程

4.1.1 编写服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {
    public static void main(String[] args) throws IOException
    {
        //建立服务器绑定窗口
        ServerSocket serverSocket = new ServerSocket(8800);
        //accept()方法处理连接请求,防止非法监听
        Socket socket = serverSocket.accept();
        //输入流
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        //输出流
        OutputStream outputStream = socket.getOutputStream();
        PrintWriter printWriter = new PrintWriter(outputStream);
        //读取用户信息
        String info = null;
        System.out.println("服务器正在建立......");
        //反馈信息
        while (!((info = bufferedReader.readLine()) == null ))
        {
            System.out.println("我是服务器Ji,接受的信息为:" + info);
        }
        String reply = "Hello 2023!";
        //传递信息
        printWriter.write(reply);
        printWriter.flush();
        //关闭资源
        inputStream.close();
        outputStream.close();
        bufferedReader.close();
        printWriter.close();
        serverSocket.close();
        socket.close();
    }
}

 

4.1.2 编写客户端(由20202329张焘编写)

import java.io.*  ;
import java.net.Socket ;
public class Client {
    public static void main(String[] args) throws IOException {
        //建立客户端连接
        Socket socket=new Socket("192.168.43.11",8800);
        //输出流,得到socket读写流
        OutputStream outputStream =socket.getOutputStream();
        OutputStreamWriter outputStreamWriter =new OutputStreamWriter(outputStream );
        InputStream inputStream =socket .getInputStream() ;
        BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(inputStream ,"UTF-8") );
        String info="用户名:jxr  密码:20202302";
        outputStreamWriter.write(info);
        outputStreamWriter.flush();
        socket.shutdownOutput() ;
        //接受响应
        String reply=null;
        while(!((reply= bufferedReader.readLine())==null)){
            System.out.println(reply);
        }
        //关闭资源
        bufferedReader .close();
        inputStream.close();
        outputStream .close();
        socket.close();
    }
}

 

 

 

实验4.2 Java和密码学

相关内容:

开发一个程序时,最好的方法就是将对象想象为“服务提供者”,程序通过调用若干对象提供的服务来实现预期目标。

密码学: 主要是研究保密通信和信息保密的学科, 包括信息保密传输和信息加密存储等。

密码编码学: 主要研究如何对信息进行编码, 如何实现对信息的隐蔽, 是密码学理论的基础, 也是保密系统设计的基础。

密码分析学: 主要研究加密消息的破译或消息的伪造, 是检验密码体制安全性最为直接的手段, 只有通过实际密码分析考验的密码体制,才是真正可用的。

对称密码(symmetric cryptography)是指在加密和解密时使用同一密钥的方式。

公钥密码(public-key cryptography)则是指在加密和解密时使用不同密钥的方式,公钥密码又称为非对称密码(asymmetric cryptography)。

4.2.1 凯撒密码

凯撒密码的加密算法极其简单。其加密过程如下:

我们做此约定:明文记为m,密文记为c,加密变换记为E(k1,m)(其中k1为密钥),解密变换记为D(k2,m)(k2为解密密钥)(在这里k1=k2,不妨记为k)。凯撒密码的加密过程可记为如下一个变换:

c≡m+k mod n (其中n为基本字符个数)

同样,解密过程可表示为:
m≡c+k mod n (其中n为基本字符个数)

代码:

public class Caesar {   //凯撒密码加密
    public static void main(String[] args) throws Exception{
           String s = args[0];//取命令行第一个参数,即需要加密的明文
        int key = Integer.parseInt(args[1]); //取命令行参数的第二个字符,即密钥,并将其转为整型//
        String es="";  //创建接收密文的字符串变量并初始化
        for(int i=0;i<s.length();i++)  //逐一对明文字符进行加密
        {
            char c = s.charAt(i);
            if(c>='a' && c<='z')   // 是小写字母
            {
                c+=key%26;  //移动key%26位
                if(c<'a') c+=26;  //向左超界
                if(c>'z') c-=26;  //向右超界
            }
            else if(c>='A' && c<='Z'); //是大写字母
            {
                c+=key%26;
                if(c<'A') c+=26;
                if(c>'Z') c-=26;
            }
            es+=c;
        }
        System.out.println(es);
    }
}

加密:

 

 

 

 解密:

 

 

 

 

 4.2.2 Java对称加密-DES算法

法一:将密钥通过对象序列化方式保存在文件中
import java.io.*;
import javax.crypto.*;
public class Skey_DES{
public static void main(String args[]) throws Exception{
        KeyGenerator kg=KeyGenerator.getInstance("DESede"); 
        kg.init(168);   

        SecretKey k=kg.generateKey( );     
        FileOutputStream f=new FileOutputStream("key1.dat");
      
        ObjectOutputStream b=new ObjectOutputStream(f);
 

        b.writeObject(k);
        //将生成的密钥k序列化后保存在"key1.dat"文件中
        }
        }

 

法二:将密钥以字节保存在文件中
import java.io.*;
import java.security.*;
public class Skey_kb{
    public static void main(String args[]) throws Exception{

        FileInputStream f=new FileInputStream("key1.dat");
        ObjectInputStream b=new ObjectInputStream(f);

        Key k=(Key)b.readObject( );
        //用readObject()读取密钥对象,并传入k中
        //因为readObject()返回的是Object类,所以要强制转换成Key类

        byte[ ] kb=k.getEncoded( );
        //创建一个byte类型的数组kb[],用Key的getEncoded()方法获取密钥编码格式

        FileOutputStream  f2=new FileOutputStream("keykb1.dat");
        f2.write(kb);
        //保存密钥编码格式到"keykb1.dat"文件中

        for(int i=0;i<kb.length;i++){
            System.out.print(kb[i]+",");
            // 打印密钥编码中的内容
        }
    }
}

 编写加密器,生成密文编码和密文文件

 

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

public class SEnc {
    public static void main(String[] args) throws Exception{
    File file;
    FileInputStream f = new FileInputStream("key1.dat");
    ObjectInputStream b = new ObjectInputStream(f);
    Key k = (Key)b.readObject();

    Cipher cp = Cipher.getInstance("DESede");

    cp.init(Cipher.ENCRYPT_MODE,k);

    String s = "Hello 2023";
    byte ptext[] = s.getBytes("UTF8");

    for(int i = 0;i<ptext.length;i++)
    {
        System.out.println(ptext[i]+",");
    }
             System.out.println("");
            byte ctext[] = cp.doFinal(ptext);
            for(int i = 0;i < ctext.length;i++)
            {
                System.out.print(ctext[i] + ",");
            }

            FileOutputStream f2 = new FileOutputStream("SEnc.dat");
            f2.write(ctext);
    }
}

 使用密钥文件解密

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class SDec{
    public static void main(String args[]) throws Exception{

        FileInputStream f=new FileInputStream("SEnc.dat");
        int num=f.available();
        byte[ ] ctext=new byte[num];
        f.read(ctext);

        FileInputStream  f2=new FileInputStream("keykb1.dat");
        int num2=f2.available();
        byte[ ] keykb=new byte[num2];
        f2.read(keykb);
        SecretKeySpec k=new  SecretKeySpec(keykb,"DESede");

        Cipher cp=Cipher.getInstance("DESede");
        cp.init(Cipher.DECRYPT_MODE, k);
        byte []ptext=cp.doFinal(ctext);

        String p=new String(ptext,"UTF8");
        System.out.println(p);
    }
}
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class SDec{
    public static void main(String args[]) throws Exception{

        FileInputStream f=new FileInputStream("SEnc.dat");
        int num=f.available();
        byte[ ] ctext=new byte[num];
        f.read(ctext);

        FileInputStream  f2=new FileInputStream("keykb1.dat");
        int num2=f2.available();
        byte[ ] keykb=new byte[num2];
        f2.read(keykb);
        SecretKeySpec k=new  SecretKeySpec(keykb,"DESede");

        Cipher cp=Cipher.getInstance("DESede");
        cp.init(Cipher.DECRYPT_MODE, k);
        byte []ptext=cp.doFinal(ctext);

        String p=new String(ptext,"UTF8");
        System.out.println(p);
    }
}

 

4.2.3 Java非对称加密-RSA算法

 获取公钥、私钥

 

import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class Skey_RSA{
    //当前目录下将生成两个文件:Skey_RSA_pub.dat和Skey_RSA_priv.dat,前者保存着公钥,后者保存着私钥。
    public static void main(String args[]) throws Exception{
        KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
        //创建密钥对生成器

        kpg.initialize(1024);
        //初始化密钥生成器

        KeyPair kp=kpg.genKeyPair();
        //生成密钥对

        PublicKey pbkey=kp.getPublic();
        PrivateKey prkey=kp.getPrivate();
        //生成公钥和私钥

        FileOutputStream  f1=new FileOutputStream("Skey_RSA_pub.dat");
        ObjectOutputStream b1=new  ObjectOutputStream(f1);
        b1.writeObject(pbkey);
        //保存公钥

        FileOutputStream  f2=new FileOutputStream("Skey_RSA_priv.dat");
        ObjectOutputStream b2=new  ObjectOutputStream(f2);
        b2.writeObject(prkey);
        //保存私钥
    }
}
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class Skey_RSA{
    //当前目录下将生成两个文件:Skey_RSA_pub.dat和Skey_RSA_priv.dat,前者保存着公钥,后者保存着私钥。
    public static void main(String args[]) throws Exception{
        KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
        //创建密钥对生成器

        kpg.initialize(1024);
        //初始化密钥生成器

        KeyPair kp=kpg.genKeyPair();
        //生成密钥对

        PublicKey pbkey=kp.getPublic();
        PrivateKey prkey=kp.getPrivate();
        //生成公钥和私钥

        FileOutputStream  f1=new FileOutputStream("Skey_RSA_pub.dat");
        ObjectOutputStream b1=new  ObjectOutputStream(f1);
        b1.writeObject(pbkey);
        //保存公钥

        FileOutputStream  f2=new FileOutputStream("Skey_RSA_priv.dat");
        ObjectOutputStream b2=new  ObjectOutputStream(f2);
        b2.writeObject(prkey);
        //保存私钥
    }
}

 公钥加密

import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import java.security.interfaces.*;
import java.math.*;
import java.io.*;
public class Enc_RSA{
    public static void main(String args[]) throws Exception{
        String s="Hello World!";

        FileInputStream f=new FileInputStream("Skey_RSA_pub.dat");
        ObjectInputStream b=new ObjectInputStream(f);
        RSAPublicKey  pbk=(RSAPublicKey)b.readObject( );
        BigInteger e=pbk.getPublicExponent();
        BigInteger n=pbk.getModulus();
        System.out.println("e= "+e);
        System.out.println("n= "+n);

        byte ptext[]=s.getBytes("UTF8");
        BigInteger m=new BigInteger(ptext);

        BigInteger c=m.modPow(e,n);
        System.out.println("c= "+c);

        String cs=c.toString( );
        BufferedWriter out=
                new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream("Enc_RSA.dat")));
        out.write(cs,0,cs.length( ));
        out.close( );
    }
}

 

 私钥加密

import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
import java.security.interfaces.*;
import java.math.*;
import java.io.*;
public class Dec_RSA{
    public static void main(String args[]) throws Exception{

        BufferedReader in=
                new BufferedReader(new InputStreamReader(
                        new FileInputStream("Enc_RSA.dat")));
        String ctext=in.readLine();
        BigInteger c=new BigInteger(ctext);
        //读取密文


        FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
        ObjectInputStream b=new ObjectInputStream(f);
        RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );
        BigInteger d=prk.getPrivateExponent();
        //读取私钥

        BigInteger n=prk.getModulus();
        System.out.println("d= "+d);
        System.out.println("n= "+n);
        BigInteger m=c.modPow(d,n);
        //获取私钥参数及解密

        System.out.println("m= "+m);
        byte[] mt=m.toByteArray();
        System.out.println("PlainText is ");
        for(int i=0;i<mt.length;i++){
            System.out.print((char) mt[i]);
        }
        //显示解密结果
    }
}

 4.2.4 使用密钥协定创建共享密钥

建立两个目录A和B,模拟需要秘密通信的A、B双方,由于DH算法需要A和B各自生成DH公钥和私钥,因此在这两个目录下都拷贝编译后文件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
    };



    private static final BigInteger skip1024Modulus
            = new BigInteger(1, skip1024ModulusBytes);
    // The SKIP 1024 bit modulus

    private static final BigInteger skip1024Base = BigInteger.valueOf(2);
    // The base used with the SKIP 1024 bit modulus

    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);
    }
} 
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_B{

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



    private static final BigInteger skip1024Modulus
            = new BigInteger(1, skip1024ModulusBytes);
    // The SKIP 1024 bit modulus

    private static final BigInteger skip1024Base = BigInteger.valueOf(2);
    // The base used with the SKIP 1024 bit modulus

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

 创建共享密钥

需要在AB两个目录下都复制粘贴编译代码

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 Keyagree{
    public static void main(String args[ ]) throws Exception{

        FileInputStream f1=new FileInputStream(args[0]);
        ObjectInputStream b1=new ObjectInputStream(f1);
        PublicKey  pbk=(PublicKey)b1.readObject( );

        FileInputStream f2=new FileInputStream(args[1]);
        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]+",");
        }
        SecretKeySpec k=new  SecretKeySpec(sb,"DESede");
    }
}  

 

将命令行参数修改成“对方的公钥名+自己的私钥名”

 

 

 

打印结果相同,共享成功!!!!!!!

 

 

4.2.5 Java摘要算法- MD5

 

import java.security.*;
public class Digestpass {
    public static void main(String args[]) throws Exception {
        String x = args[0];

        MessageDigest m = MessageDigest.getInstance("MD5");
        //生成对象并指定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);
        }
        System.out.println(result);
    }
}

将参数调整为需要加密的明文

 加密完成!!!!!1

 4.3 编写有理数/复数计算器

4.1.1 20202329张焘的有理数计算器

public class RationalNumberCalculator {
    public static void main(String[] args) {

        fenshu result;
        fenshu fenshu1,fenshu2;
        if(args[0].contains("/")){
            fenshu1=new fenshu(args[0]);
        }
        else{
            fenshu1=new fenshu(args[0]+"/"+1);
        }

        if(args[2].contains("/")){
            fenshu2=new fenshu(args[2]);
        }
        else{
            fenshu2=new fenshu(args[2]+"/"+1);
        }

        char ch=args[1].charAt(0);


        switch (ch)
        {
            case '+':
                result=fenshu1.getJia(fenshu2);
                System.out.println(fenshu1+String.valueOf(ch)+fenshu2+"="+result);
                break;
            case '-':
                result=fenshu1.getJian(fenshu2);
                System.out.println(fenshu1+String.valueOf(ch)+fenshu2+"="+result);
                break;
            case '*':
                result=fenshu1.getCheng(fenshu2);
                System.out.println(fenshu1+String.valueOf(ch)+fenshu2+"="+result);
                break;
            case '/':
                result=fenshu1.getChu(fenshu2);
                System.out.println(fenshu1+String.valueOf(ch)+fenshu2+"="+result);
                break;
            default:
                System.out.println("Illegal input!");
                break;
        }
    }
}
import java.util.StringTokenizer;
public class fenshu {
    int fenzi,fenmu;
    char ch;

    public fenshu(String str) {
        StringTokenizer st=new StringTokenizer(str,"/",true);
        this.fenzi = Integer.parseInt(st.nextToken());
        this.ch=st.nextToken().charAt(0);
        this.fenmu = Integer.parseInt(st.nextToken());
    }

    public fenshu yuefen(int fz,int fm){
        int i;

        for (i=2;i<=fz&&i<=fm;i++){
            if(fz%i==0&&fm%i==0){
                fz=fz/i;
                fm=fm/i;
            }
        }

        fenshu result=new fenshu(fz+"/"+fm);
        return result;
    }

    public fenshu getJia(fenshu x){
        int newFenmu=this.fenmu*x.fenmu;
        int newFenzi=fenzi*x.fenmu+x.fenzi*fenmu;
        return yuefen(newFenzi,newFenmu);
    }

    public fenshu getJian(fenshu x){
        int newFenmu=fenmu*x.fenmu;
        int newFenzi=fenzi*x.fenmu-x.fenzi*fenmu;
        return yuefen(newFenzi,newFenmu);
    }

    public fenshu getCheng(fenshu x){
        int newFenmu=fenmu*x.fenmu;
        int newFenzi=fenzi*x.fenzi;
        return yuefen(newFenzi,newFenmu);
    }

    public fenshu getChu(fenshu x){
        int newFenmu=fenmu*x.fenzi;
        int newFenzi=fenzi*x.fenmu;
        return yuefen(newFenzi,newFenmu);
    }

    @Override
    public String toString() {
        return fenzi + "/" + fenmu;
    }

}

 

 

4.3.2 复数计算器

import java.io.Reader;
import java.util.*;
public class Calculator {
    static double a,b,c,d;
    double RealPart;
    double ImagePart;
    static String choose;
    public static char ch;
    public void Add()
    {
        RealPart = a + c;
        ImagePart = b + d;
    }
    public void Sub()
    {
        RealPart = a - c;
        ImagePart = b - d;
    }
    public void Mul()
    {
        RealPart = a * c - b * d;
        ImagePart = b * c + a * d;
    }
    public void Div()
    {
        RealPart = (a * c - b * d) / (c * c + d * d);
        ImagePart = ( b * c + a * d ) / (c * c + d * d);
    }

    public String toSring(String s){
        if(ImagePart >= 0){
            return s + "=" + RealPart + "+" +ImagePart + "i";
        }
        else {
            return s + "=" + RealPart + "" + ImagePart + "i";
        }
    }
    public void Faction(String f){
        char z;
        StringTokenizer st = new StringTokenizer(f, " ", false);
        z = st.nextToken().charAt(0);
        a = Double.parseDouble(st.nextToken());
        z = st.nextToken().charAt(0);
        b = Double.parseDouble(st.nextToken());
        z = st.nextToken().charAt(0);
        z = st.nextToken().charAt(0);
        ch = st.nextToken().charAt(0);
        z = st.nextToken().charAt(0);
        c = Double.parseDouble(st.nextToken());
        z = st.nextToken().charAt(0);
        d = Double.parseDouble(st.nextToken());


    }
}
import java.util.Scanner;
public class Plural extends Calculator {
    public static void main(String[] args) {
        String next = "y";
        String s;
        do {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入复数计算式,各符号数字间用空格隔开,负数除外(如:( 1 + 2 i ) + ( 2 + -3 i ) ):");
            Calculator ff;
            ff = new Plural();
            s = scan.nextLine();
            ff.Faction(s);

            Calculator count;
            count = new Plural();
            switch (ch) {
                case '+':
                {
                    count.Add();
                    break;
                }
                case '-':
                {
                    count.Sub();
                    break;
                }
                case '*':
                {
                    count.Mul();
                    break;
                }
                case '/':
                {
                    count.Div();
                    break;
                }
                default:
                    System.out.println("Illegal input!");
                    break;
            }
            System.out.println(count.toSring(s));
            System.out.println("如果想要继续计算,请输入y,否则输入任意符号: ");
            choose = scan.nextLine();
        }while (choose.equals(next));
    }
}
import java.util.Scanner;
public class Plural extends Calculator {
    public static void main(String[] args) {
        String next = "y";
        String s;
        do {
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入复数计算式,各符号数字间用空格隔开,负数除外(如:( 1 + 2 i ) + ( 2 + -3 i ) ):");
            Calculator ff;
            ff = new Plural();
            s = scan.nextLine();
            ff.Faction(s);

            Calculator count;
            count = new Plural();
            switch (ch) {
                case '+':
                {
                    count.Add();
                    break;
                }
                case '-':
                {
                    count.Sub();
                    break;
                }
                case '*':
                {
                    count.Mul();
                    break;
                }
                case '/':
                {
                    count.Div();
                    break;
                }
                default:
                    System.out.println("Illegal input!");
                    break;
            }
            System.out.println(count.toSring(s));
            System.out.println("如果想要继续计算,请输入y,否则输入任意符号: ");
            choose = scan.nextLine();
        }while (choose.equals(next));
    }
}

 4.4 远程有理数计算器

20202329张焘客户端

import java.io.*;
import java.net.Socket;

public class Client2Rational {
    public static void main(String[] args) throws IOException {
        //建立客户端连接
        Socket socket = new Socket("192.168.43.11", 2302);
        //输出流,得到socket读写流
        OutputStream outputStream = socket.getOutputStream();
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
        //输入流
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        //对Socket进行读写操作
        String infol = "1/4+1/6";
        String z = infol;
        String test = "";
        int h = 4;
        for (int j = 0; j < z.length(); j++) {
            char k = z.charAt(j);
            if (k > 0 && k <= 127) {
                k += h % 26;
                if (k < 0) k += 127;
                if (k > 127) k -= 127;
            }
            test += k;
        }
        outputStreamWriter.write(test);
        outputStreamWriter.flush();
        socket.shutdownOutput();
        //接受响应
        String reply = null;
        while (!((reply = bufferedReader.readLine()) == null)) {
            System.out.println(reply);
            String s = reply;
            String es = "";
            h = -4;
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if (c >= 0 && c <= 127) {
                    c += h % 26;
                    if (c < 0) c += 127;
                    if (c > 0) c -= 127;
                }
                es += c;
            }
            System.out.println("es");
        }
        //关闭资源
        bufferedReader.close();
        inputStream.close();
        outputStreamWriter.close();
        outputStream.close();
        socket.close();
    }
}

服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
public class Server2 {
    private static fenshu frac2;
    private static fenshu frac1;
    private static String a,b;
    private static char ch;
    private static fenshu result = null;

    public static void main(String[] args) throws IOException {
        //1.建立一个服务器Socket(ServerSocket)绑定指定端口
        ServerSocket serverSocket=new ServerSocket(8808);
        //2.使用accept()方法阻止等待监听,获得新连接
        Socket socket=serverSocket.accept();
        //3.获得输入流
        InputStream inputStream=socket.getInputStream();
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
        //获得输出流
        OutputStream outputStream=socket.getOutputStream();
        PrintWriter printWriter=new PrintWriter(outputStream);
        //4.读取用户输入信息
        String info=null;
        System.out.println("服务器已经建立......");
        while(!((info = bufferedReader.readLine()) ==null)){
            System.out.println("我是服务器,用户的加密信息为:" + info);
            String s= info;
            String es="";
            int key = -4;
            for(int i=0;i<s.length( );i++)
            {  char c=s.charAt(i);
                if(c>=0 && c<=127) // 是小写字母
                { c+=key%26;  //移动key%26位
                    if(c<0) c+=127;  //向左超界
                    if(c>127) c-=127;  //向右超界
                }

                es+=c;
            }

            System.out.println("我是服务器,用户的解密后的信息为:" + es);
            StringTokenizer st = new StringTokenizer(es, " ", false);
            a=st.nextToken();
            ch=st.nextToken().charAt(0);
            b=st.nextToken();
            frac1=new fenshu(a);
            frac2=new fenshu(b);

            switch (ch)
            {
                case '+':
                    result=frac1.getJia(frac2);

                    break;
                case '-':
                    result=frac1.getJian(frac2);

                    break;
                case '*':
                    result=frac1.getCheng(frac2);

                    break;
                case '/':
                    result=frac1.getChu(frac2);

                    break;
                default:

                    break;
            }
        }
        //给客户一个响应
        String reply=frac1+String.valueOf(ch)+frac2+"="+result;
        String z= reply;
        String tes="";
        int key = 4;
        for(int j=0;j<z.length( );j++)
        {  char d=z.charAt(j);
            if(d>=0 && d<=127) // 是小写字母
            { d+=key%26;  //移动key%26位
                if(d<0) d+=127;  //向左超界
                if(d>127) d-=127;  //向右超界
            }

            tes+=d;
        }
        printWriter.write(tes);
        printWriter.flush();
        //5.关闭资源
        printWriter.close();
        outputStream.close();
        bufferedReader.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

我的服务器以及张焘的客户端的运行结果

 

 4.5远程复数计算器

我的客户端

import java.io.*;
import java.net.Socket;

public class Client1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.43.11",8800);
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        OutputStream outputStream = socket.getOutputStream();
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
        String s= "( 1 + 2 i ) + ( 1 + -2 i )";    
        int key=4;        
        String es="";     
        for(int i=0;i<s.length( );i++){   
            char c=s.charAt(i);
            if(c>='a' && c<='z') 
            {
                c+=key%26;  
                if(c<'a') c+=26;  //向左超界
                if(c>'z') c-=26;  //向右超界
            }
            else if(c>='0' && c<='9') // 是数字
            {
                c+=key%10;
                if(c<'0') c+=10;
                if(c>'9') c-=10;
            }
            else if(c>='*' && c<='/')
            {
                c+=key%6;
                if(c<'*') c+=6;
                if(c>'/') c-=6;
            }
            es+=c;
        }

        System.out.println(es);
        String info1 = es;
        outputStreamWriter.write(info1);
        outputStreamWriter.flush();
        socket.shutdownOutput();
        //接受响应
        String reply = null;
        while (!((reply = bufferedReader.readLine())==null)){
            System.out.println(reply);
        }
        bufferedReader.close();
        inputStream.close();
        outputStreamWriter.close();
        outputStream.close();
    }
}
import java.io.*;
import java.net.Socket;

public class Client1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.43.11",8800);
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        OutputStream outputStream = socket.getOutputStream();
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
        String s= "( 1 + 2 i ) + ( 1 + -2 i )";    
        int key=4;        
        String es="";     
        for(int i=0;i<s.length( );i++){   
            char c=s.charAt(i);
            if(c>='a' && c<='z') 
            {
                c+=key%26;  
                if(c<'a') c+=26;  //向左超界
                if(c>'z') c-=26;  //向右超界
            }
            else if(c>='0' && c<='9') // 是数字
            {
                c+=key%10;
                if(c<'0') c+=10;
                if(c>'9') c-=10;
            }
            else if(c>='*' && c<='/')
            {
                c+=key%6;
                if(c<'*') c+=6;
                if(c>'/') c-=6;
            }
            es+=c;
        }

        System.out.println(es);
        String info1 = es;
        outputStreamWriter.write(info1);
        outputStreamWriter.flush();
        socket.shutdownOutput();
        //接受响应
        String reply = null;
        while (!((reply = bufferedReader.readLine())==null)){
            System.out.println(reply);
        }
        bufferedReader.close();
        inputStream.close();
        outputStreamWriter.close();
        outputStream.close();
    }
}

张焘的服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
public class Server2 {
    private static fenshu frac2;
    private static fenshu frac1;
    private static String a,b;
    private static char ch;
    private static fenshu result = null;

    public static void main(String[] args) throws IOException {
        //1.建立一个服务器Socket(ServerSocket)绑定指定端口
        ServerSocket serverSocket=new ServerSocket(8808);
        //2.使用accept()方法阻止等待监听,获得新连接
        Socket socket=serverSocket.accept();
        //3.获得输入流
        InputStream inputStream=socket.getInputStream();
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
        //获得输出流
        OutputStream outputStream=socket.getOutputStream();
        PrintWriter printWriter=new PrintWriter(outputStream);
        //4.读取用户输入信息
        String info=null;
        System.out.println("服务器已经建立......");
        while(!((info = bufferedReader.readLine()) ==null)){
            System.out.println("我是服务器,用户的加密信息为:" + info);
            String s= info;
            String es="";
            int key = -4;
            for(int i=0;i<s.length( );i++)
            {  char c=s.charAt(i);
                if(c>=0 && c<=127) // 是小写字母
                { c+=key%26;  //移动key%26位
                    if(c<0) c+=127;  //向左超界
                    if(c>127) c-=127;  //向右超界
                }

                es+=c;
            }

            System.out.println("我是服务器,用户的解密后的信息为:" + es);
            StringTokenizer st = new StringTokenizer(es, " ", false);
            a=st.nextToken();
            ch=st.nextToken().charAt(0);
            b=st.nextToken();
            frac1=new fenshu(a);
            frac2=new fenshu(b);

            switch (ch)
            {
                case '+':
                    result=frac1.getJia(frac2);

                    break;
                case '-':
                    result=frac1.getJian(frac2);

                    break;
                case '*':
                    result=frac1.getCheng(frac2);

                    break;
                case '/':
                    result=frac1.getChu(frac2);

                    break;
                default:

                    break;
            }
        }
        //给客户一个响应
        String reply=frac1+String.valueOf(ch)+frac2+"="+result;
        String z= reply;
        String tes="";
        int key = 4;
        for(int j=0;j<z.length( );j++)
        {  char d=z.charAt(j);
            if(d>=0 && d<=127) // 是小写字母
            { d+=key%26;  //移动key%26位
                if(d<0) d+=127;  //向左超界
                if(d>127) d-=127;  //向右超界
            }

            tes+=d;
        }
        printWriter.write(tes);
        printWriter.flush();
        //5.关闭资源
        printWriter.close();
        outputStream.close();
        bufferedReader.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
    }
}

运行结果:

张焘的服务器与我的客户端

 

3. 实验过程中遇到的问题和解决过程

1.我的服务器与搭档的客户端无法连接

解决方法:第一步,要先保证两个人连接的是同一个热点,最好使用个人热点(因为后面要关闭防火墙。)

第二步,在设置中将两个人的全部防火墙关闭。

第三步,在网络设置中找到服务器的IP地址,在客户端对应位置输入。先运行服务器,再运行客户端,即可连接成功。

2.服务器与客户端连接成功时会由于解凯撒密码而报错。

此处要保证两个人的凯撒密码加密解密程序要一致,我们两人第一次连接时由于两个人的关于凯撒密码的程序有出入,导致无法正常连接。

4.感悟与思考

这次实验量真的有亿亿亿亿亿亿点点多,尤其是关于密码学相关部分,感觉人都要不对了。不过本次实验有了与搭档的交互,费劲千辛万苦连接成功的那一刻感觉非常开心!

不过本次实验关于密码学的部分还是没能掌握,只是熟悉了一遍相关代码。服务器客户端的建立还有待提升熟练度。

不说了,,,我要奖励自己一下!

 

posted @ 2021-10-24 21:03  20202302吉相融  阅读(16)  评论(0编辑  收藏  举报