1. 程式人生 > >加解密方法簡介

加解密方法簡介

一、對稱加密

採用單鑰密碼的加密方法,同一個金鑰可以同時用來加密和解密,這種加密方法稱為對稱加密,也稱為單金鑰加密。常用的對稱加密演算法:

  •  DES(Data Encryption Standard):資料加密標準,速度較快,適用於加密大量資料的場合;
  •  3DES(Triple DES):是基於DES,對一塊資料用三個不同的金鑰進行三次加密,強度更高;
  •  AES(Advanced Encryption Standard):高階加密標準,是下一代的加密演算法標準,速度快,安全級別高,支援128、192、256、512位金鑰的加密;
  • Blowfish

演算法特徵:

  1.  加密方和解密方使用同一個金鑰;
  2.  加密解密的速度比較快,適合資料比較長時的使用;
  3.  金鑰傳輸的過程不安全,且容易被破解,金鑰管理也比較麻煩;

二、雜湊演算法

將任意長度的資訊轉換為較短的固定長度的值,通常其長度要比資訊小得多,且演算法不可逆。常見的雜湊演算法有:

  1.  MD5(Message Digest Algorithm 5):是RSA資料安全公司開發的一種單向雜湊演算法,非可逆,相同的明文產生相同的密文;
  2.  SHA(Secure Hash Algorithm):可以對任意長度的資料運算生成一個160位的數值。其變種有SHA192,SHA256,SHA384等;
  3.  CRC-32:主要用於提供校驗功能;

演算法特徵:

    ① 輸入一樣,輸出必然相同;
    ② 雪崩效應,輸入的微小改變,將會引起結果的巨大變化;
    ③ 定長輸出,無論原始資料多大,結果大小都是相同的;
    ④ 不可逆,無法根據特徵碼還原原來的資料;

三、非對稱加密

非對稱金鑰加密也稱為公鑰加密,由一對公鑰和私鑰組成。公鑰是從私鑰提取出來的。可以用公鑰加密,再用私鑰解密,這種情形一般用於公鑰加密;也可以用私鑰加密,用公鑰解密,常用於數字簽名,因此非對稱加密的主要功能就是加密和數字簽名。

特徵:

    祕鑰對,公鑰(public key)和私鑰(secret key)
    主要功能:加密和簽名

  •  傳送方用對方的公鑰加密,可以保證資料的機密性(公鑰加密);
  •  傳送方用自己的私鑰加密,可以實現身份驗證(數字簽名);

常用的非對稱加密演算法:

  •  RSA
  • ELGamal

公鑰加密和數字簽名的簡單圖解

1.

鮑勃有兩把鑰匙,一把是公鑰,另一把是私鑰。

2.

鮑勃把公鑰送給他的朋友們----帕蒂、道格、蘇珊----每人一把。

3.

蘇珊要給鮑勃寫一封保密的信。她寫完後用鮑勃的公鑰加密,就可以達到保密的效果。

4.

鮑勃收信後,用私鑰解密,就看到了信件內容。這裡要強調的是,只要鮑勃的私鑰不洩露,這封信就是安全的,即使落在別人手裡,也無法解密。

5.

鮑勃給蘇珊回信,決定採用"數字簽名"。他寫完後先用Hash函式,生成信件的摘要(digest)。

6.

然後,鮑勃使用私鑰,對這個摘要加密,生成"數字簽名"(signature)。

7.

鮑勃將這個簽名,附在信件下面,一起發給蘇珊。

8.

蘇珊收信後,取下數字簽名,用鮑勃的公鑰解密,得到信件的摘要。由此證明,這封信確實是鮑勃發出的。

9.

蘇珊再對信件本身使用Hash函式,將得到的結果,與上一步得到的摘要進行對比。如果兩者一致,就證明這封信未被修改過。

10.

複雜的情況出現了。道格想欺騙蘇珊,他偷偷使用了蘇珊的電腦,用自己的公鑰換走了鮑勃的公鑰。此時,蘇珊實際擁有的是道格的公鑰,但是還以為這是鮑勃的公鑰。因此,道格就可以冒充鮑勃,用自己的私鑰做成"數字簽名",寫信給蘇珊,讓蘇珊用假的鮑勃公鑰進行解密。

11.

後來,蘇珊感覺不對勁,發現自己無法確定公鑰是否真的屬於鮑勃。她想到了一個辦法,要求鮑勃去找"證書中心"(certificate authority,簡稱CA),為公鑰做認證。證書中心用自己的私鑰,對鮑勃的公鑰和一些相關資訊一起加密,生成"數字證書"(Digital Certificate)。

12.

鮑勃拿到數字證書以後,就可以放心了。以後再給蘇珊寫信,只要在簽名的同時,再附上數字證書就行了。

13.

蘇珊收信後,用CA的公鑰解開數字證書,就可以拿到鮑勃真實的公鑰了,然後就能證明"數字簽名"是否真的是鮑勃籤的。

14.

下面,我們看一個應用"數字證書"的例項:https協議。這個協議主要用於網頁加密。

15.

首先,客戶端向伺服器發出加密請求。

16.

伺服器用自己的私鑰加密網頁以後,連同本身的數字證書,一起傳送給客戶端。

17.

客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發機構"列表。客戶端會根據這張列表,檢視解開數字證書的公鑰是否在列表之內。

18.

如果數字證書記載的網址,與你正在瀏覽的網址不一致,就說明這張證書可能被冒用,瀏覽器會發出警告。

19.

如果這張數字證書不是由受信任的機構頒發的,瀏覽器會發出另一種警告。

20.

如果數字證書是可靠的,客戶端就可以使用證書中的伺服器公鑰,對資訊進行加密,然後與伺服器交換加密資訊。

再詳細的Https協議的原理,將在後續的部落格中進行介紹。

加解密演算法實現

AESUtil

package com.yj.encrypt.util;

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;

public class AESUtil {

	/**
	 * 加密
	 * 
	 * @param content
	 *            需要加密的內容
	 * @param password
	 *            加密密碼
	 * @return
	 */
	public static String encrypt(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 建立密碼器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			String encryptResultStr = parseByte2HexStr(result);
			return encryptResultStr; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param content
	 *            待解密內容
	 * @param password
	 *            解密金鑰
	 * @return
	 */
	public static String decrypt(String content, String password) {
		try {
			byte[] decryptFrom = parseHexStr2Byte(content);
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 建立密碼器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(decryptFrom);
			return new String(result); // 加密
		} 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;
	}

	/**
	 * 將二進位制轉換成16進位制
	 * 
	 * @param buf
	 * @return
	 */
	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();
	}

	/**
	 * 將16進位制轉換為二進位制
	 * 
	 * @param hexStr
	 * @return
	 */
	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 high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}
}

DESUtil

package com.yj.encrypt.util;

import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class DESUtil {

	/**
	 * 加密
	 * 
	 * @param content
	 *            需要加密的內容
	 * @param secretKey
	 *            加密密碼
	 * @return
	 */
	public static String encrypt(String content, String secretKey) {
		try {
			byte[] encryptionBytes = content.getBytes("UTF-8");
			SecureRandom random = new SecureRandom();
			DESKeySpec desKey = new DESKeySpec(buildDesKey(secretKey));
			// 建立一個金鑰工廠,然後用它把DESKeySpec轉換成
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher物件實際完成加密操作
			Cipher cipher = Cipher.getInstance("DES");
			// 用金鑰初始化Cipher物件
			cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
			// 執行加密操作
			byte[] encryptionBase64Bytes = Base64.getEncoder().encode(cipher.doFinal(encryptionBytes));
			// 轉換為字串返回
			return new String(encryptionBase64Bytes);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param content
	 *            需要解密的內容
	 * @param secretKey
	 *            解密密碼
	 * @return
	 */
	public static String decrypt(String content, String secretKey) {
		try {
			byte[] decryptionbytes = Base64.getDecoder().decode(content);
			// DES演算法要求有一個可信任的隨機數源
			SecureRandom random = new SecureRandom();
			// 建立一個DESKeySpec物件
			DESKeySpec desKey = new DESKeySpec(buildDesKey(secretKey));
			// 建立一個金鑰工廠
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			// 將DESKeySpec物件轉換成SecretKey物件
			SecretKey securekey = keyFactory.generateSecret(desKey);
			// Cipher物件實際完成解密操作
			Cipher cipher = Cipher.getInstance("DES");
			// 用金鑰初始化Cipher物件
			cipher.init(Cipher.DECRYPT_MODE, securekey, random);
			// 開始解密操作
			return new String(cipher.doFinal(decryptionbytes), "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 根據字串生成金鑰位元組陣列
	 * 
	 * @param keyStr 金鑰字串
	 * 
	 * @return
	 * 
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] buildDesKey(String keyStr) throws UnsupportedEncodingException {
		byte[] key = new byte[24]; // 宣告一個24位的位元組陣列,預設裡面都是0
		byte[] temp = keyStr.getBytes("UTF-8"); // 將字串轉成位元組陣列

		/*
		 * 執行陣列拷貝 System.arraycopy(源陣列,從源陣列哪裡開始拷貝,目標陣列,拷貝多少位)
		 */
		if (key.length > temp.length) {
			// 如果temp不夠24位,則拷貝temp陣列整個長度的內容到key陣列中
			System.arraycopy(temp, 0, key, 0, temp.length);
		} else {
			// 如果temp大於24位,則拷貝temp陣列24個長度的內容到key陣列中
			System.arraycopy(temp, 0, key, 0, key.length);
		}
		return key;
	}
}

DES3Util(3DES加解密工具類)

package com.yj.encrypt.util;

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class DES3Util {

	// 定義加密演算法,有DES、DESede(即3DES)、Blowfish
	private static final String Algorithm = "DESede";

	/**
	 * 加密
	 * 
	 * @param content
	 *            需要加密的內容
	 * @param secretKey
	 *            加密密碼
	 * @return
	 */
	public static String encrypt(String content, String secretKey) {
		try {
			byte[] encryptionBytes = content.getBytes("UTF-8");
			SecretKey deskey = new SecretKeySpec(build3DesKey(secretKey), Algorithm); // 生成金鑰
			Cipher c1 = Cipher.getInstance(Algorithm); // 例項化負責加密/解密的Cipher工具類
			c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化為加密模式
			return new String(Base64.getEncoder().encode(c1.doFinal(encryptionBytes)));
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param content
	 *            需要解密的內容
	 * @param secretKey
	 *            解密密碼
	 * @return
	 */
	public static String decrypt(String content, String secretKey) {
		try {
			byte[] decryptionbytes = Base64.getDecoder().decode(content);
			SecretKey deskey = new SecretKeySpec(build3DesKey(secretKey), Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化為解密模式
			return new String(c1.doFinal(decryptionbytes));
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/*
	 * 根據字串生成金鑰位元組陣列
	 * 
	 * @param keyStr 金鑰字串
	 * 
	 * @return
	 * 
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
		byte[] key = new byte[24]; // 宣告一個24位的位元組陣列,預設裡面都是0
		byte[] temp = keyStr.getBytes("UTF-8"); // 將字串轉成位元組陣列

		/*
		 * 執行陣列拷貝 System.arraycopy(源陣列,從源陣列哪裡開始拷貝,目標陣列,拷貝多少位)
		 */
		if (key.length > temp.length) {
			// 如果temp不夠24位,則拷貝temp陣列整個長度的內容到key陣列中
			System.arraycopy(temp, 0, key, 0, temp.length);
		} else {
			// 如果temp大於24位,則拷貝temp陣列24個長度的內容到key陣列中
			System.arraycopy(temp, 0, key, 0, key.length);
		}
		return key;
	}
}

對稱加密Test檔案

package com.yj.encrypt;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yj.encrypt.util.AESUtil;
import com.yj.encrypt.util.DES3Util;
import com.yj.encrypt.util.DESUtil;

//對稱加密
public class SymmetricEncrypt {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	public static String content = "我的加密內容";

	public static String secretKey = "mykey";

	@Test
	public void DES() throws Exception {
		String result = DESUtil.encrypt(content, secretKey);
		log.info("DES加密結果:" + result);
		result = DESUtil.decrypt(result, secretKey);
		log.info("DES解密結果:" + result);
	}

	@Test
	public void DES3() throws Exception {
		String result = DES3Util.encrypt(content, secretKey);
		log.info("3DES加密結果:" + result);
		result = DES3Util.decrypt(result, secretKey);
		log.info("3DES解密結果:" + result);
	}

	@Test
	public void AES() throws Exception {  
	    String result = AESUtil.encrypt(content, secretKey);
	    log.info("AES加密後:" + result);  
	    result = AESUtil.decrypt(result,secretKey);  
	    log.info("AES解密後:" + result);  
	}

	
	// base不屬於對稱加密,暫時將它放在這裡
	// jdk實現,sun.misc包是Sun公司提供給內部使用的專用API,在java API文件中我們看不到任何有關BASE64影子,不建議使用
	// 此處我們採用apache實現
	@Test
	public void BASE64() throws Exception {
		String sourceStr = "123456";
		org.apache.tomcat.util.codec.binary.Base64 base = new org.apache.tomcat.util.codec.binary.Base64();
		String result = base.encodeAsString(sourceStr.getBytes("UTF-8"));
		log.info("BASE64加密結果:" + result);
		byte[] decodeByte = base.decode(result);
		result = new String(decodeByte);
		log.info("BASE64解密結果:" + result);
	}
}

非對稱加密Test檔案

package com.yj.encrypt;

import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//非對稱加密
public class AsymmetricEncrypt {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	public static String content = "我的加密內容";

	RSAPublicKey rsaPublicKey;

	RSAPrivateKey rsaPrivateKey;

	PublicKey elGamalPublicKey;

	PrivateKey elGamalPrivateKey;

	@Before
	public void init() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(512);// 金鑰長度為64的整數倍,最大是65536
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
		rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
		log.info("RSA公鑰:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
		log.info("RSA私鑰:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

		log.info("==RSA結束==ELGamal開始==");
		//JAVA7不支援,pom檔案需引入BouncyCastle
		Security.addProvider(new BouncyCastleProvider());
		AlgorithmParameterGenerator apg = AlgorithmParameterGenerator.getInstance("ElGamal");
		apg.init(256);
		AlgorithmParameters params = apg.generateParameters();
		DHParameterSpec dhParams = params.getParameterSpec(DHParameterSpec.class);

		KeyPairGenerator keyPairGene = KeyPairGenerator.getInstance("ElGamal");
		keyPairGene.initialize(dhParams, new SecureRandom());

		KeyPair ELGamalKeyPair = keyPairGene.generateKeyPair();
		elGamalPublicKey = ELGamalKeyPair.getPublic();
		elGamalPrivateKey = ELGamalKeyPair.getPrivate();
		log.info("ELGamal公鑰:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
		log.info("ELGamal私鑰:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));
	}

	@Test
	public void RSA1() throws Exception {
		log.info("私鑰加密,公鑰解密");

		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		byte[] result = cipher.doFinal(content.getBytes());
		log.info("RSA私鑰加密:" + Base64.encodeBase64String(result));

		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
		keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		result = cipher.doFinal(result);
		log.info("RSA公鑰解密:" + new String(result));
	}

	@Test
	public void RSA2() throws Exception {
		log.info("公鑰加密,私鑰解密");

		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] result = cipher.doFinal(content.getBytes());
		log.info("RSA公鑰加密:" + Base64.encodeBase64String(result));

		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
		keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		result = cipher.doFinal(result);
		log.info("RSA私鑰解密:" + new String(result));
	}

	/*
	 * 只有公鑰加密,私鑰解密
	 * */
	@Test
	public void Elgamal() throws Exception {
		log.info("公鑰加密,私鑰解密");

		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("ELGamal");
		PublicKey elGamalPublicKey = (PublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
		Cipher cipher = Cipher.getInstance("ELGamal", "BC");
		cipher.init(Cipher.ENCRYPT_MODE, elGamalPublicKey);
		byte[] result = cipher.doFinal(content.getBytes());
		log.info("ELGamal公鑰加密:" + Base64.encodeBase64String(result));

		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
		keyFactory = KeyFactory.getInstance("ELGamal");
		PrivateKey elGamalPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		cipher.init(Cipher.DECRYPT_MODE, elGamalPrivateKey);
		result = cipher.doFinal(result);
		log.info("ELGamal私鑰解密:" + new String(result));
	}
}

Hash加密Test檔案

package com.yj.encrypt;

import java.security.MessageDigest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//HASH加密
public class HashEncrypt {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	public static String content = "123456";

	@Test
	public void MD5() throws Exception {
		String sourceStr = "123456";
		String result;
		// 定義一個16進位制char陣列,取每一個byte前後四位對應char的十六進位制數值
		char HEX[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		byte[] sourceByte = sourceStr.getBytes("UTF-8");
		// 獲得MD5摘要演算法的 MessageDigest 物件
		MessageDigest messageDigest = MessageDigest.getInstance("MD5");
		// 使用指定的位元組更新摘要
		messageDigest.update(sourceByte);
		// 獲得密文
		byte[] md = messageDigest.digest();
		// 把密文轉換成十六進位制的字串形式
		int j = md.length;
		char buf[] = new char[j * 2];
		int k = 0;
		for (int i = 0; i < j; i++) {
			byte byte0 = md[i];
			buf[k++] = HEX[byte0 >>> 4 & 0xf];
			buf[k++] = HEX[byte0 & 0xf];
		}
		result = new String(buf);
		log.info("MD5加密結果:" + result);
	}

	@Test
	public void SHA() throws Exception {
		String sourceStr = "123456";
		String result;
		char HEX[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
		messageDigest.update(sourceStr.getBytes("UTF-8"));
		byte[] md = messageDigest.digest();
		int j = md.length;
		char buf[] = new char[j * 2];
		int k = 0;
		for (int i = 0; i < j; i++) {
			byte byte0 = md[i];
			buf[k++] = HEX[byte0 >>> 4 & 0xf];
			buf[k++] = HEX[byte0 & 0xf];
		}
		result = new String(buf);
		log.info("SHA加密結果:" + result);
	}
}

pom檔案

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.yj</groupId>
	<artifactId>Encrypt</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>Encrypt</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.17.RELEASE</version>
		<relativePath />
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-jdk15on</artifactId>
			<version>1.60</version>
		</dependency>
	</dependencies>
</project>