
Java socket通信实现DES加密与解密
DES是对称加密算法的其中一个,用一个密钥进行加密解密数据,安全性能比较低,效率较高,一些不太重要的数据可以使用DES加密算法进行加密解密传输,其他的3DES与AES用法类似。
流程图
首先认真看一下流程图,在脑海里过一遍,然后其实也就是分为以下两个过程,传输完密钥后,就可以使用这个密钥加密数据发送给服务器,服务器拿密钥解密数据,完事。
OK,直接贴代码吧,注意下Base64转码传输以及密钥的传输就行了。
Server 端
package des; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.security.InvalidKeyException; import java.security.Key; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; //DES加密 public class Server { public void openServer() throws IOException{ ServerSocket serverSocket=new ServerSocket(4400); Thread thread=null; Socket socket=null; while(true){ socket=serverSocket.accept(); thread=new Thread( new myThread(socket)); thread.start(); } } public static void main(String[] args){ try { new Server().openServer(); } catch (IOException e) { System.out.println(e.getMessage()); e.printStackTrace(); } } } class myThread implements Runnable{ private Socket socket; BufferedReader is; PrintWriter os; String passwd="bayaojiu.com"; Key key=null; public myThread(Socket socket){ this.socket=socket; try { is=new BufferedReader(new InputStreamReader(socket.getInputStream())); os=new PrintWriter(socket.getOutputStream()); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } public void run(){ try { DesKeyUtils des=new DesKeyUtils(); //接收到base64编码后的密钥字符串 String request=is.readLine(); //base64解密为普通二进制数组 byte decodeMsg[]=des.decoder.decode(request); //根据二进制数组转换成key对象 key=des.strToKey(decodeMsg); String passwdClient=null; //等待客户端发送密文 String response=is.readLine(); //用密钥将密文解密 passwdClient=des.decodeKey(response.getBytes(),key); System.out.println("receive:"+passwdClient); //等于密码就通过验证了 if(passwdClient.equals(passwd)) os.println("yes"); else os.println("false"); os.close(); is.close(); socket.close(); } catch (IOException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { } } }
Client 端
package des; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.security.Key; public class Client { private static DesKeyUtils des; private static Key publicKey; public static void main(String[] args) throws IOException { des=new DesKeyUtils(); //生成密钥 publicKey=des.generateSecrety(); connectServer(); } public static void connectServer() throws IOException{ String passwd="bayaojiu.com"; Socket socket=new Socket("127.0.0.1",4400); PrintWriter os=new PrintWriter(socket.getOutputStream()); BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream())); //转换成二进制数据进行保存 byte[]encodeData=publicKey.getEncoded(); //因为DES生成二进制数据中有ascii码无法显示的字符,传输的时候会丢失,所以我们使用base64进行无损传输 String request=des.encoder.encodeToString(encodeData); //发送给服务器 os.println(request); os.flush(); //根据Key对象对发送的内容进行加密,然后再将加密后的密文经过base64编码 String decodeMes=des.encodeKey(passwd.getBytes("UTF-8"),publicKey); //发送密文给服务器 os.println(decodeMes); os.flush(); //查看是否成功验证 System.out.println(is.readLine()); os.close(); is.close(); socket.close(); } }
然后我抽出来了一个加密解密类 DesKeyUtils
package des; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.util.Base64; 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.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class DesKeyUtils { private static Cipher cipher; final public static Base64.Decoder decoder=Base64.getDecoder(); final public static Base64.Encoder encoder=Base64.getEncoder(); //初始化 public DesKeyUtils(){ try { cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } //解密 public static String decodeKey(byte [] encodeKey,Key secretkey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ //先将经过base64编码的密文还原 encodeKey=decoder.decode(encodeKey); try { cipher.init(Cipher.DECRYPT_MODE, secretkey); //将原密文进行解密 return new String(cipher.doFinal(encodeKey),"UTF-8"); }catch(Exception e){ e.printStackTrace(); return null; } } //加密 public static String encodeKey(byte[] decodekey,Key secretkey){ try { cipher.init(Cipher.ENCRYPT_MODE, secretkey); //将明文加密成密文 byte[] encodeMsg=cipher.doFinal(decodekey); //将密文经过base64加密 return new String(encoder.encode(encodeMsg),"UTF-8"); } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | UnsupportedEncodingException e) { e.printStackTrace(); return null; } } //生成密钥 public static Key generateSecrety(){ KeyGenerator key; try { //生成 key = KeyGenerator.getInstance("DES"); key.init(56); SecretKey secretKey=key.generateKey(); byte[] bytesKey=secretKey.getEncoded(); //转换 DESKeySpec desKeySpec=new DESKeySpec(bytesKey); SecretKeyFactory factory =SecretKeyFactory.getInstance("DES"); Key convertSecretKey=factory.generateSecret(desKeySpec); return convertSecretKey; } catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); return null; } } //将二进制转换成Key对象,跟转换密钥那里差不多 public static Key strToKey(byte[] data){ Key convertSecretKey1=null; try { DESKeySpec desKeySpec=new DESKeySpec(data); SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); convertSecretKey1=factory.generateSecret(desKeySpec); return convertSecretKey1; } catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); return null; } } }
运行结果
Server:
———————————————————————————-
Client:
参考: