對稱非對稱算法混合加密實戰(DES和AES混合加密)


  •      最近需要用加密算法,開始研究加密算法,果然大學落下的需要全都補回來。淚奔啊!
  •      網上找各種資料,看別人的原理解釋看了了很多,使用非對稱算法和對稱算法混合加密在實際項目中是經常用的,但原理聽的差不多,沒有具體混合加密的可以參考的代碼,索性翻出以前寫的使用套接字創建服務端和客戶端的例子寫了個小程序,用來完整的模擬整個過程。
  •     大致思路是A生成一對公私鑰,將公鑰發送給B,B接收到后用這個公鑰加密對稱算法的密鑰,然后發送給A,A接收到后利用私鑰解密得到對稱算法的密鑰,俗稱會話密鑰,再將自己要發送的消息用會話密鑰加密,發送給B,B接收到后利用自己知道的會話密鑰解密,得到密文,這就是一個完整的過程。具體細節我不做贅述了,不專業,我也講不透。下面直接貼代碼。

 

  •      用Java實現的RSA算法和DES算法也是從網上搜刮來的,現在都忘了原帖在哪,感謝各位前輩。

 

  •      整個過程全都是原生JDK的東西實現的,只用到了Apache的一個Base64編碼工具,其實那個東西JDK也有自帶的,在java.xml.DataConventer這個包下面。不想下載Apache那個的,可以用這個代替。

RSA算法(非對稱算法)的實現:

  1 package socket;
  2 
  3 import org.apache.commons.codec.binary.Base64;
  4 
  5 import javax.crypto.Cipher;
  6 import java.security.*;
  7 import java.security.interfaces.RSAPrivateKey;
  8 import java.security.interfaces.RSAPublicKey;
  9 import java.security.spec.PKCS8EncodedKeySpec;
 10 import java.security.spec.X509EncodedKeySpec;
 11 import java.util.HashMap;
 12 import java.util.Map;
 13 
 14 
 15 /**
 16  * 非對稱加密算法RSA算法組件
 17  * 非對稱算法一般是用來傳送對稱加密算法的密鑰來使用的,相對於DH算法,RSA算法只需要一方構造密鑰,不需要
 18  * 大費周章的構造各自本地的密鑰對了。DH算法只能算法非對稱算法的底層實現。而RSA算法算法實現起來較為簡單
 19  *
 20  * @author kongqz
 21  */
 22 public class RSACoder {
 23     //非對稱密鑰算法
 24     public static final String KEY_ALGORITHM = "RSA";
 25 
 26 
 27     /**
 28      * 密鑰長度,DH算法的默認密鑰長度是1024
 29      * 密鑰長度必須是64的倍數,在512到65536位之間
 30      */
 31     private static final int KEY_SIZE = 512;
 32     //公鑰
 33     public static final String PUBLIC_KEY = "RSAPublicKey";
 34 
 35     //私鑰
 36     public static final String PRIVATE_KEY = "RSAPrivateKey";
 37 
 38     /**
 39      * 初始化密鑰對
 40      *
 41      * @return Map 甲方密鑰的Map
 42      */
 43     public static Map<String, Object> initKey() throws Exception {
 44         //實例化密鑰生成器
 45         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
 46         //初始化密鑰生成器
 47         keyPairGenerator.initialize(KEY_SIZE);
 48         //生成密鑰對
 49         KeyPair keyPair = keyPairGenerator.generateKeyPair();
 50         //甲方公鑰
 51         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 52         //甲方私鑰
 53         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 54         //將密鑰存儲在map中
 55         Map<String, Object> keyMap = new HashMap<String, Object>();
 56         keyMap.put(PUBLIC_KEY, publicKey);
 57         keyMap.put(PRIVATE_KEY, privateKey);
 58         return keyMap;
 59 
 60     }
 61 
 62 
 63     /**
 64      * 私鑰加密
 65      *
 66      * @param data 待加密數據
 67      * @param key       密鑰
 68      * @return byte[] 加密數據
 69      */
 70     public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
 71 
 72         //取得私鑰
 73         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
 74         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 75         //生成私鑰
 76         PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 77         //數據加密
 78         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 79         cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 80         return cipher.doFinal(data);
 81     }
 82 
 83     /**
 84      * 公鑰加密
 85      *
 86      * @param data 待加密數據
 87      * @param key       密鑰
 88      * @return byte[] 加密數據
 89      */
 90     public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
 91 
 92         //實例化密鑰工廠
 93         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 94         //初始化公鑰
 95         //密鑰材料轉換
 96         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
 97         //產生公鑰
 98         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 99 
100         //數據加密
101         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
102         cipher.init(Cipher.ENCRYPT_MODE, pubKey);
103         return cipher.doFinal(data);
104     }
105 
106     /**
107      * 私鑰解密
108      *
109      * @param data 待解密數據
110      * @param key  密鑰
111      * @return byte[] 解密數據
112      */
113     public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
114         //取得私鑰
115         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
116         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
117         //生成私鑰
118         PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
119         //數據解密
120         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
121         cipher.init(Cipher.DECRYPT_MODE, privateKey);
122         return cipher.doFinal(data);
123     }
124 
125     /**
126      * 公鑰解密
127      *
128      * @param data 待解密數據
129      * @param key  密鑰
130      * @return byte[] 解密數據
131      */
132     public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
133 
134         //實例化密鑰工廠
135         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
136         //初始化公鑰
137         //密鑰材料轉換
138         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
139         //產生公鑰
140         PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
141         //數據解密
142         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
143         cipher.init(Cipher.DECRYPT_MODE, pubKey);
144         return cipher.doFinal(data);
145     }
146 
147     /**
148      * 取得私鑰
149      *
150      * @param keyMap 密鑰map
151      * @return byte[] 私鑰
152      */
153     public static byte[] getPrivateKey(Map<String, Object> keyMap) {
154         Key key = (Key) keyMap.get(PRIVATE_KEY);
155         return key.getEncoded();
156     }
157 
158     /**
159      * 取得公鑰
160      *
161      * @param keyMap 密鑰map
162      * @return byte[] 公鑰
163      */
164     public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
165         Key key = (Key) keyMap.get(PUBLIC_KEY);
166         return key.getEncoded();
167     }
168 
169     /**
170      * @param args
171      * @throws Exception
172      */
173     public static void main(String[] args) throws Exception {
174         //初始化密鑰
175         //生成密鑰對
176         Map<String, Object> keyMap = RSACoder.initKey();
177         //公鑰
178         byte[] publicKey = RSACoder.getPublicKey(keyMap);
179 
180         //私鑰
181         byte[] privateKey = RSACoder.getPrivateKey(keyMap);
182         System.out.println("公鑰:/n" + Base64.encodeBase64String(publicKey));
183         System.out.println("私鑰:/n" + Base64.encodeBase64String(privateKey));
184 
185         System.out.println("================密鑰對構造完畢,甲方將公鑰公布給乙方,開始進行加密數據的傳輸=============");
186         String str = "RSA密碼交換算法";
187         System.out.println("/n===========甲方向乙方發送加密數據==============");
188         System.out.println("原文:" + str);
189         //甲方進行數據的加密
190         byte[] code1 = RSACoder.encryptByPrivateKey(str.getBytes(), privateKey);
191         System.out.println("加密后的數據:" + Base64.encodeBase64String(code1));
192         System.out.println("===========乙方使用甲方提供的公鑰對數據進行解密==============");
193         //乙方進行數據的解密
194         byte[] decode1 = RSACoder.decryptByPublicKey(code1, publicKey);
195         System.out.println("乙方解密后的數據:" + new String(decode1) + "/n/n");
196 
197         System.out.println("===========反向進行操作,乙方向甲方發送數據==============/n/n");
198 
199         str = "乙方向甲方發送數據RSA算法";
200 
201         System.out.println("原文:" + str);
202 
203         //乙方使用公鑰對數據進行加密
204         byte[] code2 = RSACoder.encryptByPublicKey(str.getBytes(), publicKey);
205         System.out.println("===========乙方使用公鑰對數據進行加密==============");
206         System.out.println("加密后的數據:" + Base64.encodeBase64String(code2));
207 
208         System.out.println("=============乙方將數據傳送給甲方======================");
209         System.out.println("===========甲方使用私鑰對數據進行解密==============");
210 
211         //甲方使用私鑰對數據進行解密
212         byte[] decode2 = RSACoder.decryptByPrivateKey(code2, privateKey);
213 
214         System.out.println("甲方解密后的數據:" + new String(decode2));
215     }
216 }

DES算法(對稱算法)的實現:

 1 package socket;
 2 
 3 import javax.crypto.Cipher;
 4 import javax.crypto.KeyGenerator;
 5 import javax.crypto.SecretKey;
 6 import javax.crypto.SecretKeyFactory;
 7 import javax.crypto.spec.DESKeySpec;
 8 
 9 import org.apache.commons.codec.binary.Base64;
10 import org.apache.commons.codec.binary.Hex;
11 
12 public class DES{
13     public byte[] bytes;
14     
15     //生成一個DES密鑰
16     public static String getKey(){
17         try {
18             KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
19             keyGenerator.init(56);
20             // 生成一個Key
21             SecretKey generateKey = keyGenerator.generateKey();
22             // 轉變為字節數組
23             byte[] encoded = generateKey.getEncoded();
24             // 生成密鑰字符串
25             String encodeHexString = Hex.encodeHexString(encoded);
26             return encodeHexString;
27         } catch (Exception e) {
28             e.printStackTrace();
29             return "密鑰生成錯誤.";
30         }   
31     }
32     
33     //加密
34     public static String encryptor(String str,String Key){
35         String s=null;
36         try {
37             DESKeySpec desKey = new DESKeySpec(Key.getBytes());
38             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
39             SecretKey securekey = keyFactory.generateSecret(desKey);
40             Cipher cipher = Cipher.getInstance("DES");
41             cipher.init(Cipher.ENCRYPT_MODE,securekey);    //初始化密碼器,用密鑰 secretKey 進入加密模式
42             byte[] bytes=cipher.doFinal(str.getBytes());   //加密
43             s= Base64.encodeBase64String(bytes);
44         } catch (Exception e) {
45             e.printStackTrace();
46             return "加密錯誤.";
47         }
48         return s;
49     }   
50 
51     //解密
52     public static String decryptor(String buff,String Key){
53         String s=null;
54         try {
55             DESKeySpec desKey = new DESKeySpec(Key.getBytes());
56             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
57             SecretKey securekey = keyFactory.generateSecret(desKey);
58             Cipher cipher = Cipher.getInstance("DES");
59             cipher.init(Cipher.DECRYPT_MODE,securekey);
60             byte[] responseByte=cipher.doFinal(Base64.decodeBase64(buff));
61             s=new String(responseByte);
62             return s;
63         } catch (Exception e) {
64             e.printStackTrace();
65             return "解密錯誤.";
66         }
67     }
68 }

一個消息輔助類:

1 package socket;
2 
3 public class MessageType {
4     public static final int PUBLIC_KEY_MESSAGE = 1;
5     public static final int SESSION_KEY_MESSAGE = 2;
6     public static final int CRYPTO_MESSAGE = 3;
7     public static final int RESULT_MESAAGE = 4;
8 }

服務端:

  1 package socket;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.OutputStream;
  6 import java.io.PrintWriter;
  7 import java.net.ServerSocket;
  8 import java.net.Socket;
  9 import java.util.Scanner;
 10 
 11 import org.apache.commons.codec.binary.Base64;
 12 
 13 public class Server {
 14     static ServerSocket serverSocket;
 15 
 16     public static void main(String[] args) {
 17         try {
 18             int i = 1;
 19             serverSocket = new ServerSocket(8001);
 20             System.out.println("服務器啟動,等待連接...");
 21             while (true) {
 22                 // 等待客戶端通過端口8001請求的連接
 23                 Socket socket = serverSocket.accept();
 24                 System.out.println(socket.getInetAddress().getHostAddress() + "上線,當前第" + i + "個");
 25                 Runnable runnable = new ThreadEchoHandler(socket);
 26                 Thread thread = new Thread(runnable);
 27                 thread.start();
 28                 i++;
 29             }
 30         } catch (IOException e) {
 31             e.printStackTrace();
 32         } finally {
 33             try {
 34                 serverSocket.close();
 35             } catch (IOException e) {
 36                 e.printStackTrace();
 37             }
 38         }
 39     }
 40 
 41 }
 42 
 43 class ThreadEchoHandler implements Runnable {
 44     private Socket incomingSocket;
 45     private Scanner scanner;
 46     private PrintWriter writer;
 47     private String key;
 48 
 49     public ThreadEchoHandler(Socket in) {
 50         incomingSocket = in;
 51         System.out.println("正在生成DES的密鑰...");
 52         key = DES.getKey();
 53         System.out.println("生成DES密鑰為:"+key);
 54     }
 55 
 56     public void run() {
 57         try {
 58             // 建立套接字的輸入輸出流
 59             InputStream inputStream = incomingSocket.getInputStream();
 60             OutputStream outputStream = incomingSocket.getOutputStream();
 61             // 將輸入流轉化為掃描器,輸出流轉化為寫入器
 62             scanner = new Scanner(inputStream);
 63             writer = new PrintWriter(outputStream, true);
 64 
 65             while(scanner.hasNext()) {
 66                 String backString = scanner.next();
 67                 String[] split = backString.split(":");
 68                 if(split.length>1) {
 69                     int flag = Integer.parseInt(split[0]);
 70                     switch(flag) {
 71                     case MessageType.PUBLIC_KEY_MESSAGE:
 72                         System.out.println("接收到客戶端的RSA的公鑰:"+split[1]);
 73                         System.out.println("=========用RSA公鑰加密DES會話密鑰=============");
 74                         byte[] decryptDesKey = RSACoder.encryptByPublicKey(key.getBytes(),Base64.decodeBase64(split[1]));
 75                         String decryptDesKeyString = Base64.encodeBase64String(decryptDesKey);
 76                         System.out.println("加密后的DES密鑰:" + decryptDesKeyString);
 77                         System.out.println("=========密鑰加密成功=============");
 78                         System.out.println("發送加密后的DES密鑰");
 79                         writer.println(MessageType.SESSION_KEY_MESSAGE+":"+decryptDesKeyString);
 80                         break;
 81                     case MessageType.CRYPTO_MESSAGE:
 82                         System.out.println("接收到密文為"+split[1]);
 83                         System.out.println("用DES會話密鑰解密密文...");
 84                         String message = DES.decryptor(split[1], key);
 85                         System.out.println("解密客戶端發過來的消息為:"+message);
 86                         String result = DES.encryptor("准奏!", key);
 87                         writer.println(MessageType.RESULT_MESAAGE+":"+result);
 88                         System.out.println("已處理相關請求,並回饋給客戶端!");
 89                         break;
 90                     }
 91                 }
 92             }
 93             System.out.println("客戶端已斷開連接,會話結束!");
 94         } catch (IOException e) {
 95             e.printStackTrace();
 96         } catch (Exception e) {
 97             e.printStackTrace();
 98         } finally {
 99             // 關閉套接字(很重要,防止造成資源浪費)
100             try {
101                 scanner.close();
102                 incomingSocket.close();
103             } catch (IOException e) {
104                 e.printStackTrace();
105             }
106         }
107     }
108 }

客戶端:

 1 package socket;                                                                                                                                                                                                                 
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.io.OutputStream;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 import java.net.UnknownHostException;
 9 import java.util.Map;
10 import java.util.Scanner;
11 
12 import org.apache.commons.codec.binary.Base64;
13 
14 public class Client {
15 public static void main(String[] args) throws Exception {
16     Socket socket=null;
17     InputStream inputStream=null;
18     OutputStream outputStream=null;
19     Scanner scanner=null;
20     PrintWriter writer=null;
21     String sessionKey=null;
22     
23     
24     try {
25         socket = new Socket("localhost",8001);
26         inputStream = socket.getInputStream();
27         outputStream = socket.getOutputStream();
28         scanner=new Scanner(inputStream);
29         writer= new PrintWriter(outputStream, true);
30         
31         Map<String, Object> initKey = null;
32         try {
33             initKey = RSACoder.initKey();
34             System.out.println("一對公私鑰生成成功,分別為:");
35             System.out.println("公鑰為:" + initKey.get(RSACoder.PUBLIC_KEY));
36             System.out.println("私鑰為:" + initKey.get(RSACoder.PRIVATE_KEY));
37         } catch (Exception e) {
38             e.printStackTrace();
39         }
40         System.out.println("正在發送RSA的公鑰給服務端...");
41         writer.println(MessageType.PUBLIC_KEY_MESSAGE+":"+Base64.encodeBase64String(RSACoder.getPublicKey(initKey)));
42         writer.flush();
43         
44         //* 開始接受服務端發送的消息
45         boolean notExit =true;
46         while(notExit&&scanner.hasNext()) {
47             String backString = scanner.next();
48             System.out.println(backString);
49             String[] split = backString.split(":");
50             if(split.length>1) {
51                 int flag = Integer.parseInt(split[0]);
52                 switch(flag) {
53                 case MessageType.SESSION_KEY_MESSAGE:
54                     System.out.println("接收到服務端發送的會話密鑰:"+split[1]);
55                     System.out.println("=========用RSA私鑰解密DES會話密鑰=============");
56                     byte[] sessionKey_byte = RSACoder.decryptByPrivateKey(Base64.decodeBase64(split[1]), RSACoder.getPrivateKey(initKey));
57                     sessionKey = new String(sessionKey_byte);
58                     System.out.println("DES會話密鑰解密完成:"+sessionKey);
59                     
60                     System.out.println("用DES密鑰將明文“能否午時三刻行刑?”加密...");
61                     String cipherText = DES.encryptor("能否午時三刻行刑?", sessionKey);
62                     System.out.println("加密過的明文為"+cipherText);
63                     System.out.println("======================");
64                     System.out.println("==========發送加密后的消息給服務器============");
65                     writer.println(MessageType.CRYPTO_MESSAGE+":"+cipherText);
66                     writer.flush();
67                     break;
68                 case MessageType.RESULT_MESAAGE:
69                     System.out.println("接收到服務端發送的處理結果密文:"+split[1]);
70                     System.out.println("=========用DES會話密鑰解密=============");
71                     String result = DES.decryptor(split[1], sessionKey);
72                     System.out.println("解密的明文為:"+result);
73                     System.out.println("==========所有流程結束============");
74                     notExit=false;
75                     break;
76                 }
77             }
78         }
79     } catch (UnknownHostException e) {
80         e.printStackTrace();
81     } catch (IOException e) {
82         e.printStackTrace();
83     }finally {
84         scanner.close();
85         inputStream.close();
86         outputStream.close();
87         socket.close();
88     }
89 }
90 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM