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:

 

 

 

参考:

https://blog.csdn.net/winfredzen/article/details/53539088

您或许感兴趣

[2018-04-13]TCP三次握手(详细解析)以及SYN攻击
[2018-06-05]RSA传递AES密钥进行通信(Java 实现)
[2018-06-24]nginx下laravel抽离public文件夹,与项目文件夹同级,并重建索引

发表评论

电子邮件地址不会被公开。