DES、3DES、AES、PBE對稱加密算法實現(xiàn)及應(yīng)用
1.對稱加密算法概述
對稱加密算法是應(yīng)用較早的加密算法,技術(shù)成熟。在對稱加密算法中,數(shù)據(jù)發(fā)信方將明文和加密密鑰一起經(jīng)過特殊加密算法處理后,使其變成復(fù)雜的加密密文發(fā)送出去。收信方收到密文后,若想解讀原文,則需要使用加密用過的密鑰及相同算法的逆算法對密文進(jìn)行解密,才能使其恢復(fù)成可讀明文。
在對稱加密算法中,使用的密鑰只有一個,發(fā)收信雙方都使用這個密鑰對數(shù)據(jù)進(jìn)行加密和解密,這就要求解密方事先必須知道加密密鑰。
對稱加密算法的特點是算法公開、計算量小、加密速度快、加密效率高。
不足之處是,交易雙方都使用同樣鑰匙,安全性得不到保證。
在計算機系統(tǒng)中廣泛使用的對稱加密算法有DES和IDEA等。因為DES近年來屢屢被破解,所以,美國國家標(biāo)準(zhǔn)局倡導(dǎo)的AES即將作為新標(biāo)準(zhǔn)取代DES。
2.對稱加密算法-DES
DES算法為密碼體制中的對稱密碼體制,又被稱為美國數(shù)據(jù)加密標(biāo)準(zhǔn),是1972年美國IBM公司研制的對稱密碼體制加密算法。
明文按64位進(jìn)行分組,密鑰長64位,密鑰事實上是56位參與DES運算(第8、16、24、32、40、48、56、64位是校驗位, 使得每個密鑰都有奇數(shù)個1)分組后的明文組和56位的密鑰按位替代或交換的方法形成密文組的加密方法。
引入Bouncy Castle依賴:
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15</artifactId>
- <version>1.46</version>
- </dependency>
引入Commons Codec依賴:
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.10</version>
- </dependency>
Java代碼實現(xiàn):
- import java.security.Key;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.DESKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class DES {
- public static final String src = "des test";
- public static void main(String[] args) {
- jdkDES();
- bcDES();
- }
- // 用jdk實現(xiàn):
- public static void jdkDES() {
- try {
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
- keyGenerator.init(56);
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] bytesKey = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("jdk des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用bouncy castle實現(xiàn):
- public static void bcDES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DES", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(56);
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] bytesKey = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("bc des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
應(yīng)用例子:
3.對稱加密算法-3DES
密碼學(xué)中,三重數(shù)據(jù)加密算法(英語:Triple Data Encryption Algorithm,縮寫為TDEA,Triple DEA),或稱3DES(Triple DES),是一種對稱密鑰加密塊密碼,相當(dāng)于是對每個數(shù)據(jù)塊應(yīng)用三次數(shù)據(jù)加密標(biāo)準(zhǔn)(DES)算法。由于計算機運算能力的增強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES即是設(shè)計用來提供一種相對簡單的方法,即通過增加DES的密鑰長度來避免類似的攻擊,而不是設(shè)計一種全新的塊密碼算法。
Java代碼實現(xiàn):
- import java.security.Key;
- import java.security.SecureRandom;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.DESedeKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class DES3 {
- public static final String src = "3des test";
- public static void main(String[] args) {
- jdk3DES();
- bc3DES();
- }
- // 用jdk實現(xiàn):
- public static void jdk3DES() {
- try {
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
- // 必須長度是:112或168
- // keyGenerator.init(168);
- keyGenerator.init(new SecureRandom());
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] bytesKey = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk 3des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("jdk 3des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用bouncy castle實現(xiàn):
- public static void bc3DES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(168);
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] bytesKey = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc 3des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("bc 3des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
4.對稱加密算法-AES
高級加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard,縮寫:AES),在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。這個標(biāo)準(zhǔn)用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程,高級加密標(biāo)準(zhǔn)由美國國家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197,并在2002年5月26日成為有效的標(biāo)準(zhǔn)。2006年,高級加密標(biāo)準(zhǔn)已然成為對稱密鑰加密中最流行的算法之一。
該算法為比利時密碼學(xué)家Joan Daemen和Vincent Rijmen所設(shè)計,結(jié)合兩位作者的名字,以Rijndael為名投稿高級加密標(biāo)準(zhǔn)的甄選流程。(Rijndael的發(fā)音近于"Rhine doll")
Java代碼實現(xiàn):
- import java.security.Key;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class AES {
- public static final String src = "aes test";
- public static void main(String[] args) {
- jdkAES();
- bcAES();
- }
- // 用jdk實現(xiàn):
- public static void jdkAES() {
- try {
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
- keyGenerator.init(128);
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] keyBytes = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- Key key = new SecretKeySpec(keyBytes, "AES");
- // 加密
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk aes encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key);
- result = cipher.doFinal(result);
- System.out.println("jdk aes decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用bouncy castle實現(xiàn):
- public static void bcAES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(128);
- // 產(chǎn)生密鑰
- SecretKey secretKey = keyGenerator.generateKey();
- // 獲取密鑰
- byte[] keyBytes = secretKey.getEncoded();
- // KEY轉(zhuǎn)換
- Key key = new SecretKeySpec(keyBytes, "AES");
- // 加密
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc aes encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key);
- result = cipher.doFinal(result);
- System.out.println("bc aes decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
5.對稱加密算法-PBE
PBE算法(Password Based Encryption,基于口令加密)是一種基于口令的加密算法,其特點是使用口令代替了密鑰,而口令由用戶自己掌管,采用隨機數(shù)雜湊多重加密等方法保證數(shù)據(jù)的安全性。
PBE算法在加密過程中并不是直接使用口令來加密,而是加密的密鑰由口令生成,這個功能由PBE算法中的KDF函數(shù)完成。KDF函數(shù)的實現(xiàn)過程為:將用戶輸入的口令首先通過“鹽”(salt)的擾亂產(chǎn)生準(zhǔn)密鑰,再將準(zhǔn)密鑰經(jīng)過散列函數(shù)多次迭代后生成最終加密密鑰,密鑰生成后,PBE算法再選用對稱加密算法對數(shù)據(jù)進(jìn)行加密,可以選擇DES、3DES、RC5等對稱加密算法。
具體實現(xiàn)如下:
Java代碼實現(xiàn):
- import java.security.Key;
- import java.security.SecureRandom;
- import javax.crypto.Cipher;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.PBEKeySpec;
- import javax.crypto.spec.PBEParameterSpec;
- import org.apache.commons.codec.binary.Hex;
- public class PBE {
- public static final String src = "pbe test";
- public static void main(String[] args) {
- jdkPBE();
- }
- // 用jdk實現(xiàn):
- public static void jdkPBE() {
- try {
- // 初始化鹽
- SecureRandom random = new SecureRandom();
- byte[] salt = random.generateSeed(8);
- // 口令與密鑰
- String password = "timliu";
- PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
- SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
- Key key = factory.generateSecret(pbeKeySpec);
- // 加密
- PBEParameterSpec pbeParameterSpac = new PBEParameterSpec(salt, 100);
- Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
- cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpac);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk pbe encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpac);
- result = cipher.doFinal(result);
- System.out.println("jdk pbe decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
應(yīng)用舉例: