对称非对称算法混合加密实战(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 }
原文地址:https://www.cnblogs.com/plumsq/p/10646893.html