兩人一組結對編程:結對對象 20175223 姚明宇
html
http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA
MyBC.java
MyDC.java
import java.util.*; import java.util.stream.Collectors; import java.lang.Integer; public class MyBC{ private static final Mapbasic = new HashMap (); static { basic.put('-', 1); basic.put('+', 1); basic.put('*', 2); basic.put('/', 2); basic.put('(', 0); } //中綴表達式 轉 後綴表達式 public static String toSuffix(String infix){ List queue = new ArrayList (); List stack = new ArrayList (); 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(" ")); } }
import java.util.StringTokenizer; import java.util.Stack; import java.lang.Integer; public class MyDC { /** * constant for addition symbol */ private final char ADD = '+'; /** * constant for subtraction symbol */ private final char SUBTRACT = '-'; /** * constant for multiplication symbol */ private final char MULTIPLY = '*'; /** * constant for division symbol */ private final char DIVIDE = '/'; /** * the stack */ private Stackstack; public MyDC() { stack = new Stack ( ); } public int evaluate(String expr) { int op1, op2, result = 0; String token; StringTokenizer tokenizer = new StringTokenizer (expr); while (tokenizer.hasMoreTokens ( )) { token = tokenizer.nextToken ( ); //若是是運算符,調用isOperator if (isOperator(token)==true) { op2=stack.pop(); op1=stack.pop(); //從棧中彈出操做數2 //從棧中彈出操做數1 result=evalSingleOp(token.charAt(0),op1,op2); //根據運算符和兩個操做數調用evalSingleOp計算result; stack.push(result); //計算result入棧; } else//若是是操做數 { stack.push(Integer.parseInt(token)); } //操做數入棧; } return result; } private boolean isOperator(String token) { return (token.equals ("+") || token.equals ("-") || token.equals ("*") || token.equals ("/")); } private int evalSingleOp(char operation, int op1, int op2) { int result = 0; switch (operation) { case ADD: result = op1 + op2; break; case SUBTRACT: result = op1 - op2; break; case MULTIPLY: result = op1 * op2; break; case DIVIDE: result = op1 / op2; break; default:return 0; } return result; } }
//import junit.framework.TestCase; 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"); } } }
import java.util.Scanner; public class MyBCTest { public static void main(String[] args) { MyBC mybc = new MyBC (); MyDC mydc = new MyDC (); String inExpression; String str2; Scanner reader = new Scanner (System.in); System.out.println ("IEnter a expression: "); inExpression = reader.nextLine (); str2 = mybc.toSuffix (inExpression); System.out.println ("str2: " +str2); System.out.println ("result: " +mydc.evaluate(str2)); } }
結對編程:20175233嚴順堯
負責客戶端,20175223姚明宇
負責服務器java
import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Scanner; public class Client { public static void main(String args[]) { Scanner reader = new Scanner (System.in); System.out.println ("客戶輸入一箇中綴表達式: "); String str = reader.nextLine (); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket ("127.0.0.1", 2010); in = new DataInputStream (mysocket.getInputStream ( )); out = new DataOutputStream (mysocket.getOutputStream ( )); out.writeUTF (str); //in讀取信息,堵塞狀態 String temp = in.readUTF ( ); System.out.println ("客戶收到服務器的後綴表達式:\n" + temp); String answer = in.readUTF ( ); System.out.println ("客戶收到服務器的計算結果:\n" + answer); Thread.sleep (500); } catch (Exception e) { System.out.println ("服務器已斷開" + e); } } }
import java.io.*; import java.net.*; public class Server { public static void main(String args[]) { String question, temp, answer; MyDC mydc = new MyDC (); ServerSocket serverForClient = null; Socket socketOnServer = null; DataOutputStream out = null; DataInputStream in = null; try { serverForClient = new ServerSocket (2010); } catch (IOException e1) { System.out.println (e1); } try { System.out.println ("等待客戶呼叫"); //堵塞狀態,除非有客戶呼叫 socketOnServer = serverForClient.accept ( ); out = new DataOutputStream (socketOnServer.getOutputStream ( )); in = new DataInputStream (socketOnServer.getInputStream ( )); // in讀取信息,堵塞狀態 question = in.readUTF ( ); System.out.println ("服務器收到客戶的中綴表達式:\n" + question); temp = MyBC.toSuffix (question); System.out.println ("服務器將中綴表達式變形爲後綴表達式:\n" +temp); out.writeUTF (temp); answer = String.valueOf(mydc.evaluate(temp)); out.writeUTF (answer); Thread.sleep (500); } catch (Exception e) { System.out.println ("客戶已斷開" + e); } } }
import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.lang.*; public class AES { public static String ecodes(String content, String key) { if (content == null || content.length ( ) < 1) { return null; } try { KeyGenerator kgen = KeyGenerator.getInstance ("AES"); SecureRandom random = SecureRandom.getInstance ("SHA1PRNG"); random.setSeed (key.getBytes ( )); kgen.init (128, random); SecretKey secretKey = kgen.generateKey ( ); byte[] enCodeFormat = secretKey.getEncoded ( ); SecretKeySpec secretKeySpec = new SecretKeySpec (enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance ("AES"); byte[] byteContent = content.getBytes ("utf-8"); cipher.init (Cipher.ENCRYPT_MODE, secretKeySpec); byte[] byteRresult = cipher.doFinal (byteContent); StringBuffer sb = new StringBuffer ( ); for (int i = 0; i < byteRresult.length; i++) { String hex = Integer.toHexString (byteRresult[i] & 0xFF); if (hex.length ( ) == 1) { hex = '0' + hex; } sb.append (hex.toUpperCase ( )); } return sb.toString ( ); } catch (NoSuchAlgorithmException e) { e.printStackTrace ( ); } catch (NoSuchPaddingException e) { e.printStackTrace ( ); } catch (InvalidKeyException e) { e.printStackTrace ( ); } catch (UnsupportedEncodingException e) { e.printStackTrace ( ); } catch (IllegalBlockSizeException e) { e.printStackTrace ( ); } catch (BadPaddingException e) { e.printStackTrace ( ); } return null; } public static String dcodes(String content, String key) { if (content == null || content.length ( ) < 1) { return null; } if (content.trim ( ).length ( ) < 19) { return content; } byte[] byteRresult = new byte[content.length ( ) / 2]; for (int i = 0; i < content.length ( ) / 2; i++) { int high = Integer.parseInt (content.substring (i * 2, i * 2 + 1), 16); int low = Integer.parseInt (content.substring (i * 2 + 1, i * 2 + 2), 16); byteRresult[i] = (byte) (high * 16 + low); } try { KeyGenerator kgen = KeyGenerator.getInstance ("AES"); SecureRandom random = SecureRandom.getInstance ("SHA1PRNG"); random.setSeed (key.getBytes ( )); kgen.init (128, random); SecretKey secretKey = kgen.generateKey ( ); byte[] enCodeFormat = secretKey.getEncoded ( ); SecretKeySpec secretKeySpec = new SecretKeySpec (enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance ("AES"); cipher.init (Cipher.DECRYPT_MODE, secretKeySpec); byte[] result = cipher.doFinal (byteRresult); return new String (result); } 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 ( ); } return null; } }
import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Scanner; public class ClientAES { public static void main(String args[]) { Scanner reader = new Scanner (System.in); System.out.println ("客戶輸入一箇中綴表達式: "); String str = reader.nextLine (); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket ("127.0.0.1", 2010); in = new DataInputStream (mysocket.getInputStream ( )); out = new DataOutputStream (mysocket.getOutputStream ( )); String key = "20175223yaomingyushidashuaibi111"; //輸入密文,32字符密鑰 String miwen = AES.ecodes(str,key); out.writeUTF (miwen); //in讀取信息,堵塞狀態 String temp = in.readUTF ( ); String answer = in.readUTF ( ); Thread.sleep (500); } catch (Exception e) { System.out.println ("服務器已斷開" + e); } } }
import java.io.*; import java.net.*; public class ServerAES { public static void main(String args[]) { String miwen, temp, answer; MyDC mydc = new MyDC (); ServerSocket serverForClient = null; Socket socketOnServer = null; DataOutputStream out = null; DataInputStream in = null; try { serverForClient = new ServerSocket (2010); } catch (IOException e1) { System.out.println (e1); } try { System.out.println ("等待客戶呼叫"); socketOnServer = serverForClient.accept ( ); out = new DataOutputStream (socketOnServer.getOutputStream ( )); in = new DataInputStream (socketOnServer.getInputStream ( )); // in讀取信息,堵塞狀態 miwen = in.readUTF ( ); System.out.println ("服務器收到客戶的密文:\n" + miwen); String key = "20175223yaomingyushidashuaibi111"; String mingwen = AES.dcodes(miwen, key); temp = MyBC.toSuffix (mingwen); System.out.println ("服務器將中綴表達式變形爲後綴表達式:\n" +temp); out.writeUTF (temp); answer = String.valueOf(mydc.evaluate(temp)); out.writeUTF (answer); Thread.sleep (500); } catch (Exception e) { System.out.println ("客戶已斷開" + e); } } }
import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * 非對稱加密算法DH算法組件 * 非對稱算法通常是用來傳送對稱加密算法的密鑰來使用的,因此這裏咱們用DH算法模擬密鑰傳送 * 對稱加密AES算法繼續作咱們的數據加解密 * @author kongqz * */ public class DH { //非對稱密鑰算法 public static final String KEY_ALGORITHM="DH"; //本地密鑰算法,即對稱加密算法。可選des,aes,desede public static final String SECRET_ALGORITHM="AES"; /** * 密鑰長度,DH算法的默認密鑰長度是1024 * 密鑰長度必須是64的倍數,在512到1024位之間 * */ private static final int KEY_SIZE=512; //公鑰 private static final String PUBLIC_KEY="DHPublicKey"; //私鑰 private static final String PRIVATE_KEY="DHPrivateKey"; /** * 初始化甲方密鑰 * @return Map 甲方密鑰的Map * */ public static MapinitKey() throws Exception{ //實例化密鑰生成器 KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化密鑰生成器 keyPairGenerator.initialize(KEY_SIZE); //生成密鑰對 KeyPair keyPair=keyPairGenerator.generateKeyPair(); //甲方公鑰 DHPublicKey publicKey=(DHPublicKey) keyPair.getPublic(); //甲方私鑰 DHPrivateKey privateKey=(DHPrivateKey) keyPair.getPrivate(); //將密鑰存儲在map中 Map keyMap=new HashMap (); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 初始化乙方密鑰 * @param key 甲方密鑰(這個密鑰是經過第三方途徑傳遞的) * @return Map 乙方密鑰的Map * */ public static Map initKey(byte[] key) throws Exception{ //解析甲方的公鑰 //轉換公鑰的材料 X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key); //實例化密鑰工廠 KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM); //產生公鑰 PublicKey pubKey=keyFactory.generatePublic(x509KeySpec); //由甲方的公鑰構造乙方密鑰 DHParameterSpec dhParamSpec=((DHPublicKey)pubKey).getParams(); //實例化密鑰生成器 KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(keyFactory.getAlgorithm()); //初始化密鑰生成器 keyPairGenerator.initialize(dhParamSpec); //產生密鑰對 KeyPair keyPair=keyPairGenerator.genKeyPair(); //乙方公鑰 DHPublicKey publicKey=(DHPublicKey)keyPair.getPublic(); //乙方私鑰 DHPrivateKey privateKey=(DHPrivateKey)keyPair.getPrivate(); //將密鑰存儲在Map中 Map keyMap=new HashMap (); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 加密 * @param data 待加密數據 * @param key 密鑰 * @return byte[] 加密數據 * */ public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ //生成本地密鑰 SecretKey secretKey=new SecretKeySpec(key,SECRET_ALGORITHM); //數據加密 Cipher cipher=Cipher.getInstance(secretKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 解密 * @param data 待解密數據 * @param key 密鑰 * @return byte[] 解密數據 * */ public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ //生成本地密鑰 SecretKey secretKey=new SecretKeySpec(key,SECRET_ALGORITHM); //數據解密 Cipher cipher=Cipher.getInstance(secretKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(data); } /** * 構建密鑰 * @param publicKey 公鑰 * @param privateKey 私鑰 * @return byte[] 本地密鑰 * */ public static byte[] getSecretKey(byte[] publicKey,byte[] privateKey) throws Exception{ //實例化密鑰工廠 KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM); //初始化公鑰 //密鑰材料轉換 X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(publicKey); //產生公鑰 PublicKey pubKey=keyFactory.generatePublic(x509KeySpec); //初始化私鑰 //密鑰材料轉換 PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(privateKey); //產生私鑰 PrivateKey priKey=keyFactory.generatePrivate(pkcs8KeySpec); //實例化 KeyAgreement keyAgree=KeyAgreement.getInstance(keyFactory.getAlgorithm()); //初始化 keyAgree.init(priKey); keyAgree.doPhase(pubKey, true); //生成本地密鑰 SecretKey secretKey=keyAgree.generateSecret(SECRET_ALGORITHM); return secretKey.getEncoded(); } /** * 取得私鑰 * @param keyMap 密鑰map * @return byte[] 私鑰 * */ public static byte[] getPrivateKey(Map keyMap){ Key key=(Key)keyMap.get(PRIVATE_KEY); return key.getEncoded(); } /** * 取得公鑰 * @param keyMap 密鑰map * @return byte[] 公鑰 * */ public static byte[] getPublicKey(Map keyMap) throws Exception{ Key key=(Key) keyMap.get(PUBLIC_KEY); return key.getEncoded(); } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { //生成甲方的密鑰對 Map keyMap1=DH.initKey(); //甲方的公鑰 byte[] publicKey1=DH.getPublicKey(keyMap1); //甲方的私鑰 byte[] privateKey1=DH.getPrivateKey(keyMap1); System.out.println("甲方公鑰:/n"+Base64.encodeBase64String(publicKey1)); System.out.println("甲方私鑰:/n"+Base64.encodeBase64String(privateKey1)); //由甲方的公鑰產生的密鑰對 Map keyMap2=DH.initKey(publicKey1); byte[] publicKey2=DH.getPublicKey(keyMap2); byte[] privateKey2=DH.getPrivateKey(keyMap2); System.out.println("乙方公鑰:/n"+Base64.encodeBase64String(publicKey2)); System.out.println("乙方私鑰:/n"+Base64.encodeBase64String(privateKey2)); //組裝甲方的本地加密密鑰,由乙方的公鑰和甲方的私鑰組合而成 byte[] key1=DH.getSecretKey(publicKey2, privateKey1); System.out.println("甲方的本地密鑰:/n"+Base64.encodeBase64String(key1)); //組裝乙方的本地加密密鑰,由甲方的公鑰和乙方的私鑰組合而成 byte[] key2=DH.getSecretKey(publicKey1, privateKey2); System.out.println("乙方的本地密鑰:/n"+Base64.encodeBase64String(key2)); System.out.println("================密鑰對構造完畢,開始進行加密數據的傳輸============="); String str="密碼交換算法"; System.out.println("/n===========甲方向乙方發送加密數據=============="); System.out.println("原文:"+str); System.out.println("===========使用甲方本地密鑰對進行數據加密=============="); //甲方進行數據的加密 byte[] code1=DH.encrypt(str.getBytes(), key1); System.out.println("加密後的數據:"+Base64.encodeBase64String(code1)); System.out.println("===========使用乙方本地密鑰對數據進行解密=============="); //乙方進行數據的解密 byte[] decode1=DH.decrypt(code1, key2); System.out.println("乙方解密後的數據:"+new String(decode1)+"/n/n"); System.out.println("===========反向進行操做,乙方向甲方發送數據==============/n/n"); str="乙方向甲方發送數據DH"; System.out.println("原文:"+str); //使用乙方本地密鑰對數據進行加密 byte[] code2=DH.encrypt(str.getBytes(), key2); System.out.println("===========使用乙方本地密鑰對進行數據加密=============="); System.out.println("加密後的數據:"+Base64.encodeBase64String(code2)); System.out.println("=============乙方將數據傳送給甲方======================"); System.out.println("===========使用甲方本地密鑰對數據進行解密=============="); //甲方使用本地密鑰對數據進行解密 byte[] decode2=DH.decrypt(code2, key1); System.out.println("甲方解密後的數據:"+new String(decode2)); } }
import org.apache.commons.codec.binary.Base64; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Map; import java.util.Scanner; public class ClientDH { public static void main(String args[]) { String cipherText, plainText, answer; Scanner reader = new Scanner (System.in); System.out.println ("客戶輸入一箇中綴表達式: "); String str = reader.nextLine (); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket ("127.0.0.1", 2010); in = new DataInputStream (mysocket.getInputStream ( )); out = new DataOutputStream (mysocket.getOutputStream ( )); //設立AES算法的32字符密鑰,輸入密文與密鑰 String AES_Key = "20175223yaomingyushidashuaibi111"; //將中綴表達式變形爲後綴表達式 plainText = MyBC.toSuffix (str); System.out.println ("後綴表達式明文:\n" + plainText); //將後綴表達式明文經過AES加密,並將後綴表達式密文發往客戶端 cipherText = AES.ecodes (plainText, AES_Key); System.out.println ("後綴表達式密文:\n" + cipherText + "\n"); //out發送信息 out.writeUTF (cipherText); //對AES算法的32字符密鑰進行DH算法加密 //生成甲方的密鑰對 MapkeyMap1 = DH.initKey ( ); //甲方的公鑰 byte[] publicKey1 = DH.getPublicKey (keyMap1); //甲方的私鑰 byte[] privateKey1 = DH.getPrivateKey (keyMap1); System.out.println ("甲方公鑰:/n" + Base64.encodeBase64String (publicKey1)); System.out.println ("甲方私鑰:/n" + Base64.encodeBase64String (privateKey1)); String tempKey1 = Base64.encodeBase64String (publicKey1); //out發送信息 out.writeUTF (tempKey1); //組裝甲方的本地加密密鑰,由乙方的公鑰和甲方的私鑰組合而成 //in讀取信息,堵塞狀態 String tempKey2 = in.readUTF ( ); byte[] publicKey2 = Base64.decodeBase64 (tempKey2); System.out.println ("乙方公鑰:/n" + Base64.encodeBase64String (publicKey1)); byte[] key1 = DH.getSecretKey (publicKey2, privateKey1); System.out.println ("甲方的本地密鑰:/n" + Base64.encodeBase64String (key1)); //甲方使用本地密鑰對AES_Key進行消息加密,併發給乙方 byte[] code1 = DH.encrypt (AES_Key.getBytes ( ), key1); System.out.println ("甲方使用本地密鑰對AES_Key進行加密後的數據:" + Base64.encodeBase64String (code1)); //out發送信息,333333 out.writeUTF (Base64.encodeBase64String (code1)); //接受乙方的計算結果 answer = in.readUTF ( ); System.out.println ("\n**計算由服務器進行**\n\n客戶收到服務器的計算結果:\n" + answer); Thread.sleep (500); } catch (Exception e) { System.out.println ("服務器已斷開" + e); } } }
import org.apache.commons.codec.binary.Base64; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Map; public class ServerDH { public static void main(String args[]) { String cipherText, plainText, answer; MyDC mydc = new MyDC ( ); ServerSocket serverForClient = null; Socket socketOnServer = null; DataOutputStream out = null; DataInputStream in = null; try { serverForClient = new ServerSocket (2010); } catch (IOException e1) { System.out.println (e1); } try { System.out.println ("等待客戶呼叫"); //堵塞狀態,除非有客戶呼叫 socketOnServer = serverForClient.accept ( ); out = new DataOutputStream (socketOnServer.getOutputStream ( )); in = new DataInputStream (socketOnServer.getInputStream ( )); // in讀取信息,堵塞狀態,111111 cipherText = in.readUTF ( ); System.out.println ("服務器收到客戶的後綴表達式密文:\n" + cipherText + "\n"); //由甲方的公鑰產生的密鑰對 // in讀取信息,堵塞狀態,2222222 String tempKey1 = in.readUTF ( ); byte[] publicKey1 = Base64.decodeBase64 (tempKey1); System.out.println ("甲方公鑰:/n" + Base64.encodeBase64String (publicKey1)); MapkeyMap2 = DH.initKey (publicKey1); byte[] publicKey2 = DH.getPublicKey (keyMap2); byte[] privateKey2 = DH.getPrivateKey (keyMap2); System.out.println ("乙方公鑰:/n" + Base64.encodeBase64String (publicKey2)); System.out.println ("乙方私鑰:/n" + Base64.encodeBase64String (privateKey2)); //爲組裝甲方的本地加密密鑰,將乙方的公鑰發給甲方 String tempKey2 = Base64.encodeBase64String (publicKey2); //out發送信息,333333 out.writeUTF (tempKey2); //組裝乙方的本地加密密鑰,由甲方的公鑰和乙方的私鑰組合而成 byte[] key2 = DH.getSecretKey (publicKey1, privateKey2); System.out.println ("乙方的本地密鑰:/n" + Base64.encodeBase64String (key2)); //接受甲方的AES_Key的加密信息,對其解密 byte[] code1 = Base64.decodeBase64 (in.readUTF ( )); byte[] decode1 = DH.decrypt (code1, key2); String AES_Key = new String (decode1); System.out.println ("\n乙方解密後的AES_Key數據:" + AES_Key); //使用解密後的AES_Key對後綴表達式密文解密,並算出結果 plainText = AES.dcodes (cipherText, AES_Key); System.out.println ("\nAES_Key對後綴表達式密文解密:\n" + plainText); answer = String.valueOf (mydc.evaluate (plainText)); //將計算結果發給甲方 out.writeUTF (answer); System.out.println ("\n**結果由客戶端進行輸出**" ); Thread.sleep (500); } catch (Exception e) { System.out.println ("客戶已斷開" + e); } } }
import java.security.*; public class Md5{ public static String numberMD5(String plainTest) throws Exception{ String x=plainTest; MessageDigest m=MessageDigest.getInstance("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); } return result; } }
import org.apache.commons.codec.binary.Base64; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Map; public class ServerMd5 { public static void main(String args[]) { String cipherText, plainText, answer; MyDC mydc = new MyDC ( ); ServerSocket serverForClient = null; Socket socketOnServer = null; DataOutputStream out = null; DataInputStream in = null; try { serverForClient = new ServerSocket (2010); } catch (IOException e1) { System.out.println (e1); } try { System.out.println ("等待客戶呼叫"); //堵塞狀態,除非有客戶呼叫 socketOnServer = serverForClient.accept ( ); out = new DataOutputStream (socketOnServer.getOutputStream ( )); in = new DataInputStream (socketOnServer.getInputStream ( )); // in讀取信息,堵塞狀態,111111 cipherText = in.readUTF ( ); System.out.println ("服務器收到客戶的後綴表達式密文:\n" + cipherText + "\n"); //由甲方的公鑰產生的密鑰對 // in讀取信息,堵塞狀態,2222222 String tempKey1 = in.readUTF ( ); byte[] publicKey1 = Base64.decodeBase64 (tempKey1); System.out.println ("甲方公鑰:/n" + Base64.encodeBase64String (publicKey1)); MapkeyMap2 = DH.initKey (publicKey1); byte[] publicKey2 = DH.getPublicKey (keyMap2); byte[] privateKey2 = DH.getPrivateKey (keyMap2); System.out.println ("乙方公鑰:/n" + Base64.encodeBase64String (publicKey2)); System.out.println ("乙方私鑰:/n" + Base64.encodeBase64String (privateKey2)); //爲組裝甲方的本地加密密鑰,將乙方的公鑰發給甲方 String tempKey2 = Base64.encodeBase64String (publicKey2); //out發送信息,333333 out.writeUTF (tempKey2); //組裝乙方的本地加密密鑰,由甲方的公鑰和乙方的私鑰組合而成 byte[] key2 = DH.getSecretKey (publicKey1, privateKey2); System.out.println ("乙方的本地密鑰:/n" + Base64.encodeBase64String (key2)); //接受甲方的AES_Key的加密信息,對其解密 byte[] code1 = Base64.decodeBase64 (in.readUTF ( )); byte[] decode1 = DH.decrypt (code1, key2); String AES_Key = new String (decode1); System.out.println ("\n乙方解密後的AES_Key數據:" + AES_Key); //使用解密後的AES_Key對後綴表達式密文解密,並算出結果 plainText = AES.dcodes (cipherText, AES_Key); String md5zhi2 =Md5.numberMD5(plainText); String md5zhi1 =in.readUTF ( ); if(md5zhi2.equals(md5zhi1))System.out.println ("\n能解密"); else System.out.println ("\n不能解密"); System.out.println ("\nAES_Key對後綴表達式密文解密:\n" + plainText); answer = String.valueOf (mydc.evaluate (plainText)); //將計算結果發給甲方 out.writeUTF (answer); System.out.println ("\n**結果由客戶端進行輸出**" ); Thread.sleep (500); } catch (Exception e) { System.out.println ("客戶已斷開" + e); } } }
import org.apache.commons.codec.binary.Base64; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Map; import java.util.Scanner; public class ClientMd5 { public static void main(String args[]) { String cipherText, plainText, answer; Scanner reader = new Scanner (System.in); System.out.println ("客戶輸入一箇中綴表達式: "); String str = reader.nextLine (); Socket mysocket; DataInputStream in = null; DataOutputStream out = null; try { mysocket = new Socket ("127.0.0.1", 2010); in = new DataInputStream (mysocket.getInputStream ( )); out = new DataOutputStream (mysocket.getOutputStream ( )); //設立AES算法的32字符密鑰,輸入密文與密鑰 String AES_Key = "20175223yaomingyushidashuaibi111"; //將中綴表達式變形爲後綴表達式 plainText = MyBC.toSuffix (str); String md5zhi1 =Md5.numberMD5(plainText); System.out.println ("後綴表達式明文:\n" + plainText); //將後綴表達式明文經過AES加密,並將後綴表達式密文發往客戶端 cipherText = AES.ecodes (plainText, AES_Key); System.out.println ("後綴表達式密文:\n" + cipherText + "\n"); //out發送信息 out.writeUTF (cipherText); //對AES算法的32字符密鑰進行DH算法加密 //生成甲方的密鑰對 MapkeyMap1 = DH.initKey ( ); //甲方的公鑰 byte[] publicKey1 = DH.getPublicKey (keyMap1); //甲方的私鑰 byte[] privateKey1 = DH.getPrivateKey (keyMap1); System.out.println ("甲方公鑰:/n" + Base64.encodeBase64String (publicKey1)); System.out.println ("甲方私鑰:/n" + Base64.encodeBase64String (privateKey1)); String tempKey1 = Base64.encodeBase64String (publicKey1); //out發送信息 out.writeUTF (tempKey1); //組裝甲方的本地加密密鑰,由乙方的公鑰和甲方的私鑰組合而成 //in讀取信息,堵塞狀態 String tempKey2 = in.readUTF ( ); byte[] publicKey2 = Base64.decodeBase64 (tempKey2); System.out.println ("乙方公鑰:/n" + Base64.encodeBase64String (publicKey1)); byte[] key1 = DH.getSecretKey (publicKey2, privateKey1); System.out.println ("甲方的本地密鑰:/n" + Base64.encodeBase64String (key1)); //甲方使用本地密鑰對AES_Key進行消息加密,併發給乙方 byte[] code1 = DH.encrypt (AES_Key.getBytes ( ), key1); System.out.println ("甲方使用本地密鑰對AES_Key進行加密後的數據:" + Base64.encodeBase64String (code1)); //out發送信息,333333 out.writeUTF (Base64.encodeBase64String (code1)); out.writeUTF(md5zhi1); //接受乙方的計算結果 answer = in.readUTF ( ); System.out.println ("\n**計算由服務器進行**\n\n客戶收到服務器的計算結果:\n" + answer); Thread.sleep (500); } catch (Exception e) { System.out.println ("服務器已斷開" + e); } } }
out.writeUTF()
; 傳輸後沒法正確接收,變爲亂碼客戶端:git
//經過 `Base64` 的方法 `encodeBase64String ();` 將數組轉化爲字符串類型 String tempKey1 = Base64.encodeBase64String (publicKey1); //out發送信息 out.writeUTF (tempKey1);
服務器:算法
...... //由客戶端的公鑰產生的密鑰對 String tempKey1 = in.readUTF (); byte [] publicKey1 = tempKey1.getBytes (); System.out.println("客戶端公鑰:/n"+Base64.encodeBase64String(publicKey1)); Map<String,Object> keyMap2=DH.initKey(publicKey1); ......
報錯:密鑰格式不對。express
由於 out.writeUTF()
in.readUTF ()
傳輸的數據類型爲 String
,而不是 byte []
數組,因此不可用 getBytes ()
方法來提取。
要使用 Base64 方法 encodeBase64String ()
的對應的方法 decodeBase64 (tempKey1)
來轉換數據類型。apache
String tempKey1 = in.readUTF ( ); byte[] publicKey1 = Base64.decodeBase64 (tempKey1); System.out.println ("客戶端公鑰:/n" + Base64.encodeBase64String (publicKey1)); Map <String, Object> keyMap2 = DH.initKey (publicKey1);