- 最近需要用加密算法,开始研究加密算法,果然大学落下的需要全都补回来。泪奔啊!
- 网上找各种资料,看别人的原理解释看了了很多,使用非对称算法和对称算法混合加密在实际项目中是经常用的,但原理听的差不多,没有具体混合加密的可以参考的代码,索性翻出以前写的使用套接字创建服务端和客户端的例子写了个小程序,用来完整的模拟整个过程。
- 大致思路是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 }