一、实验内容与步骤
任务一
1、实验要求
两人一组结对编程:
0. 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
1. 结对实现中缀表达式转后缀表达式的功能 MyBC.java
2. 结对实现从上面功能中获取的表达式中实现后缀表达式求值的功能,调用MyDC.java
3. 上传测试代码运行结果截图和码云链接
2、实验内容
①MyBC.java
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.lang.String; import org.junit.Test; public class MyBC{ private static final Map<Character, Integer> basic = new HashMap<Character, Integer>(); static { basic.put('-', 1); basic.put('+', 1); basic.put('*', 2); basic.put('/', 2); basic.put('(', 0); } //中缀表达式 转 后缀表达式 public static String toSuffix(String infix){ List<String> queue = new ArrayList<String>(); List<Character> stack = new ArrayList<Character>(); char[] charArr = infix.trim().toCharArray(); String standard = "*/+-()"; char ch = '&'; int len = 0; for (int i = 0; i < charArr.length; i++) { ch = charArr[i]; if(Character.isDigit(ch)) { len++; }else if(Character.isLetter(ch)) { len++; }else if(ch == '.'){ len++; }else if(Character.isSpaceChar(ch)) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } continue; }else if(standard.indexOf(ch) != -1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } if(ch == '(') { stack.add(ch); continue; } if (!stack.isEmpty()) { int size = stack.size() - 1; boolean flag = false; while (size >= 0 && ch == ')' && stack.get(size) != '(') { queue.add(String.valueOf(stack.remove(size))); size--; flag = true; } while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) { queue.add(String.valueOf(stack.remove(size))); size--; } } if(ch != ')') { stack.add(ch); } else { stack.remove(stack.size() - 1); } } if(i == charArr.length - 1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1,i+1))); } int size = stack.size() - 1; while (size >= 0) { queue.add(String.valueOf(stack.remove(size))); size--; } } } return queue.stream().collect(Collectors.joining(" ")); } }
②MyBCTest.java
public class MyBCTest { public static void main(String[] args){ MyBC a = new MyBC(); MyDC b = new MyDC(); String c =new String(); System.out.println("Test: "); c = a.toSuffix("1+3*6/2+7+(4*5)/5"); System.out.printf(c); System.out.printf(" The result is: "); System.out.printf("%d",b.evaluate(c)); } }
③MyDC.java
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.lang.String; import org.junit.Test; public class MyDC{ private static final Map<Character, Integer> basic = new HashMap<Character, Integer>(); static { basic.put('-', 1); basic.put('+', 1); basic.put('*', 2); basic.put('/', 2); basic.put('(', 0); } //中缀表达式 转 后缀表达式 public static String toSuffix(String infix){ List<String> queue = new ArrayList<String>(); List<Character> stack = new ArrayList<Character>(); char[] charArr = infix.trim().toCharArray(); String standard = "*/+-()"; char ch = '&'; int len = 0; for (int i = 0; i < charArr.length; i++) { ch = charArr[i]; if(Character.isDigit(ch)) { len++; }else if(Character.isLetter(ch)) { len++; }else if(ch == '.'){ len++; }else if(Character.isSpaceChar(ch)) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } continue; }else if(standard.indexOf(ch) != -1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i))); len = 0; } if(ch == '(') { stack.add(ch); continue; } if (!stack.isEmpty()) { int size = stack.size() - 1; boolean flag = false; while (size >= 0 && ch == ')' && stack.get(size) != '(') { queue.add(String.valueOf(stack.remove(size))); size--; flag = true; } while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) { queue.add(String.valueOf(stack.remove(size))); size--; } } if(ch != ')') { stack.add(ch); } else { stack.remove(stack.size() - 1); } } if(i == charArr.length - 1) { if(len > 0) { queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1,i+1))); } int size = stack.size() - 1; while (size >= 0) { queue.add(String.valueOf(stack.remove(size))); size--; } } } return queue.stream().collect(Collectors.joining(" ")); } public int evaluate(String expression) { return 0; } }
④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"); } } }
3、运行结果如下:
任务二
1、实验要求
结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题
1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式通过网络发送给服务器
3. 服务器接收到后缀表达式,调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
4. 客户端显示服务器发送过来的结果
5. 上传测试结果截图和码云链接
2、实验内容
结对对象:20175332
①编写代码
import java.io.*; import java.net.*; public class Service { public static void main(String args[]) { int answer; ServerSocket serverForClient=null; Socket socketOnServer=null; DataOutputStream out=null; DataInputStream in=null; try { serverForClient = new ServerSocket(5228); } catch(IOException e1) { System.out.println(e1); } try{ System.out.println("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 out=new DataOutputStream(socketOnServer.getOutputStream()); in=new DataInputStream(socketOnServer.getInputStream()); String s=in.readUTF(); // in读取信息,堵塞状态 System.out.println("服务器收到客户的提问:"+s); MyDC d=new MyDC(); answer=d.evaluate(s); out.writeUTF(answer+""); Thread.sleep(500); } catch(Exception e) { System.out.println("客户已断开"+e); } } }
import java.io.*; import java.net.*; import java.lang.*; import java.util.Scanner; /** * Demo class * * @author liyuechen * @date 2019/5/26 */ public class Client { public static void main(String[] args) { Socket mysocket; DataInputStream in=null; DataOutputStream out=null; try{ mysocket=new Socket("127.1.0.0",5228); 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.toSuffix(str); out.writeUTF(str); String s=in.readUTF(); System.out.println("客户收到服务器的回答:"+s); Thread.sleep(500); } catch(Exception e) { System.out.println("服务器已断开"+e); } } }
3、客户端输入中缀表达式,调用MyBC.java转为后缀表达式;服务器接收后缀表达式,调用MyDC.java计算结果值并返回到客户端。运行结果如下:
任务三
1、实验要求
加密结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题
1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密后通过网络把密文发送给服务器
3. 服务器接收到后缀表达式表达式后,进行解密(和客户端协商密钥,可以用数组保存),然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
4. 客户端显示服务器发送过来的结果
5. 上传测试结果截图和码云链接
2、实验内容
编写加密代码AES.java
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; import java.util.Scanner; 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 AES { /* * 加密 */ public static String AESEncode(String encodeRules,String content){ try { KeyGenerator keygen=KeyGenerator.getInstance("AES"); keygen.init(128, new SecureRandom(encodeRules.getBytes())); SecretKey original_key=keygen.generateKey(); byte [] raw=original_key.getEncoded(); SecretKey key=new SecretKeySpec(raw, "AES"); Cipher cipher=Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte [] byte_encode=content.getBytes("utf-8"); byte [] byte_AES=cipher.doFinal(byte_encode); String AES_encode=new String(new BASE64Encoder().encode(byte_AES)); 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(); } return null; } public static String AESDncode(String encodeRules,String content){ try { KeyGenerator keygen=KeyGenerator.getInstance("AES"); keygen.init(128, new SecureRandom(encodeRules.getBytes())); SecretKey original_key=keygen.generateKey(); byte [] raw=original_key.getEncoded(); SecretKey key=new SecretKeySpec(raw, "AES"); Cipher cipher=Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); 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(); } return null; } }
KeyAES.java
import java.io.*; import javax.crypto.*; public class KeyAES{ 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); } }
Serviceone.java
import java.io.*; import java.net.*; public class Serviceone { 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(5228); } catch(IOException e1) { System.out.println(e1); } try{ System.out.println("等待客户呼叫"); socketOnServer = serverForClient.accept(); //堵塞状态,除非有客户呼叫 out=new DataOutputStream(socketOnServer.getOutputStream()); in=new DataInputStream(socketOnServer.getInputStream()); String key = in.readUTF(); String s=in.readUTF(); // in读取信息,堵塞状态 System.out.println("服务器收到的信息:"+s); String clear=AES.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); } } }
Clientone.java
import java.io.*; import java.net.*; import java.lang.*; import java.util.Scanner; public class Clientone { 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.toSuffix(str); String secret=AES.AESEncode(key,str);//客户端进行加密 try { mysocket = new Socket("127.1.0.0", 5228); 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); } } }
3、在客户端输入中缀表达式,调用MyBC.java转后缀表达式,再调用AES.JAVA的加密部分转加密密文;服务器接收到密文,调用AES.JAVA的解密部分对密文解密,再调用MyDC.java对解密明文计算值,返回客户端。运行结果如下:
任务四
1、实验要求
密钥分发结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题
1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文发送给服务器
3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
4. 服务器接收到后缀表达式表达式后,进行解密,然后调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
5. 客户端显示服务器发送过来的结果
6. 上传测试结果截图和码云链接
2、实验内容:使用密钥协定创建共享密钥——DH算法
KeyDH.java
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 KeyDH{ //三个静态变量的定义从 // C:j2sdk-1_4_0-docdocsguidesecurityjceJCERefGuide.html // 拷贝而来 // The 1024 bit Diffie-Hellman modulus values used by SKIP 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(args[0]); ObjectOutputStream b1=new ObjectOutputStream(f1); b1.writeObject(pbk); // 保存私钥 FileOutputStream f2=new FileOutputStream(args[1]); ObjectOutputStream b2=new ObjectOutputStream(f2); b2.writeObject(prk); } }
KeyShare.java
import java.security.PublicKey; import java.security.PrivateKey; import java.io.*; import javax.crypto.KeyAgreement; import javax.crypto.spec.*; public class KeyShare{ public static void main(String args[ ]) throws Exception{ File file=new File("Sharekey.dat"); // 读取对方的DH公钥 FileInputStream f1=new FileInputStream("Apub.dat"); ObjectInputStream b1=new ObjectInputStream(f1); PublicKey pbk=(PublicKey)b1.readObject( ); //读取自己的DH私钥 FileInputStream f2=new FileInputStream("Bpri.dat"); ObjectInputStream b2=new ObjectInputStream(f2); PrivateKey prk=(PrivateKey)b2.readObject( ); // 执行密钥协定 KeyAgreement ka=KeyAgreement.getInstance("DH"); ka.init(prk); ka.doPhase(pbk,true); //生成共享信息 byte[ ] sb=ka.generateSecret(); for(int i=0;i<sb.length;i++){ System.out.print(sb[i]+","); } OutputStream out=new FileOutputStream(file); out.write(sb); out.close(); SecretKeySpec k=new SecretKeySpec(sb,"AES"); } }
Servicetwo.java
import java.io.*; import java.net.*; public class Servicetwo { 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(5228); } 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 = AES.AESDncode(sharekey,keyone);//使用共享密钥对被加密的原密钥解密。 String secret =in.readUTF(); // in读取信息,堵塞状态 System.out.println("服务器收到的信息:"+secret); String clear = AES.AESDncode(truekey,secret);//使用原密钥解密表达式 MyDC d=new MyDC(); int answer=d.evaluate(clear); out.writeUTF(answer+""); System.out.println("服务器提供的解密:"+clear); Thread.sleep(500); } catch(Exception e) { System.out.println("客户已断开"+e); } } }
Clienttwo.java
import java.io.*; import java.net.*; import java.util.Scanner; public class Clienttwo { 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.toSuffix(str); String secret=AES.AESEncode(key1, str);//客户端对表达式进行加密 key1 = AES.AESEncode(sharekey,key1);//客户端对密钥进行DH加密 try{ mysocket=new Socket("127.1.0.0",5228); in=new DataInputStream(mysocket.getInputStream()); out=new DataOutputStream(mysocket.getOutputStream()); out.writeUTF(key1); out.writeUTF(secret); String s=in.readUTF(); //in读取信息,堵塞状态 System.out.println("客户收到服务器的回答:"+s); Thread.sleep(50000); } catch(Exception e) { System.out.println("服务器已断开"+e); } } }
3、运行结果如下:
任务五
1、实验要求
完整性校验结对编程:1人负责客户端,一人负责服务器
0. 注意责任归宿,要会通过测试证明自己没有问题
1. 基于Java Socket实现客户端/服务器功能,传输方式用TCP
2. 客户端让用户输入中缀表达式,然后把中缀表达式调用MyBC.java的功能转化为后缀表达式,把后缀表达式用3DES或AES算法加密通过网络把密文和明文的MD5値发送给服务器
3. 客户端和服务器用DH算法进行3DES或AES算法的密钥交换
4. 服务器接收到后缀表达式表达式后,进行解密,解密后计算明文的MD5值,和客户端传来的MD5进行比较,一致则调用MyDC.java的功能计算后缀表达式的值,把结果发送给客户端
5. 客户端显示服务器发送过来的结果
6. 上传测试结果截图和码云链接
2、实验内容
MD.java
import java.security.*; public class MD{ 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; } }
Servicethree.java
import java.io.*; import java.net.*; public class Servicethree { 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(5228); } 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 = AES.AESDncode(sharekey,keyone);//使用共享密钥对被加密的原密钥解密。 String secret =in.readUTF(); // in读取信息,堵塞状态 System.out.println("服务器收到的信息:"+secret); String mdClient=in.readUTF(); System.out.println("客户端提供的MD5为:"+ mdClient); String clear = AES.AESDncode(truekey,secret);//使用原密钥解密表达式 MyDC d=new MyDC(); int answer=d.evaluate(clear); if((mdClient.equals(MD.MD5(clear)))==true) {//判断MD5值是否相等,若相等,则返回答案 System.out.println("MD5值匹配"); System.out.println("服务器提供的解密:" + clear); System.out.println("服务器解出密文的MD5为:" + MD.MD5(clear)); out.writeUTF(answer + ""); } Thread.sleep(500); } catch(Exception e) { System.out.println("客户已断开"+e); } } }
Client.java
import java.io.*; import java.net.*; import java.util.Scanner; public class Clientthree { 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.toSuffix(str); String secret=AES.AESEncode(key1, str);//客户端对表达式进行加密 String md=MD.MD5(str);//客户端提供的MD5 key1 = AES.AESEncode(sharekey,key1);//客户端对密钥进行DH加密 try{ mysocket=new Socket("127.1.0.0",5228); 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); } } }
3、运行结果如下: