课前预备

首先,今天所要用到的知识是

①对称加密算法AES

②非对称加密算法RSA

注:

一:对称加密是通过单一密钥对传输的文本进行加解密的,常见的对称加密有,从强度低到高(DES,3DES,AES)

▲对称加密

二:非对称加密是通过一对key进行加解的,公钥加密,私钥解密,私钥签名,公钥验证,相对于对称加密而言,效率较低,安全性高。常见的非对称加密有,(DH,RSA)

▲非对称加密

 

为什么要非对称加密与对称加密结合这么做呢,上篇文章当中,我们模拟了TCP传输DES密钥(AES密钥是现在对称加密中最不容易被破解的)进行加解密传输,但是若是我们一开始传递的密钥被盗取了,还是存在一定的风险,所以后来人们就使用非对称加密进行传输数据,但是由于非对称加密的效率较低,后来又演变成非对称加密进行传递对称加密生成的密钥,然后之后的通信就使用这个密钥进行通信。

▲RSA加密与AES加密混合的通信方式

 

知道了流程,接下来就很容易了,开搞

package other;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

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.spec.SecretKeySpec;

public class RsaEncoding {
	private final static String KEYTYPE="RSA";
	
	private final static String AesKeyType="AES";
	
	private final static String AesCipherType="AES/ECB/PKCS5Padding";
	
	private final static String KEY_RSA_SIGNATURE="MD5withRSA";
	
	private final static String KEY_RSA_PUBLICKEY="RSAPublicKey";
	
	private final static String KEY_RSA_PRIVATEKEY="RSAPrivateKey";
	
	private final static Base64.Decoder decoder=Base64.getDecoder();
	
	private final static Base64.Encoder encoder=Base64.getEncoder();
	
	
	//生成公钥与私钥
	public static Map<String,Object>init(){
		Map<String,Object> map=null;
		try {
			KeyPairGenerator generator=KeyPairGenerator.getInstance(KEYTYPE);
			generator.initialize(1024);
			KeyPair keyPair=generator.generateKeyPair();
			//publicKey
			RSAPublicKey publicKey=(RSAPublicKey)keyPair.getPublic();
			//privateKey
			RSAPrivateKey privateKey=(RSAPrivateKey)keyPair.getPrivate();
			//put into map
			map=new HashMap();
			map.put(KEY_RSA_PRIVATEKEY, privateKey);
			map.put(KEY_RSA_PUBLICKEY, publicKey);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return map;
	}
	
	//从map中获取私钥
	public static String getPrivateKey(Map<String,Object> map){
		String str="";
		Key key=(Key)map.get(KEY_RSA_PRIVATEKEY);
		str=encoder.encodeToString(key.getEncoded());
		return str;
	}
	
	//从map中获取公钥
	public static String getPublicKey(Map<String,Object> map){
		String str="";
		Key key=(Key)map.get(KEY_RSA_PUBLICKEY);
		str=encoder.encodeToString(key.getEncoded());
		return str;
	}
	
	//使用私钥进行解密
	public static byte[]decryptByPrivateKey(byte[] data,String key){
		byte[] result=null;
		
		try{
			byte[]bytes=decoder.decode(key);
			//gain privateKey
			PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(bytes);
			KeyFactory factory=KeyFactory.getInstance(KEYTYPE);
			PrivateKey privateKey=factory.generatePrivate(keySpec);
			
			//decrypt data
			Cipher cipher=Cipher.getInstance(factory.getAlgorithm());
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			result=cipher.doFinal(data);
		}catch(Exception e){
			e.printStackTrace();
		}
		return result;
	}
	
	//使用公钥进行加密
	public static byte[]encryptByPublicKey(byte[]data,String Key){
		byte []result=null;
		try {
			byte[]bytes=decoder.decode(Key);
			//gain an publicKey
			X509EncodedKeySpec keySpec=new X509EncodedKeySpec(bytes);
			KeyFactory factory;
			factory = KeyFactory.getInstance(KEYTYPE);
			PublicKey publicKey=factory.generatePublic(keySpec);
			
			//encrypt data
			Cipher cipher=Cipher.getInstance(factory.getAlgorithm());
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			result=cipher.doFinal(data);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return result;
	}
	
	//使用私钥进行签名,返回数字签名字符串
	public static String sign(byte[]data,String privateKey){
		String str="";
		try{
			byte[]bytes=decoder.decode(privateKey);
			PKCS8EncodedKeySpec pkcs=new PKCS8EncodedKeySpec(bytes);
			KeyFactory factory =KeyFactory.getInstance(KEYTYPE);
			PrivateKey key=factory.generatePrivate(pkcs);
			
			Signature signature=Signature.getInstance(KEY_RSA_SIGNATURE);
			signature.initSign(key);
			signature.update(data);
			str=encoder.encodeToString(signature.sign());
		}catch(Exception e){
			e.printStackTrace();
		}
		return str;
	}
	
	//由数字签名字符串以及数据然后使用公钥进行验证,返回正证明数字签名是由私钥进行签名的
	public static boolean verify (byte[]data,String publicKey,String sign){
		boolean flag=false;
		try{
			byte[]bytes=decoder.decode(publicKey);
			X509EncodedKeySpec keySpec=new X509EncodedKeySpec(bytes);
			KeyFactory factory=KeyFactory.getInstance(KEYTYPE);
			PublicKey key=factory.generatePublic(keySpec);
			
			Signature signature=Signature.getInstance(KEY_RSA_SIGNATURE);
			signature.initVerify(key);
			signature.update(data);
			flag=signature.verify(decoder.decode(sign));
		}catch(Exception e){
			e.printStackTrace();
		}  
		return flag;
	}
	
	//生成AES密钥
	public static String generateAesKey(){
		String str="";
		
		try{
			KeyGenerator keyGenerator=KeyGenerator.getInstance(AesKeyType);
			keyGenerator.init(128);
			SecretKey secretKey=keyGenerator.generateKey();
			byte[] keyBytes=secretKey.getEncoded();
			str=encoder.encodeToString(keyBytes);
		}catch(Exception e){
			e.printStackTrace();
		}
		return str;
	}
        //字节类型的密钥转换成Key对象
	public static Key keyByteToKey(byte []bytes){
		SecretKeySpec spec=null;
		try{
			spec=new SecretKeySpec(decoder.decode(bytes),AesKeyType);
		}catch(Exception e){
			e.printStackTrace();
		}
		return spec;
	}
	
        //使用AES密钥进行加密数据
	public static byte[] encryptDataWithAes(byte[]data,String Secretkey){
		byte[] str=null;
		try{
			Key key=keyByteToKey(Secretkey.getBytes());
			Cipher cipher=Cipher.getInstance(AesCipherType);
			cipher.init(Cipher.ENCRYPT_MODE, key);
			str=cipher.doFinal(data);
		}catch(Exception e){
			e.printStackTrace();
		}
		return str;
	}
	
        //使用AES密钥进行解密数据
	public static String decryptDataWithAes(byte[]data,String Secretkey){
		String str=null;
		try{
			Key key=keyByteToKey(Secretkey.getBytes());
			Cipher cipher=Cipher.getInstance(AesCipherType);
			cipher.init(Cipher.DECRYPT_MODE, key);
			str=new String(cipher.doFinal(data));
		}catch(Exception e){
			e.printStackTrace();
		}
		return str;
	}
	
        //测试运行类
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		String privateKey="";
		String publicKey="";
		String secretKey=""; 
		
		Map<String,Object>map=init();
		publicKey=getPublicKey(map);
		privateKey=getPrivateKey(map);
		secretKey=generateAesKey();
		
		System.out.println("公钥: \n" + publicKey);  
        System.out.println("私钥: \n" + privateKey);  
        System.out.println("公钥加密--------私钥解密");  
        byte[]encWord=encryptByPublicKey(secretKey.getBytes(),publicKey);
        String decWord=new String(decryptByPrivateKey(encWord, privateKey));
        System.out.println("加密前密钥:"+secretKey+"   解密后密钥:"+decWord);
       
        System.out.println("\n数据加密--------数据解密");  
        String data="This is data;这是数据;";
        byte[]encData= encryptDataWithAes(data.getBytes(),decWord);
        String deData=decryptDataWithAes(encData, decWord);
        System.out.println("加密前数据:"+data+"   解密后数据:"+deData);
        
        /*
        //生成数字签名
        String sign=sign(encWord,privateKey);
        System.out.println("数字签名:"+sign);
        
        //验证数字签名
        boolean status=verify(encWord,publicKey,sign);
        System.out.println("签名状态:"+status);
        */
	}

}

运行结果

 

参考资料:

https://blog.csdn.net/happylee6688/article/details/45218801 

您或许感兴趣

[2018-05-16]Java socket通信实现DES加密与解密
[2018-04-13]TCP三次握手(详细解析)以及SYN攻击
[2018-06-24]nginx下laravel抽离public文件夹,与项目文件夹同级,并重建索引
[2018-07-01]Redis-Cluster集群的理解和搭建

发表评论

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