实验五 Java网络编程

实验五 Java网络编程

实验五所涉及的密码学算法及编程思路

## Java对称加密-DES算法

(1) 获取密钥生成器

KeyGenerator kg=KeyGenerator.getInstance("DESede");

(2) 初始化密钥生成器

kg.init(168);

(3) 生成密钥

SecretKey k=kg.generateKey( );

(4) 通过对象序列化方式将密钥保存在文件中

FileOutputStream f=new FileOutputStream("key1.dat");

ObjectOutputStream b=new ObjectOutputStream(f);

b.writeObject(k);

-解密阶段

(1) 获取密文

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

2) 获取密钥

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

(3) 创建密码器(Cipher对象)

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

(4) 初始化密码器

cp.init(Cipher.DECRYPT_MODE, k);

(5) 执行解密

byte []ptext=cp.doFinal(ctext);

非对称加密-RSA算法

(1) 创建密钥对生成器

KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");

(2) 初始化密钥生成器

kpg.initialize(1024);

(3) 生成密钥对

KeyPair kp=kpg.genKeyPair( );

(4) 获取公钥和私钥

PublicKey pbkey=kp.getPublic( );

PrivateKey prkey=kp.getPrivate( );

-加密过程

(1) 获取公钥

  1. FileInputStream f=new FileInputStream("Skey_RSA_pub.dat");
  2. ObjectInputStream b=new ObjectInputStream(f);
  3. RSAPublicKey pbk=(RSAPublicKey)b.readObject( );

(2) 获取公钥的参数(e, n)

BigInteger e=pbk.getPublicExponent();

BigInteger n=pbk.getModulus();

(3) 获取明文整数(m)

String s="Hello World!";

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

BigInteger m=new BigInteger(ptext);

(4) 执行计算

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

-解密过程

(1) 读取密文

  1. BufferedReader in= new BufferedReader(new
  2. InputStreamReader(newFileInputStream("Enc_RSA.dat")));
  3. String ctext=in.readLine();
  4. BigInteger c=new BigInteger(ctext);

2) 获取私钥

  1. FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
  2. ObjectInputStream b=new ObjectInputStream(f);
  3. RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );

(3) 获取私钥的参数(d, n)

  1. BigInteger d=prk.getPrivateExponent( );
  2. BigInteger n=prk.getModulus( );

(4) 执行计算

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

(5) 计算明文整型数对应的字符串

  1. byte[] mt=m.toByteArray();
  2. for(int i=0;i<mt.length;i++){
  3. System.out.print((char) mt[i]);
  4. }
创建共享密钥
  • (1) 读取自己的DH私钥和对方的DH公钥
  1. FileInputStream f1=new FileInputStream(args[0]);
  2. ObjectInputStream b1=new ObjectInputStream(f1);
  3. PublicKey pbk=(PublicKey)b1.readObject( );
  4. FileInputStream f2=newJava摘要算法- MD5 FileInputStream(args[1]);
  5. ObjectInputStream b2=new ObjectInputStream(f2);
  6. PrivateKey prk=(PrivateKey)b2.readObject( );

(2) 创建密钥协定对象

  1. KeyAgreement ka=KeyAgreement.getInstance("DH");

(3) 初始化密钥协定对象

  1. ka.init(prk);

(4) 执行密钥协定

  1. ka.doPhase(pbk,true);

(5) 生成共享信息

  1. byte[ ] sb=ka.generateSecret();
Java摘要算法- MD5

(1) 生成MessageDigest对象

  1. MessageDigest m=MessageDigest.getInstance("MD5");

(2) 传入需要计算的字符串

  1. m.update(x.getBytes("UTF8" ));

(3) 计算消息摘要

  1. byte s[ ]=m.digest( );

(4) 处理计算结果

  1. String result="";
  2. for (int i=0; i<s.length; i++){
  3. result+=Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);
  4. }

实验步骤:

  • 与结对伙伴链接上同一个热点。
  • 在cmd中输入ipconfig
  • 找到相应的网域的ip(如我的ip为192.168.43.159)
  • 伙伴在cmd中输入ping 192.168.43.159(应先关闭防火墙)
  • 显示连接成功
  • 找到一个闲置的端口(我用的端口为我的学号5329)
  • 伙伴或自己打开服务器,自己在运行客户端,便可以开始测试代码了。

    -此时可以连接服务器了

实验内容

-实验截图分别为我idea截图和与我合作的黄斐学长的idea截图

第一题:

结对实现中缀表达式转后缀表达式的功能 MyBC.java

结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java

  • 将运算符写在两个操作数中间的表达式,称为“中缀表达式”,如1+2/(3-4)+5。在中缀表达式中,运算符具有不同的优先级,圆括号用于改变运算符的运算次序,所以求值过程不能直接按照从左到右的顺序进行。

  • 将运算符写在两个操作数之后的表达式称为“后缀表达式”,如上面的中缀表达式可转换为后缀表达式1 2 3 4 - * + 5 +。后缀表达式中没有括号,而且运算符没有优先级。后缀表达式的求值过程能够严格地从左到右按顺序进行,符合运算器的求值规律。

  • 表达式求值算法分两步进行:①中缀转后缀;②求后缀表达式的值。

①中缀转后缀的算法可描述为:

  • 设置一个运算符栈,设置一个后缀表达式字符串;
  • 从左到右依次对中缀表达式中的每个字符ch分别进行以下处理,直至表达式结束:
  • 若ch是左括号‘(’,将其入栈;
  • 若ch是数字,将其后连续若干数字添加到后缀表达式字符串之后,并添加空格作为分隔符;
  • 若ch是运算符,先将栈顶若干优先级高于ch的运算符出栈,添加到后缀表达式字符串之后,再将ch入栈。当‘(’运算符在栈中时,它的优先级最低。
  • 若ch是‘)’,则若干运算符全部出栈,直到出栈的是左括号,一对括号匹配。
  • 若表达式结束,将栈中运算符全部出栈,添加到后缀表达式字符串之后。
代码如下:
  • MyBC
  1. import java.util.*;
  2. public class MyBC {
  3. private static LinkedList<String> op1 = new LinkedList<>();
  4. private static LinkedList<String> op2 = new LinkedList<>();
  5. private static StringBuilder a = new StringBuilder();
  6. public StringBuilder houzhui(LinkedList<String> list) {
  7. Iterator<String> i = list.iterator();
  8. while (i.hasNext()) {
  9. String s = i.next();
  10. if (isOperator(s)) {
  11. if (op1.isEmpty()) {
  12. op1.push(s);
  13. } else {
  14. if (priority(op1.peek()) <= priority(s) && !s.equals(")")) {
  15. op1.push(s);
  16. } else if (!s.equals(")") && priority(op1.peek()) > priority(s)) {
  17. while (op1.size() != 0 && priority(op1.peek()) >= priority(s)
  18. && !op1.peek().equals("(")) {
  19. if (!op1.peek().equals("(")) {
  20. String operator = op1.pop();
  21. a.append(operator).append(" ");
  22. op2.push(operator);
  23. }
  24. }
  25. op1.push(s);
  26. } else if (s.equals(")")) {
  27. while (!op1.peek().equals("(")) {
  28. String operator = op1.pop();
  29. a.append(operator).append(" ");
  30. op2.push(operator);
  31. }
  32. op1.pop();
  33. }
  34. }
  35. } else {
  36. a.append(s).append(" ");
  37. op2.push(s);
  38. }
  39. }
  40. if (!op1.isEmpty()) {
  41. Iterator<String> iterator = op1.iterator();
  42. while (iterator.hasNext()) {
  43. String operator = iterator.next();
  44. a.append(operator).append(" ");
  45. op2.push(operator);
  46. iterator.remove();
  47. }
  48. }
  49. return a;
  50. }
  51. private static boolean isOperator(String oper) {
  52. if (oper.equals("+") || oper.equals("-") || oper.equals("/") || oper.equals("*")
  53. || oper.equals("(") || oper.equals(")")) {
  54. return true;
  55. }
  56. return false;
  57. }
  58. private static int priority(String s) {
  59. switch (s) {
  60. case "+":
  61. return 1;
  62. case "-":
  63. return 1;
  64. case "*":
  65. return 2;
  66. case "/":
  67. return 2;
  68. case "(":
  69. return 3;
  70. case ")":
  71. return 3;
  72. default:
  73. return 0;
  74. }
  75. }
  76. }
  • MyDC
  1. import java.util.LinkedList;
  2. import java.util.*;
  3. import java.util.*;
  4. public class MyDC {
  5. public static int evaluate(StringBuilder b) {
  6. LinkedList<String> mList = new LinkedList<>();
  7. String[] postStr = b.toString().split(" ");
  8. int result;
  9. for (String s : postStr) {
  10. if (fuhao(s)) {
  11. if (!mList.isEmpty()) {
  12. int num1 = Integer.valueOf(mList.pop());
  13. int num2 = Integer.valueOf(mList.pop());
  14. if (s.equals("/") && num1 == 0) {
  15. System.out.println("除数不能为0");
  16. return 0;
  17. }
  18. int newNum = cal(num2, num1, s);
  19. mList.push(String.valueOf(newNum));
  20. }
  21. } else {
  22. mList.push(s);
  23. }
  24. }
  25. result=Integer.parseInt(mList.pop());
  26. return result;
  27. }
  28. private static boolean fuhao(String a) {
  29. if (a.equals("+") || a.equals("-") || a.equals("/") || a.equals("*")
  30. || a.equals("(") || a.equals(")")) {
  31. return true;
  32. }
  33. return false;
  34. }
  35. private static int cal(int num1, int num2, String operator) {
  36. switch (operator) {
  37. case "+":
  38. return num1 + num2;
  39. case "-":
  40. return num1 - num2;
  41. case "*":
  42. return num1 * num2;
  43. case "/":
  44. return num1 / num2;
  45. default:
  46. return 0;
  47. }
  48. }
  49. }
  • MyDCTest
  1. import java.util.LinkedList;
  2. import java.util.*;
  3. public class MyDCTest {
  4. public static void main(String[] args){
  5. LinkedList<String> list=new LinkedList<>();
  6. StringBuilder result1;
  7. int result2;
  8. String expression, again;
  9. System.out.println("请输入一个中缀表达式并以#结束");
  10. Scanner scanner=new Scanner(System.in);
  11. String s;
  12. while (!(s=scanner.next()).equals("#")) {
  13. list.add(s);
  14. }
  15. MyBC hz=new MyBC();
  16. result1 = hz.houzhui(list);
  17. System.out.println("后缀表达式: "+result1);
  18. MyDC evaluator = new MyDC();
  19. result2 = evaluator.evaluate(result1);
  20. System.out.println("That expression equals " + result2);
  21. System.out.println();
  22. }
  23. }
实验截图

第二题:

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

0. 注意责任归宿,要会通过测试证明自己没有问题

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
  3. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  4. 客户端显示服务器发送过来的结果
  5. 上传测试结果截图和码云链接
  • 套接字是一个网络连接的端点。在java中,使用java.net.Socket对象来表示一个套接字。
  • 要创建一个套接字,可以使用Socket的构造方法,如:public Socket(java.lang.String host, int port)。其中,host是远程机器名或IP地址,port是远程应用程序的端口号。
  • 一旦成功创建了Socket类的一个实例,就可以使用它发送或接收字节流。要发送字节流,必须先调用Socket类的getOutputStream方法来获取一个java.io.OutputStream对象。要向远程应用程序发送文本,通常要从返回的OutputStream对象构建一个java.io.PrintWriter对象。要接收来自连接的另一端的字节流,可以调用Socket类的getInputStream方法,它返回一个java.io.InputStream。
代码如下

Stack

  1. public class MyStack<T> implements SStack<T> {
  2. private Object element[];
  3. private int top;
  4. public MyStack(int size){
  5. this.element = new Object[Math.abs(size)];
  6. this.top = -1;
  7. }
  8. public MyStack() {
  9. this(64);
  10. }
  11. public boolean isEmpty() {
  12. return this.top == -1;
  13. }
  14. public void push(T x) {
  15. if(x==null)
  16. return;
  17. if(this.top == element.length-1){
  18. Object[] temp = this.element;
  19. this.element = new Object[temp.length*2];
  20. for(int i = 0; i < temp.length; i++)
  21. this.element[i] = temp[i];
  22. }
  23. this.top++;
  24. this.element[this.top] = x;
  25. }
  26. public T pop() {
  27. return this.top==-1 ? null:(T)this.element[this.top--];
  28. }
  29. public T get() {
  30. return this.top==-1 ? null:(T)this.element[this.top];
  31. }
  32. }

SStack

  1. public interface SStack<T> {
  2. boolean isEmpty();
  3. void push(T x);
  4. T pop();
  5. T get();
  6. }

Client(客户端代码)

  1. import java.net.*;
  2. import java.io.*;
  3. public class TCPClient {
  4. public static void main(String srgs[]) {
  5. try {
  6. //创建连接特定服务器的指定端口的Socket对象
  7. Socket socket = new Socket("127.0.0.1", 4421);
  8. //获得从服务器端来的网络输入流
  9. BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  10. //获得从客户端向服务器端输出数据的网络输出流
  11. PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
  12. //创建键盘输入流,以便客户端从键盘上输入信息
  13. BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
  14. System.out.print("请输入待发送的数据:");
  15. String str=stdin.readLine(); //从键盘读入待发送的数据
  16. String postfix = MyBC.toPostfix(str);
  17. out.println(postfix); //通过网络传送到服务器
  18. str=in.readLine();//从网络输入流读取结果
  19. System.out.println( "从服务器接收到的结果为:"+str); //输出服务器返回的结果
  20. }
  21. catch (Exception e) {
  22. System.out.println(e);
  23. }
  24. finally{
  25. //stdin.close();
  26. //in.close();
  27. //out.close();
  28. //socket.close();
  29. }
  30. }
  31. }
  • ServerSocket是服务器套接字的一个实现。ServerSocket和Socket不同,服务器套接字的角色是,等待来自客户端的连接请求。一旦服务器套接字获得了一个连接请求,它就会创建一个Socket实例,以处理和客户端的通信。

    Service(服务端代码)
  1. import java.net.*;
  2. import java.io.*;
  3. public class TCPServer{
  4. public static void main(String srgs[]) {
  5. ServerSocket sc = null;
  6. Socket socket=null;
  7. try {
  8. NewMyDC evaluator = new NewMyDC();
  9. sc= new ServerSocket(4421);//创建服务器套接字
  10. System.out.println("端口号:" + sc.getLocalPort());
  11. System.out.println("服务器已经启动...");
  12. socket = sc.accept(); //等待客户端连接
  13. System.out.println("已经建立连接");
  14. //获得网络输入流对象的引用
  15. BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  16. ////获得网络输出流对象的引用
  17. PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
  18. String aline=in.readLine();//读取客户端传送来的数据
  19. System.out.println("从客户端接收到信息为:"+aline); //通过网络输出流返回结果给客户端
  20. int result = evaluator.value(aline);
  21. out.println("Echo:" + result);
  22. out.close();
  23. in.close();
  24. sc.close();
  25. } catch (Exception e) {
  26. System.out.println(e);
  27. }
  28. }
  29. }
实验截图:

第三题:

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

0. 注意责任归宿,要会通过测试证明自己没有问题

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
  3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  4. 客户端显示服务器发送过来的结果
  5. 上传测试结果截图和码云链接
  • 实现DES加密主要有以下几个步骤:
  • 对称密钥的生成和保存;
  • 使用对称密钥进行加密和解密;
  • 从文件中获取加密时使用的密钥,使用密钥进行解密;
代码如下
  • 客户端加密并发送至服务器部分的代码如下:
  1. KeyGenerator kg = KeyGenerator.getInstance("DESede");
  2. kg.init(168);
  3. SecretKey k = kg.generateKey();
  4. byte[] ptext2 = k.getEncoded();
  5. Socket socket = new Socket("127.0.0.1", 4421);
  6. BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  7. PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
  8. BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
  9. //RSA算法,使用服务器端的公钥对DES的密钥进行加密
  10. FileInputStream f3 = new FileInputStream("Skey_RSA_pub.dat");
  11. ObjectInputStream b2 = new ObjectInputStream(f3);
  12. RSAPublicKey pbk = (RSAPublicKey) b2.readObject();
  13. BigInteger e = pbk.getPublicExponent();
  14. BigInteger n = pbk.getModulus();
  15. BigInteger m = new BigInteger(ptext2);
  16. BigInteger c = m.modPow(e, n);
  17. String cs = c.toString();
  18. out.println(cs); // 通过网络将加密后的秘钥传送到服务器
  19. System.out.print("请输入待发送的数据:");
  20. //用DES加密明文得到密文
  21. String s = stdin.readLine(); // 从键盘读入待发送的数据
  22. String postfix = MyBC.toPostfix(s);
  23. Cipher cp = Cipher.getInstance("DESede");
  24. cp.init(Cipher.ENCRYPT_MODE, k);
  25. byte ptext[] = postfix.getBytes("UTF8");
  26. byte ctext[] = cp.doFinal(ptext);
  27. String str = parseByte2HexStr(ctext);
  28. out.println(str); // 通过网络将密文传送到服务器

-服务器解密、计算并发送至客户端部分的代码如下:

  1. String line = in.readLine();
  2. BigInteger cipher = new BigInteger(line);
  3. FileInputStream f = new FileInputStream("Skey_RSA_priv.dat");
  4. ObjectInputStream b = new ObjectInputStream(f);
  5. RSAPrivateKey prk = (RSAPrivateKey) b.readObject();
  6. BigInteger d = prk.getPrivateExponent();
  7. BigInteger n = prk.getModulus();//mod n
  8. BigInteger m = cipher.modPow(d, n);//m=d (mod n)
  9. System.out.println("d= " + d);
  10. System.out.println("n= " + n);
  11. System.out.println("m= " + m);
  12. byte[] keykb = m.toByteArray();
  13. // 使用DES对密文进行解密
  14. String readline = in.readLine();//读取客户端传送来的数据
  15. FileInputStream f2 = new FileInputStream("keykb1.dat");
  16. int num2 = f2.available();
  17. byte[] ctext = parseHexStr2Byte(readline);
  18. Key k = new SecretKeySpec(keykb,"DESede");
  19. Cipher cp = Cipher.getInstance("DESede");
  20. cp.init(Cipher.DECRYPT_MODE, k);
  21. byte[] ptext = cp.doFinal(ctext);
  22. String p = new String(ptext, "UTF8");//编码转换
  23. System.out.println("从客户端接收到信息为:" + p); //打印解密结果
  24. NewMyDC evaluator = new NewMyDC();
  25. int _result = evaluator.value(p);
  26. out.println("Echo:" + _result);
  27. out.close();
  28. in.close();
  29. link.close();
  • 服务端代码如下(Serice)
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintWriter;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.io.*;
  8. import java.security.*;
  9. import javax.crypto.*;
  10. import javax.crypto.spec.*;
  11. public class SocketService {
  12. public static void main(String[] args) throws IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
  13. SocketService socketService = new SocketService();
  14. try {
  15. socketService.oneServer();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. } catch (NoSuchPaddingException e) {
  19. e.printStackTrace();
  20. } catch (NoSuchAlgorithmException e) {
  21. e.printStackTrace();
  22. } catch (InvalidKeyException e) {
  23. e.printStackTrace();
  24. } catch (BadPaddingException e) {
  25. e.printStackTrace();
  26. } catch (IllegalBlockSizeException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. public void oneServer() throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
  31. MyDC mydc=new MyDC();
  32. try{
  33. ServerSocket server=null;
  34. try{
  35. server=new ServerSocket(5204);
  36. System.out.println("服务器启动成功");
  37. }catch(Exception e) {
  38. System.out.println("没有启动监听:"+e);
  39. }
  40. Socket socket=null;
  41. try{
  42. socket=server.accept();
  43. }catch(Exception e) {
  44. System.out.println("Error."+e);
  45. }
  46. String line;
  47. BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
  48. PrintWriter writer=new PrintWriter(socket.getOutputStream());
  49. line=in.readLine();
  50. System.out.printf("密文=%s\n",line);
  51. // 获取密钥
  52. byte[]ctext=line.getBytes("ISO-8859-1");
  53. FileInputStream f2=new FileInputStream("keykb1.dat");
  54. int num2=f2.available();
  55. byte[ ] keykb=new byte[num2];
  56. System.out.printf("\n");
  57. f2.read(keykb);
  58. SecretKeySpec k=new SecretKeySpec(keykb,"DESede");
  59. // 解密
  60. Cipher cp=Cipher.getInstance("DESede");
  61. cp.init(Cipher.DECRYPT_MODE, k);
  62. byte []ptext=cp.doFinal(ctext);
  63. // 显示明文
  64. String p=new String(ptext,"UTF8");
  65. System.out.println("明文:"+p);
  66. int a;
  67. String Np="";
  68. for(int i=1;i<p.length();i++)
  69. Np+=p.charAt(i);
  70. a=mydc.evaluate(Np);
  71. writer.println(a);
  72. writer.flush();
  73. writer.close();
  74. in.close();
  75. socket.close();
  76. server.close();
  77. }catch(Exception e) {
  78. System.out.println("Error."+e);
  79. }
  80. // 获取密文
  81. }
  82. }
  • 客户端代码
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintWriter;
  5. import java.net.Socket;
  6. import java.io.*;
  7. import java.security.*;
  8. import java.util.Arrays;
  9. import javax.crypto.*;
  10. public class SocketClient {
  11. // 搭建客户端
  12. public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
  13. MyBC mybc=new MyBC();
  14. try {
  15. Socket socket = new Socket("192.168.43.166",5329);
  16. System.out.println("客户端启动成功");
  17. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  18. PrintWriter write = new PrintWriter(socket.getOutputStream());
  19. BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  20. String readline;
  21. System.out.println("Client:" );
  22. readline = br.readLine();
  23. String line=mybc.evaluate(readline);
  24. FileInputStream f=new FileInputStream("key1.dat");
  25. ObjectInputStream b=new ObjectInputStream(f);
  26. Key k=(Key)b.readObject();
  27. Cipher cp=Cipher.getInstance("DESede");
  28. cp.init(Cipher.ENCRYPT_MODE, k);
  29. byte ptext[]=line.getBytes("UTF-8");
  30. byte ctext[]=cp.doFinal(ptext);
  31. String Str=new String(ctext,"ISO-8859-1");
  32. write.println(Str);
  33. write.flush();
  34. System.out.println("Server return:" + in.readLine());
  35. write.close();
  36. in.close();
  37. socket.close();
  38. } catch (Exception e) {
  39. System.out.println("can not listen to:" + e);
  40. }
  41. }
  42. }
实验截图



第四题:

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

0. 注意责任归宿,要会通过测试证明自己没有问题

  1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
  2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
  3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
  4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
  5. 客户端显示服务器发送过来的结果
  6. 上传测试结果截图和码云链接
  • 执行密钥协定的标准算法是DH算法(Diffie-Hellman算法),分为以下两步:
  • 创建DH公钥和私钥;
  • 创建共享密钥。
  • 创建DH公钥和私钥:
代码如下
  1. public class Key_DH{
  2. private static final byte skip1024ModulusBytes[] = {
  3. (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58,
  4. (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD,
  5. (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4,
  6. (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B,
  7. (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D,
  8. (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C,
  9. (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C,
  10. (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6,
  11. (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0,
  12. (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B,
  13. (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB,
  14. (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D,
  15. (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD,
  16. (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43,
  17. (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C,
  18. (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C,
  19. (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C,
  20. (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40,
  21. (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C,
  22. (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72,
  23. (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03,
  24. (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29,
  25. (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C,
  26. (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB,
  27. (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B,
  28. (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08,
  29. (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D,
  30. (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C,
  31. (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22,
  32. (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB,
  33. (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55,
  34. (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7
  35. };
  36. // The SKIP 1024 bit modulus
  37. private static final BigInteger skip1024Modulus
  38. = new BigInteger(1, skip1024ModulusBytes);
  39. // The base used with the SKIP 1024 bit modulus
  40. private static final BigInteger skip1024Base = BigInteger.valueOf(2);
  41. public static void main(String args[ ]) throws Exception{
  42. DHParameterSpec DHP=
  43. new DHParameterSpec(skip1024Modulus,skip1024Base);
  44. KeyPairGenerator kpg= KeyPairGenerator.getInstance("DH");
  45. kpg.initialize(DHP);
  46. KeyPair kp=kpg.genKeyPair();
  47. PublicKey pbk=kp.getPublic();
  48. PrivateKey prk=kp.getPrivate();
  49. // 保存公钥
  50. FileOutputStream f1=new FileOutputStream(args[0]);
  51. ObjectOutputStream b1=new ObjectOutputStream(f1);
  52. b1.writeObject(pbk);
  53. // 保存私钥
  54. FileOutputStream f2=new FileOutputStream(args[1]);
  55. ObjectOutputStream b2=new ObjectOutputStream(f2);
  56. b2.writeObject(prk);
  57. }
  58. }

-创建共享密钥:

  1. public class KeyAgree{
  2. public static void main(String args[ ]) throws Exception{
  3. // 读取对方的DH公钥
  4. FileInputStream f1=new FileInputStream(args[0]);
  5. ObjectInputStream b1=new ObjectInputStream(f1);
  6. PublicKey pbk=(PublicKey)b1.readObject( );
  7. //读取自己的DH私钥
  8. FileInputStream f2=new FileInputStream(args[1]);
  9. ObjectInputStream b2=new ObjectInputStream(f2);
  10. PrivateKey prk=(PrivateKey)b2.readObject( );
  11. // 执行密钥协定
  12. KeyAgreement ka=KeyAgreement.getInstance("DH");
  13. ka.init(prk);
  14. ka.doPhase(pbk,true);
  15. //生成共享信息
  16. byte[ ] sb=ka.generateSecret();
  17. for(int i=0;i<sb.length;i++){
  18. System.out.print(sb[i]+",");
  19. }
  20. SecretKeySpec k=new SecretKeySpec(sb,"DESede");
  21. }
  22. }
实验截图



第五题:

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

0. 注意责任归宿,要会通过测试证明自己没有问题

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

Service

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintWriter;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.io.*;
  8. import java.security.*;
  9. import javax.crypto.*;
  10. import javax.crypto.spec.*;
  11. public class SocketService {
  12. public static void main(String[] args) throws IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
  13. SocketService socketService = new SocketService();
  14. try {
  15. socketService.oneServer();
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. } catch (NoSuchPaddingException e) {
  19. e.printStackTrace();
  20. } catch (NoSuchAlgorithmException e) {
  21. e.printStackTrace();
  22. } catch (InvalidKeyException e) {
  23. e.printStackTrace();
  24. } catch (BadPaddingException e) {
  25. e.printStackTrace();
  26. } catch (IllegalBlockSizeException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. public void oneServer() throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
  31. MyDC mydc=new MyDC();
  32. try{
  33. ServerSocket server=null;
  34. try{
  35. server=new ServerSocket(5329);
  36. System.out.println("服务器启动成功");
  37. }catch(Exception e) {
  38. System.out.println("没有启动监听:"+e);
  39. }
  40. Socket socket=null;
  41. try{
  42. socket=server.accept();
  43. }catch(Exception e) {
  44. System.out.println("Error."+e);
  45. }
  46. String line;
  47. BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
  48. PrintWriter writer=new PrintWriter(socket.getOutputStream());
  49. line=in.readLine();
  50. String line1=in.readLine();
  51. System.out.printf("密文=%s\n",line);
  52. // 获取密钥
  53. byte[]ctext=line.getBytes("ISO-8859-1");
  54. FileInputStream f2=new FileInputStream("keykb1.dat");
  55. int num2=f2.available();
  56. byte[ ] keykb=new byte[num2];
  57. System.out.printf("\n");
  58. f2.read(keykb);
  59. SecretKeySpec k=new SecretKeySpec(keykb,"DESede");
  60. // 解密
  61. Cipher cp=Cipher.getInstance("DESede");
  62. cp.init(Cipher.DECRYPT_MODE, k);
  63. byte []ptext=cp.doFinal(ctext);
  64. // 显示明文
  65. String p=new String(ptext,"UTF8");
  66. int a;
  67. System.out.println("明文:"+p);
  68. String Np="";
  69. for(int i=1;i<p.length();i++)
  70. Np+=p.charAt(i);
  71. a=mydc.evaluate(Np);
  72. String x=p;
  73. MessageDigest m=MessageDigest.getInstance("MD5");
  74. m.update(x.getBytes("UTF8"));
  75. byte s[ ]=m.digest( );
  76. String result="";
  77. for (int i=0; i<s.length; i++){
  78. result+=Integer.toHexString((0x000000ff & s[i]) |
  79. 0xffffff00).substring(6);
  80. }
  81. if(!(line1.equals(result)))System.out.printf("MD5比对正确!\n");
  82. writer.println(a);
  83. writer.flush();
  84. writer.close();
  85. in.close();
  86. socket.close();
  87. server.close();
  88. }catch(Exception e) {
  89. System.out.println("Error."+e);
  90. }
  91. // 获取密文
  92. }

创建共享密钥

  1. public class KeyAgree{
  2. public static void main(String args[ ]) throws Exception{
  3. // 读取对方的DH公钥
  4. FileInputStream f1=new FileInputStream(args[0]);
  5. ObjectInputStream b1=new ObjectInputStream(f1);
  6. PublicKey pbk=(PublicKey)b1.readObject( );
  7. //读取自己的DH私钥
  8. FileInputStream f2=new FileInputStream(args[1]);
  9. ObjectInputStream b2=new ObjectInputStream(f2);
  10. PrivateKey prk=(PrivateKey)b2.readObject( );
  11. // 执行密钥协定
  12. KeyAgreement ka=KeyAgreement.getInstance("DH");
  13. ka.init(prk);
  14. ka.doPhase(pbk,true);
  15. //生成共享信息
  16. byte[ ] sb=ka.generateSecret();
  17. for(int i=0;i<sb.length;i++){
  18. System.out.print(sb[i]+",");
  19. }
  20. SecretKeySpec k=new SecretKeySpec(sb,"DESede");
  21. }
  22. }
实验截图



码云链接

实验总结与体会

这次实验是java这门课程的最后一次实验,在这次实验中拿到题目的第一反应就是怎么办呀,老师也没给教程,什么都没有,好无助,好绝望呀。

但是想想再挣扎一下吧,代码好难不会写怎么办呀,最后拿了学长的代码来用,拿来的代码也有很多问题,慢慢改到能编译了,发现运行结果不对,再继续修改到,编译运行都对了。本次实验花了两天时间,虽然时间花费了很多,但也学习到了很多知识。我认为这次实验完成的很棒。{{uploading-image-522164.png(uploading...)}}

重温本次实验,真正的用到了结对编程。虽然代码不是自己的,重新仔细的看了一遍。明白了每段代码发挥的作用。相对与信息安全专业来说,密码是保证信息安全得重要手段,本次实验让我们体会到了编程实现密码算法对信息安全的实用性,正确性。

实验中的一些重点问题:

-对称加密-DES算法

实验五 Java网络编程的更多相关文章

  1. 20145213《Java程序设计》实验五Java网络编程及安全

    20145213<Java程序设计>实验五Java网络编程及安全 实验内容 1.掌握Socket程序的编写. 2.掌握密码技术的使用. 3.设计安全传输系统. 实验预期 1.客户端与服务器 ...

  2. 20145206《Java程序设计》实验五Java网络编程及安全

    20145206<Java程序设计>实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 我和201451 ...

  3. 20145337实验五Java网络编程及安全

    20145337实验五Java网络编程及安全 实验内容 掌握Socket程序的编写 掌握密码技术的使用 设计安全传输系统 实验步骤 基于Java Socket实现安全传输 基于TCP实现客户端和服务器 ...

  4. JAVA课程实验报告 实验五 Java网络编程及安全

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1353  姓名:韩玉琪  学号:20135317 成绩:             指导教师:娄嘉 ...

  5. 20145225《Java程序设计》 实验五 Java网络编程及安全

    20145225<Java程序设计> 实验五 Java网络编程及安全 实验报告 一.实验内容 基于Java Socket实现安全传输. 基于TCP实现客户端和服务器,结对编程一人负责客户端 ...

  6. 20145208 实验五 Java网络编程

    20145208 实验五 Java网络编程 实验内容 1.用书上的TCP代码,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务 ...

  7. 20145215实验五 Java网络编程及安全

    20145215实验五 Java网络编程及安全 实验内容 掌握Socket程序的编写: 掌握密码技术的使用: 设计安全传输系统. 实验步骤 本次实验我的结对编程对象是20145208蔡野,我负责编写客 ...

  8. 20145220 实验五 Java网络编程

    20145220 实验五 Java网络编程 实验内容 1.用书上的TCP代码,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务 ...

  9. 20145203 实验五 Java网络编程及安全

    20145203 实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验要求 1.基于Java Socket实现安全传输 2 ...

  10. 实验五Java网络编程及安全

    实验五 Java网络编程及安全 结对伙伴:20135231林涵锦(负责服务器方)http://www.cnblogs.com/20135213lhj/  实验目的与要求: 1.掌握Java网络编程的方 ...

随机推荐

  1. metasploit渗透测试笔记(内网渗透篇)

    x01 reverse the shell File 通常做法是使用msfpayload生成一个backdoor.exe然后上传到目标机器执行.本地监听即可获得meterpreter shell. r ...

  2. Python中替换的三种方法

    strip()    replace()      re.sub() 1.replace()是python的内置函数,字符类型.replace(old,new) s1="你好2017&quo ...

  3. 【[ZJOI2012]灾难】

    好像很久之前就看过这道题,大概是刚学\(LCA\)的时候 之后当时肯定是不会的呀 现在发现这道题并不是非常难 首先我们发现这个灭绝的关系非常像一棵树,我们建出这个灭绝树求一个前缀和就可以啦 那么应该怎 ...

  4. programming-languages学习

    programming-languages学习 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src {backg ...

  5. [转]MBTiles 1.2 规范翻译

    MBTiles 1.2 可以参考超图的文档MBTiles扩展具体实现可以参考浅谈利用SQLite存储离散瓦片的思路和实现方法 mapbox提供了一个简单实现测试代码,github地址在这里https: ...

  6. Redis(四)持久化

    本文转载自编程迷思,原文链接 深入学习Redis(2):持久化 前言 在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关的知识——持久化.复制(及读写分离).哨 ...

  7. AMQ(approximate membership queries)介绍

    目录 简介 举例 Bloom Filter 算法过程 1)位数组: 2)添加元素,k个独立hash函数 3)判断元素是否存在集合 Quotient Filter and Cascade Filter ...

  8. LWIP2.0.2 & FreeRTOS & MQTT 客户端的 使用

    1.参考链接 :http://www.nongnu.org/lwip/2_0_x/group__mqtt.html 2.首先移植好lwip,然后添加lwip-2.0.2\src\apps\mqtt   ...

  9. linux内存管理--用户空间和内核空间

    关于虚拟内存有三点需要注意: 4G的进程地址空间被人为的分为两个部分--用户空间与内核空间.用户空间从0到3G(0xc0000000),内核空间占据3G到4G.用户进程通常情况下只能访问用户空间的虚拟 ...

  10. 前端基础-HTML的的标签详解

    阅读目录 一.head内常用标签 二. HTML语义化 三. 字符实体 四. h系列标签 五. p标签 六. img标签 七. a标签 八. 列表标签 九. table标签 十. form标签 一. ...