zoukankan      html  css  js  c++  java
  • java实验报告(实验五)

    北京电子科技学院(BESTI)

                  

    课程:移动平台开发         班级:1592            

    姓名:苏泽楠

    学号:20159207

    成绩:             指导教师:娄嘉鹏       实验日期:2015.10.22

    实验密级:         预习程度:             实验时间:

    仪器组次:          必修/选修:选修        实验序号:5

    实验名称:Java网络编程及安全                                                           

    实验目的与要求:结对编程,实现客户端和服务器之间数据的发送与接收,实现加解密和验证Hash函数值。

    实验仪器:

    名称

    型号

    数量

    PC

    Lenovo

    1

     

       

    结对伙伴:杨翔http://www.cnblogs.com/20159212yx/

    实验内容

    1.掌握Socket程序的编写;

    2.掌握密码技术的使用;

    3.设计安全

    实验步骤

    1. 发送方A对信息(明文)采用DES密钥加密,使用RSA加密前面的DES密钥信息,最终将混合信息进行传递。同时用hash函数将明文进行用作验证。

        接收方B接收到信息后,用RSA解密DES密钥信息,再用RSA解密获取到的密钥信息解密密文信息,最终就可以得到我们要的信息(明文)。用hash函数对解出的明文进行验证,与发送过来的hash值相等,验证通过。

     

    实验代码

    客户端

    import java.net.*;

    import java.io.*;

    import java.security.*;

    import javax.crypto.*;

    import javax.crypto.spec.*;

    import java.security.spec.*;

    import javax.crypto.interfaces.*;

    import java.security.interfaces.*;

    import java.math.*;

    public class Client {

        public static void main(String args[]) throws Exception{

          try {

                KeyGenerator kg=KeyGenerator.getInstance("DESede");//Java中KeyGenerator类中提供了创建对称密钥的方法;

                kg.init(168); //初始化密钥生成器,指定密钥的长度。        SecretKey k=kg.generateKey( );//生成密钥,使用第一步获得的KeyGenerator类型的对象中generateKey( )方法可以获得密钥。其类型为SecretKey类型,可用于以后的加密和解密。

                byte[] ptext2=k.getEncoded();// 获取主要编码格式,将返回的编码放在byte类型的数组中。

              

                Socket socket = new Socket("192.168.88.1",8080);//创建连接到服务器的8080端口

                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//从服务器端获得输入流

                PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true); //获得向服务器端输出数据的输出

                BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); //从键盘上输入信息

               

                //服务器端RSA的公钥对DES的密钥进行加密

                FileInputStream f3=new FileInputStream("Skey_RSA_pub.dat");//将文件中保存的对象读取出来以便使用

                ObjectInputStream b2=new ObjectInputStream(f3);

                RSAPublicKey  pub_key=(RSAPublicKey)b2.readObject( );//生成公钥

                BigInteger e=pub_key.getPublicExponent();

                BigInteger n=pub_key.getModulus();//模

                System.out.println("e= "+e);

                System.out.println("n= "+n);//(n,e)是公钥

                BigInteger m=new BigInteger(ptext2);

                BigInteger c=m.modPow(e,n);

                System.out.println("c= "+c);

                String cs=c.toString( );

                out.println(cs);  //传送到服务器

               

                System.out.print("请输入待发送的数据:"); 

                String s=stdin.readLine(); //从键盘读入要发送的发信息

                Cipher cp=Cipher.getInstance("DESede");//获取Cipher实例 密码器

                cp.init(Cipher.ENCRYPT_MODE, k);//初始化cipher ENCRYPT_MODE表示加密DECRYPT_MODE解密 , k是密钥

                byte by[]=s.getBytes("UTF8");//获取字符串的utf8字节码

                byte miby[]=cp.doFinal(by);//加密后的字节码

                String str=parseByte2HexStr(miby);//获取密文字符串

                out.println(str);  //传送到服务器

               

                //将客户端的明文哈希值传送给密文

                String x=s;

                MessageDigest m2=MessageDigest.getInstance("MD5");//通过其静态方法getInstance( )生成MessageDigest对象。

                m2.update(x.getBytes( ));//x为需要计算的字符串,用getBytes( )方法生成字符串数组。

                byte ss[ ]=m2.digest( );//计算的结果通过字节类型的数组返回。

                String result="";//将计算结果ss转换为字符串

                for (int i=0; i<ss.length; i++){

                result+=Integer.toHexString((0x000000ff & ss[i]) | 0xffffff00).substring(6);

                }

                System.out.println(result);

                out.println(result);

           

                str=in.readLine();//读取结果

                System.out.println( "从服务器接收到的结果为:"+str);

            }

            catch (Exception e) {

                System.out.println(e);

            }

         }

         

        //将二进制转换成16进制

         public static String parseByte2HexStr(byte buf[]) { 

            StringBuffer sb = new StringBuffer(); 

            for (int i = 0; i < buf.length; i++) { 

                String hex = Integer.toHexString(buf[i] & 0xFF); 

                if (hex.length() == 1) { 

                    hex = '0' + hex; 

                } 

                sb.append(hex.toUpperCase()); 

            } 

            return sb.toString(); 

        } 

       

         //将16进制转换为二进制

        public static byte[] parseHexStr2Byte(String hexStr) { 

            if (hexStr.length() < 1) 

                return null; 

            byte[] result = new byte[hexStr.length()/2]; 

            for (int i = 0;i< hexStr.length()/2; i++) { 

                int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16); 

                int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16); 

                result[i] = (byte) (high * 16 + low); 

            } 

            return result; 

        } 

    }

    服务器端

    import java.net.*;
    import java.io.*;
    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.*;

    public class ComputeTCPServer {
    public static void main(String srgs[]) {
    ServerSocket sc = null;
    Socket socket = null;
    try {
    sc = new ServerSocket(4421);// 创建服务器套接字
    System.out.println("端口号:" + sc.getLocalPort());
    System.out.println("服务器已经启动...");
    socket = sc.accept(); // 等待客户端连接
    System.out.println("已经建立连接");
    // 获得网络输入流对象的引用
    BufferedReader in = new BufferedReader(new InputStreamReader(
    socket.getInputStream()));
    // //获得网络输出流对象的引用
    PrintWriter out = new PrintWriter(new BufferedWriter(
    new OutputStreamWriter(socket.getOutputStream())), true);

    // 使用服务器端RSA的私钥对DES的密钥进行解密

    String line = in.readLine(); // 读取客户端传送来的数据

    BigInteger cipher = new BigInteger(line);

    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();// mod n

    BigInteger m = cipher.modPow(d, n);// m=d (mod n)

    System.out.println("d= " + d);

    System.out.println("n= " + n);

    System.out.println("m= " + m);

    byte[] keykb = m.toByteArray();

    // 使用DES对密文进行解密

    String readline = in.readLine();// 读取客户端传送来的数据

    FileInputStream f2 = new FileInputStream("keykb1.dat");

    int num2 = f2.available();

    byte[] ctext = parseHexStr2Byte(readline);

    Key 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); // 打印解密结果

    // 使用Hash函数检测明文完整性

    String aline3 = in.readLine();

    String x = p;

    MessageDigest m2 = MessageDigest.getInstance("MD5");// 使用MD5算法返回实现指定摘要算法的
    // MessageDigest对象

    m2.update(x.getBytes());

    byte a[] = m2.digest();

    String result = "";

    for (int i = 0; i < a.length; i++) {

    result += Integer.toHexString((0x000000ff & a[i]) | 0xffffff00)
    .substring(6);

    }

    System.out.println(result);

    if (aline3.equals(result)) {

    System.out.println("匹配成功");

    }

    out.println("匹配成功");

    out.close();

    in.close();

    ServerSocket link = null;
    link.close();

    } catch (Exception e) {

    System.out.println(e);

    }
    }

    public static String parseByte2HexStr(byte buf[]) {

    StringBuffer sb = new StringBuffer();

    for (int i = 0; i < buf.length; i++) {

    String hex = Integer.toHexString(buf[i] & 0xFF);

    if (hex.length() == 1) {

    hex = '0' + hex;

    }

    sb.append(hex.toUpperCase());// 将字符串中的小写字母转换成大写字母,然后加在字符串上

    }

    return sb.toString();

    }

    // 将十六进制转换为二进制

    public static byte[] parseHexStr2Byte(String hexStr) {

    if (hexStr.length() < 1)

    return null;

    byte[] result = new byte[hexStr.length() / 2];

    for (int i = 0; i < hexStr.length() / 2; i++) {

    int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);

    int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
    16);

    result[i] = (byte) (high * 16 + low);

    }

    return result;

    }
     }

    截图如下:

    实验总结

    我在实验中遇到如下问题:

    服务器端已经启动,但连客户端的时候抛出异常,经过调试发现是端口的问题,端口不可以复用,最后用两台电脑做了出来。

  • 相关阅读:
    C# 操作配置文件
    C# Excel操作类
    没有找到 mspdb100.dll 的解决办法
    工厂方法模式
    .Net互操作2
    The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决
    手机抓包xcode自带命令行工具配合wireshark实现
    expecting SSH2_MSG_KEX_ECDH_REPLY ssh_dispatch_run_fatal问题解决
    使用ssh-keygen设置ssh无密码登录
    远程复制文件到服务器
  • 原文地址:https://www.cnblogs.com/20159207szn/p/4909249.html
Copyright © 2011-2022 走看看