DES、3DES、AES、PBE對稱加密算法實現及應用

【本文版權歸微信公衆號"代碼藝術"(ID:onblog)全部,如果轉載請務必保留本段原創聲明,違者必究。如果文章有不足之處,歡迎關注微信公衆號私信與我進行交流!】java

1.對稱加密算法概述

對稱加密算法是應用較早的加密算法,技術成熟。在對稱加密算法中,數據發信方將明文和加密密鑰一塊兒通過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則須要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢復成可讀明文。算法

在對稱加密算法中,使用的密鑰只有一個,發收信雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰。apache

對稱加密算法的特色是算法公開、計算量小、加密速度快、加密效率高。安全

不足之處是,交易雙方都使用一樣鑰匙,安全性得不到保證。微信

在計算機系統中普遍使用的對稱加密算法有DES和IDEA等。由於DES近年來屢屢被破解,因此,美國國家標準局倡導的AES即將做爲新標準取代DES。dom

2.對稱加密算法-DES

DES算法爲密碼體制中的對稱密碼體制,又被稱爲美國數據加密標準,是1972年美國IBM公司研製的對稱密碼體制加密算法。ide

明文按64位進行分組,密鑰長64位,密鑰事實上是56位參與DES運算(第八、1六、2四、3二、40、4八、5六、64位是校驗位, 使得每一個密鑰都有奇數個1)分組後的明文組和56位的密鑰按位替代或交換的方法造成密文組的加密方法。函數

密鑰長度 默認 工做模式 填充方式 實現方
56 56 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到12八、OFB、OFB8到128 NoPadding、PKCS5Padding、ISO10126Padding JDK
64 56 同上 PKCS7Padding、ISO10126d2Padding、X932Padding、ISO7816d4Padding、ZeroBytePadding BC

引入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代碼實現:

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實現:
  public static void jdkDES() {
    try {
      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
      keyGenerator.init(56);
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] bytesKey = secretKey.getEncoded();

      // KEY轉換
      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實現:
  public static void bcDES() {
    try {
      Security.addProvider(new BouncyCastleProvider());

      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("DES", "BC");
      keyGenerator.getProvider();
      keyGenerator.init(56);
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] bytesKey = secretKey.getEncoded();

      // KEY轉換
      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();
    }
  }
}

應用例子:

3.對稱加密算法-3DES

密碼學中,三重數據加密算法(英語:Triple Data Encryption Algorithm,縮寫爲TDEA,Triple DEA),或稱3DES(Triple DES),是一種對稱密鑰加密塊密碼,至關因而對每一個數據塊應用三次數據加密標準(DES)算法。因爲計算機運算能力的加強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES便是設計用來提供一種相對簡單的方法,即經過增長DES的密鑰長度來避免相似的***,而不是設計一種全新的塊密碼算法。

Java代碼實現:

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實現:
  public static void jdk3DES() {
    try {
      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
      // 必須長度是:112或168
//			keyGenerator.init(168);
      keyGenerator.init(new SecureRandom());
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] bytesKey = secretKey.getEncoded();

      // KEY轉換
      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實現:
  public static void bc3DES() {
    try {
      Security.addProvider(new BouncyCastleProvider());

      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede", "BC");
      keyGenerator.getProvider();
      keyGenerator.init(168);
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] bytesKey = secretKey.getEncoded();

      // KEY轉換
      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

【本文版權歸微信公衆號"代碼藝術"(ID:onblog)全部,如果轉載請務必保留本段原創聲明,違者必究。如果文章有不足之處,歡迎關注微信公衆號私信與我進行交流!】

高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣爲全世界所使用。通過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日發佈於FIPS PUB 197,並在2002年5月26日成爲有效的標準。2006年,高級加密標準已然成爲對稱密鑰加密中最流行的算法之一。

該算法爲比利時密碼學家Joan Daemen和Vincent Rijmen所設計,結合兩位做者的名字,以Rijndael爲名投稿高級加密標準的甄選流程。(Rijndael的發音近於"Rhine doll")

密鑰長度 默認 工做模式 填充方式 實現方
12八、19二、256 128 ECB、CBC、PCBC、CTR、CTS、CFB、CFB8到12八、OFB、OFB8到128 NoPadding、PKCS5Padding、ISO10126Padding JDK(256位密鑰須要得到無政策限制權限文件)
同上 同上 同上 PKCS7Padding、ZeroBytePadding BC

Java代碼實現:

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實現:
  public static void jdkAES() {
    try {
      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
      keyGenerator.init(128);
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] keyBytes = secretKey.getEncoded();

      // KEY轉換
      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實現:
  public static void bcAES() {
    try {
      Security.addProvider(new BouncyCastleProvider());

      // 生成KEY
      KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BC");
      keyGenerator.getProvider();
      keyGenerator.init(128);
      // 產生密鑰
      SecretKey secretKey = keyGenerator.generateKey();
      // 獲取密鑰
      byte[] keyBytes = secretKey.getEncoded();

      // KEY轉換
      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,基於口令加密)是一種基於口令的加密算法,其特色是使用口令代替了密鑰,而口令由用戶本身掌管,採用隨機數雜湊多重加密等方法保證數據的安全性。

PBE算法在加密過程當中並非直接使用口令來加密,而是加密的密鑰由口令生成,這個功能由PBE算法中的KDF函數完成。KDF函數的實現過程爲:將用戶輸入的口令首先經過「鹽」(salt)的擾亂產生準密鑰,再將準密鑰通過散列函數屢次迭代後生成最終加密密鑰,密鑰生成後,PBE算法再選用對稱加密算法對數據進行加密,能夠選擇DES、3DES、RC5等對稱加密算法。

具體實現以下:

算法 密鑰長度 默認 工做模式 填充方式 實現
PBEWithMD5AndDES 64 64 CBC(下同) PKCS5Padding、PKCS7Padding、ISO10126Padding、ZeroBytePadding、(下同) BC(下同)
PBEWithMD5AndRC2 112 128      
PBEWithSHA1AndDES 64 64      
PBEWithSHA1AndRC2 128 128      
PBEWithSHAAndIDEA-CBC 128 128      
PBEWithSHAAnd2-KeyTripleDES-CBC 128 128      
PBEWithSHAAnd3-KeyTripleDES-CBC 192 192      
PBEWithSHAAnd128BitRC2-CBC 128 128      
PBEWithSHAAnd40BitRC2-CBC 40 40      
PBEWithSHAAnd128BitRC4 128 128      
PBEWithSHAAnd40BitRC4 40 40      
PBEWithSHAAndTwofish-CBC 256 256      

Java代碼實現:

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實現:
  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();
    }
  }
}

應用舉例:

版權聲明

【本文版權歸微信公衆號"代碼藝術"(ID:onblog)全部,如果轉載請務必保留本段原創聲明,違者必究。如果文章有不足之處,歡迎關注微信公衆號私信與我進行交流!】

相關文章
相關標籤/搜索