天天看點

AES和RSA:加密解密

最近生活亂七八糟,什麼都懶上了天。感覺自己會的東西好少

上司新配置設定了一個任務,讓我将http換成https,對參數進行加密

可選擇有兩個加密算法AES和RSA

由于公司内部使用,且資料量大,可以用私鑰。于是就用AES。

AES

1.概念

AES又叫Rijndael算法,是DES更新的加密标準,運作要求低,不需計算機有非常高的處理能力和大的記憶體;

操作可以很容易的抵禦時間和空間的攻擊,在不同的運作環境下始終保持良好的性能;

AES密鑰長度:最長隻有256bit,可用軟體和硬體實作高速處理;

密鑰管理:要求在通信前對密鑰進行秘密配置設定,解密的私鑰必須通過網絡傳送至加密資料接收方;

AES加密速度很快;

對稱加密;

2.幫助類

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

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;

import com.util.encrypt.Base64;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class AesEncrypt {
	private static final String AES_STR = "AES";
	private static final String SHA1PRNG_STR = "SHA1PRNG";
	
	public static String encrypt(String bef_aes, String password) {
		byte[] byteContent = null;
		try {
			byteContent = bef_aes.getBytes("utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return encrypt(byteContent,password);
	}
	public static String encrypt(byte[] content, String password) {
		try {
			SecretKey secretKey = getKey(password);
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES_STR);
			Cipher cipher = Cipher.getInstance(AES_STR);// 建立密碼器
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(content);
			String aft_aes = parseByte2HexStr(result);
			return aft_aes; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}
	public static String decrypt(String aft_aes_base64, String password,String charset){
		String aft_aes="";
		try {
			aft_aes = Base64.decode(aft_aes_base64);
			
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return decrypt(aft_aes,password);
		
	}
	public static String decrypt(String aft_aes, String password) {
		try {
			byte[] content = parseHexStr2Byte(aft_aes);
			SecretKey secretKey = getKey(password);
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES_STR);
			Cipher cipher = Cipher.getInstance(AES_STR);// 建立密碼器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(content);
			String bef_aes = new String(result);
			return bef_aes; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public static String parseByte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}
	public static byte[] parseHexStr2Byte(String hexStr) {   
        if (hexStr.length() < 1)   
                return null;   
        byte[] result = new byte[hexStr.length()/2];   
        for (int i = 0;i< hexStr.length()/2; i++) {   
                int value = Integer.parseInt(hexStr.substring(i*2, i*2+2), 16);   
                result[i] = (byte)value;   
        }   
        return result;   
}  
	public static SecretKey getKey(String strKey) {
	    try {	    	
	        KeyGenerator _generator = KeyGenerator.getInstance(AES_STR);
	        SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG_STR);
	        secureRandom.setSeed(strKey.getBytes());
	        _generator.init(128,secureRandom);
	       	return _generator.generateKey();
	    } catch (Exception e) {
	        throw new RuntimeException("初始化密鑰出現異常");
	    }
	  }	
	
	  /**
		  * AES的加密函數
		  * @param str 傳入需要加密的字元
		  * @param key 傳入一個16位長度的密鑰。否則報錯
		  * @return 執行成功傳回加密結果,否則報錯
		  * @throws Exception 抛出一個加密異常
		  */
		 @SuppressWarnings("restriction")
		public static String aesEncrypt(String str, String key) throws Exception {
		        if (str == null || key == null) return null;
		        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), "AES"));
		        byte[] bytes = cipher.doFinal(str.getBytes("utf-8"));
		        return new BASE64Encoder().encode(bytes);
		    }
		 /**
		  * AES的解密函數
		  * @param str 傳入需要解密的字元
		  * @param key 傳入一個16位長度的密鑰。否則報錯
		  * @return 執行成功傳回加密結果,否則報錯
		  * @throws Exception 抛出一個解密異常
		  */
		 @SuppressWarnings("restriction")
		    public static String aesDecrypt(String str, String key) throws Exception {
		        if (str == null || key == null) return null;
		        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), "AES"));
		        byte[] bytes = new BASE64Decoder().decodeBuffer(str);
		        bytes = cipher.doFinal(bytes);
		        return new String(bytes, "utf-8");
		    } 

}
           

3.controller

//如果參數的加密後的位元組流,則需要先解密然後轉Object
@RequestMapping(value="/ts",method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String aa(@RequestBody  String param)
{
byte[] byteContent = param.getBytes("utf-8");
String key="ABCDEFGHIJKLMNRS";//秘鑰
String  dataJson="";//加密内容
//去除Base64 和hex:用字元串形式看二進制代碼 将二進制轉化成16進制
String simpleResult = AesEncrypt.aesEncrypt(dataJson, key);//加密後的密文
String simpleContent= AesEncrypt.aesDecrypt(dataJson, key);//解密後的内容
String result = AesEncrypt.encrypt(dataJson, key);//加密後的密文
String content= AesEncrypt.decrypt(dataJson, key);//解密後的内容
}

           

RSA

1.概念

是公開密鑰系統的代表;

安全性:建立在具有大素數因子的合數,其因子分解困難這一法則之上;

處理速度慢;

密鑰管理:加解密過程中不必網絡傳輸保密的密鑰;密鑰管理優于AES算法;

RSA加解密速度慢,不适合大量資料檔案加密;

公鑰加密 私鑰解密

鑰加密 公鑰解密 使用簽名确定是否為該私鑰加密

2.使用

//非對稱密鑰算法
    public static final String KEY_ALGORITHM = "RSA";


    /**
     * 密鑰長度,DH算法的預設密鑰長度是1024
     * 密鑰長度必須是64的倍數,在512到65536位之間
     */
    private static final int KEY_SIZE = 512;
    //公鑰
    private static final String PUBLIC_KEY = "RSAPublicKey";

    //私鑰
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 初始化密鑰對
     *
     * @return Map 甲方密鑰的Map
     */
    public static Map<String, Object> initKey() throws Exception {
        //執行個體化密鑰生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        //初始化密鑰生成器
        keyPairGenerator.initialize(KEY_SIZE);
        //生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //甲方公鑰
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //甲方私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //将密鑰存儲在map中
        Map<String, Object> keyMap = new HashMap<String, Object>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;

    }


    /**
     * 私鑰加密
     *
     * @param data 待加密資料
     * @param key       密鑰
     * @return byte[] 加密資料
     */
    public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {

        //取得私鑰
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私鑰
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //資料加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰加密
     *
     * @param data 待加密資料
     * @param key       密鑰
     * @return byte[] 加密資料
     */
    public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {

        //執行個體化密鑰工廠
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公鑰
        //密鑰材料轉換
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        //産生公鑰
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);

        //資料加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }

    /**
     * 私鑰解密
     *
     * @param data 待解密資料
     * @param key  密鑰
     * @return byte[] 解密資料
     */
    public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
        //取得私鑰
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私鑰
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //資料解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公鑰解密
     *
     * @param data 待解密資料
     * @param key  密鑰
     * @return byte[] 解密資料
     */
    public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {

        //執行個體化密鑰工廠
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公鑰
        //密鑰材料轉換
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        //産生公鑰
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
        //資料解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }

    /**
     * 取得私鑰
     *
     * @param keyMap 密鑰map
     * @return byte[] 私鑰
     */
    public static byte[] getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }

    /**
     * 取得公鑰
     *
     * @param keyMap 密鑰map
     * @return byte[] 公鑰
     */
    public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }

           

使用

//初始化密鑰
      //生成密鑰對
      Map<String, Object> keyMap = initKey();
      //公鑰
      byte[] publicKey = getPublicKey(keyMap);

      //私鑰
      byte[] privateKey = getPrivateKey(keyMap);
      System.out.println("公鑰:/n" + Base64.encodeBase64String(publicKey));
      System.out.println("私鑰:/n" + Base64.encodeBase64String(privateKey));

      System.out.println("================密鑰對構造完畢,甲方将公鑰公布給乙方,開始進行加密資料的傳輸=============");
      String str = "RSA密碼交換算法";
      System.out.println("/n===========甲方向乙方發送加密資料==============");
      System.out.println("原文:" + str);
      //甲方進行資料的加密
      byte[] code1 = encryptByPrivateKey(str.getBytes(), privateKey);
      System.out.println("加密後的資料:" + Base64.encodeBase64String(code1));
      System.out.println("===========乙方使用甲方提供的公鑰對資料進行解密==============");
      //乙方進行資料的解密
      byte[] decode1 = decryptByPublicKey(code1, publicKey);
      System.out.println("乙方解密後的資料:" + new String(decode1) + "/n/n");

      System.out.println("===========反向進行操作,乙方向甲方發送資料==============/n/n");

      str = "乙方向甲方發送資料RSA算法";

      System.out.println("原文:" + str);

      //乙方使用公鑰對資料進行加密
      byte[] code2 =encryptByPublicKey(str.getBytes(), publicKey);
      System.out.println("===========乙方使用公鑰對資料進行加密==============");
      System.out.println("加密後的資料:" + Base64.encodeBase64String(code2));

      System.out.println("=============乙方将資料傳送給甲方======================");
      System.out.println("===========甲方使用私鑰對資料進行解密==============");

      //甲方使用私鑰對資料進行解密
      byte[] decode2 = decryptByPrivateKey(code2, privateKey);

      System.out.println("甲方解密後的資料:" + new String(decode2));