對稱加密(DES,AES,PBE)

定義

對稱加密的定義引用百度百科:java

    採用單鑰密碼系統的加密方法,同一個密鑰能夠同時用做信息的加密和解密,這種加密方法稱爲對稱加密,也稱爲單密鑰加密。算法

須要對加密和解密使用相同密鑰的加密算法。因爲其速度快,對稱性加密一般在消息發送方須要加密大量數據時使用。對稱性加密也稱爲密鑰加密.apache

    在使用加密算法時,複習下前面提到的java加密經常使用的類:安全

keyGenerator:祕鑰生成器,也就是根據算法類型隨機生成一個祕鑰,例如HMAC,因此這個大部分用在非可逆的算法中dom

SecretKeyFactory:祕密祕鑰工廠,言外之意就是須要根據一個祕密(password)去生成一個祕鑰,例如DES,PBE,因此大部分使用在對稱加密中ide

KeyPairGenerator:祕鑰對生成器,也就是能夠生成一對祕鑰,也就是公鑰和私鑰,因此大部分使用在非對稱加密中學習

種類

1.DES(Data Encryption Standard) 數據加密標準

    因爲DES發明比較早且長度爲56位,以目前的計算機運算能力存在被破解的風險,通常這種算法不經常使用只做爲學習加密算法的案例.測試

code:加密

/**
	 * jdk提供的DES算法實現
	 */
	public static void jdkDES(String content){
			try {
				//生成密鑰生成器
				KeyGenerator keyGenerator=KeyGenerator.getInstance("DES");
				keyGenerator.init(56);

//              密鑰生成器生成key
				SecretKey secretKey=keyGenerator.generateKey();
				byte[] encoded = secretKey.getEncoded();
				
				
			 //  DESKeySpec對象 DESKeySpec(byte[] key)
//  key能夠使用密鑰生成生成的key或者自定義密碼password(密碼,長度要是8的倍數)
				DESKeySpec desKeySpec=new DESKeySpec("12345678".getBytes());
//			DESKeySpec desKeySpec=new DESKeySpec(encoded);
				
				SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("DES");
				Key key = secretKeyFactory.generateSecret(desKeySpec);
				
//				加密
//				Cipher.getInstance("DES/ECB/PKCS5Padding"); 參數爲 算法/工做模式/填充方式
//				Cipher cipher=Cipher.getInstance("DES"); //默認的工做模式/填充方式
				Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");
				
				cipher.init(Cipher.ENCRYPT_MODE, key);
				byte[] encrypt = cipher.doFinal(content.getBytes());
				System.out.println("jdk DES encrypt:"+new  BASE64Encoder().encode(encrypt));
				
//				解密 
//				使用同一密鑰key
				cipher.init(Cipher.DECRYPT_MODE, key);
				byte[]  decrypt = cipher.doFinal(encrypt);
				System.out.println("jdk DES decrypt:"+ new String(decrypt));
			} catch (Exception e) {
				e.printStackTrace();
			}
		
	}

若是要使用BC 第三方提供的DES算法,主要在第一行 加入spa

                Security.addProvider(new BouncyCastleProvider());
                //生成密鑰生成器
                KeyGenerator keyGenerator=KeyGenerator.getInstance("DES","BC");

便可,在此不贅述.

2.  3DES(3重DES,又稱DESede) 

    增長了密鑰長度和迭代次數,安全性更高.

code:

/**
	 * jdk提供的DES算法實現 
	 */
	public static void jdk3DES(String content){
			try {
				
				Security.addProvider(new BouncyCastleProvider());
				//生成密鑰生成器
				KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede","BC");//bc 提供
				keyGenerator.init(168);//112 or 168
				SecretKey secretKey=keyGenerator.generateKey();
				byte[] encoded = secretKey.getEncoded();
				
				
			 //  DESKeySpec對象 DESKeySpec(byte[] key)  key能夠使用密鑰生成器或者自定義密碼password(密碼,長度要是8的倍數)
//				DESKeySpec desKeySpec=new DESKeySpec("12345678".getBytes());
			DESedeKeySpec desKeySpec=new DESedeKeySpec(encoded);
				
				SecretKeyFactory secretKeyFactory=SecretKeyFactory.getInstance("DESede");
				Key key = secretKeyFactory.generateSecret(desKeySpec);
				
//				加密
//				Cipher.getInstance("DES/ECB/PKCS5Padding"); 參數爲 算法/工做模式/填充方式
//				Cipher cipher=Cipher.getInstance("DES"); //默認的工做模式/填充方式
				Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding");
				
				cipher.init(Cipher.ENCRYPT_MODE, key);
				byte[] encrypt = cipher.doFinal(content.getBytes());
				System.out.println("jdk DESede encrypt:"+new  BASE64Encoder().encode(encrypt));
				
//				解密 
//				使用同一密鑰key
				cipher.init(Cipher.DECRYPT_MODE, key);
				byte[]  decrypt = cipher.doFinal(encrypt);
				System.out.println("jdk DESede decrypt:"+ new String(decrypt));
			} catch (Exception e) {
				e.printStackTrace();
			}
		
	}

大體上與DES相同 ,只是密鑰長度必須112或者168

3.AES(目前使用比較普遍的對稱加密算法)

code:

/**
	 * JDK 提供的AES 實現
	 */
	public static void jdkAES(String content){
		 //建立密鑰生成器
		try {
			KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
			keyGenerator.init(128);
//			keyGenerator.init(128,new SecureRandom("123456".getBytes("UTF-8")));//或者加上自定義的密碼
			//生成器生成key
			SecretKey generateKey = keyGenerator.generateKey();
			byte[] keyBytes = generateKey.getEncoded();
			
			//根據算法轉換相應的Key
			Key key=new SecretKeySpec(keyBytes, "AES");
			
			//加密
			Cipher cipher=Cipher.getInstance("AES");
			cipher.init(Cipher.ENCRYPT_MODE, key);
			byte[] encrypt = cipher.doFinal(content.getBytes());
			System.out.println("JDK AES encrypt:"+Hex.encodeHexString(encrypt));
			
			//解密
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] decrypt = cipher.doFinal(encrypt);
			System.out.println("JDK AES decrypt:"+new String(decrypt));
			
		} catch (Exception  e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

4. PBE(Password Base Encryption,基於口令加密)

          4.1  PBE算法(Password Base Encryption,基於口令加密)算法是一種基於口令的加密算法。特色在於口令由用戶本身掌握,採用隨機數(咱們這裏叫作 鹽)雜湊多重加密等方法保證數據的安全性。

  PBE算法沒有密鑰的概念,把口令當作密鑰了。由於密鑰長短影響算法安全性,還不方便記憶,這裏咱們直接換成咱們本身經常使用的口令就大大不一樣了,便於咱們的記憶。可是單純的口令很容易被字典法給窮舉出來,因此咱們這裏給口令加了點「鹽」,這個鹽和口令組合,想破解就難了。

            4.2 模型分析

這裏咱們仍是假設甲乙雙發要傳遞消息,須要口令和鹽還有算法

傳統的對稱加密算法就是,構建密鑰,指定算法,而後發送數據前用密鑰加密數據,密鑰和加密後的數據一塊兒發送給對方,對方拿着密鑰對數據進行解密。

 如今是密鑰沒有了,咱們就用「口令+鹽」構造出一個密鑰,而後對數據進行加密

 這裏「口令」咱們能夠隨便設置,均可以設置成咱們開本身電腦的密碼

 這裏「鹽」的設置能夠採用隨機數,能夠是甲乙雙方約定的數據

 最終咱們的口令和鹽都要公佈給雙方

一、消息傳遞雙方約定口令,這裏甲方構建口令

二、甲方構建口令後,公佈給乙方

三、由口令構建方(甲方)構建本次消息傳遞使用的鹽,其實也能夠雙方約定一個數據,例如硬盤號,今天的日期等等,不必定非要寫個安全算法計算出來,只要雙方一致就行

四、甲方使用口令、鹽對數據加密

五、甲方將鹽、加密數據發送給消息接收者(乙方)

六、乙方用收到的口令、鹽(能夠是約定的數據)對數據進行解密

圖解:

 

整體看來口令和鹽兩邊都須要知道。消息傳遞過程仍是須要指定雙方的統一算法進行。而這些算法其實仍是用的那些常見的對稱加密算法.

4.3: code:

package com.fitc.soldier.service.common;
	
	import java.security.Key;
	import java.security.SecureRandom;
	
	import javax.crypto.Cipher;
	import javax.crypto.SecretKey;
	import javax.crypto.SecretKeyFactory;
	import javax.crypto.spec.PBEKeySpec;
	import javax.crypto.spec.PBEParameterSpec;
	
	import org.apache.commons.codec.binary.Base64;
	
	public class PBEdemo {
		
		/**
		 * 實例算法
		 */
		 public static final String ALGORITHM="PBEWITHMD5andDES";  
		    /** 
		     * 迭代次數 
		     * */  
		public static final int ITERATION_COUNT=100;  
		
		
		 /** 
	     * 使用PBE算法對數據進行加解密 
	     * @throws Exception  
	     *  
	     */  
	    public static void main(String[] args) throws Exception {  
	        //待加密數據  
	        String str="這是測試數據!!!";  
	        //設定的口令密碼  
	        String password="azsxdc";  
	          
	        System.out.println("原文:\t"+str);  
	        System.out.println("密碼:\t"+password);  
	          
	        //初始化鹽  
	        byte[] salt=PBEdemo.initSalt();  
	        System.out.println("鹽:\t"+Base64.encodeBase64String(salt));  
	        //加密數據  
	        byte[] data=PBEdemo.encrypt(str.getBytes(), password, salt);  
	        System.out.println("加密後:\t"+Base64.encodeBase64String(data));  
	        //解密數據  
	        data=PBEdemo.decrypt(data, password, salt);  
	        System.out.println("解密後:"+new String(data));  
	    }  
		
		/** 
	     * 鹽初始化 
	     * 鹽長度必須爲8字節 
	     * @return byte[] 鹽 
	     * */  
	    public static byte[] initSalt() throws Exception{  
	        //實例化安全隨機數  
	        SecureRandom random=new SecureRandom();  
	        //產出鹽  
	        return random.generateSeed(8);  
	    } 
	    
	    /** 
	     * 轉換密鑰 
	     * @param password 密碼 
	     * @return Key 密鑰 
	     * */  
	    private static Key toKey(String password) throws Exception{  
	        //密鑰彩禮轉換  
	        PBEKeySpec keySpec=new PBEKeySpec(password.toCharArray());  
	        //實例化  
	        SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(ALGORITHM);  
	        //生成密鑰  
	        SecretKey secretKey=keyFactory.generateSecret(keySpec);  
	          
	        return secretKey;  
	    }  
	
	    /** 
	     * 加密 
	     * @param data 待加密數據 
	     * @param password 密碼 
	     * @param salt 鹽 
	     * @return byte[] 加密數據 
	     *  
	     * */  
	    public static byte[] encrypt(byte[] data,String password,byte[] salt) throws Exception{  
	        //轉換密鑰  
	        Key key=toKey(password);  
	        //實例化PBE參數材料  
	        PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);  
	        //實例化  
	        Cipher cipher=Cipher.getInstance(ALGORITHM);  
	        //初始化  
	        cipher.init(Cipher.ENCRYPT_MODE, key,paramSpec);  
	        //執行操做  
	        return cipher.doFinal(data);  
	    }  
	    /** 
	     * 解密 
	     * @param data 待解密數據 
	     * @param password 密碼 
	     * @param salt 鹽 
	     * @return byte[] 解密數據 
	     *  
	     * */  
	    public static byte[] decrypt(byte[] data,String password,byte[] salt) throws Exception{  
	        //轉換密鑰  
	        Key key=toKey(password);  
	        //實例化PBE參數材料  
	        PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);  
	        //實例化  
	        Cipher cipher=Cipher.getInstance(ALGORITHM);  
	        //初始化  
	        cipher.init(Cipher.DECRYPT_MODE, key,paramSpec);  
	        //執行操做  
	        return cipher.doFinal(data);  
	    }  
	}

輸出結果:

相關文章
相關標籤/搜索