天天看點

非對稱加密算法-DH,RSA,ElGamal

代碼參考URL:http://www.imooc.com/learn/288

1.非對稱加密算法--DH

流程說明參考的文章:http://blog.csdn.net/sunny_sailor/article/details/7445649

DH的流程:

1.甲方建構密鑰對兒,将公鑰公布給乙方,将私鑰保留;雙方約定資料加密算法;乙方通過甲方公鑰建構密鑰對兒,将公鑰公布給甲方,将私鑰保留。 

2.甲方使用私鑰、乙方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰加密資料,發送給乙方加密後的資料;乙方使用私鑰、甲方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰對資料解密。 

3.乙方使用私鑰、甲方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰加密資料,發送給甲方加密後的資料;甲方使用私鑰、乙方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰對資料解密。

非對稱加密算法-DH,RSA,ElGamal

1.使用jdk,bc來實作對應代碼:

package com.samlai.security.asyEncry;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;


public class DHStudy {
	/**
	 * 非對稱加密算法 -DH(密鑰交換)
	 *  對稱加密帶來的困擾
	 *  建構本地密鑰
	 *  對稱
	 */
	private static String STR = "one type of security:DH";
	
	public static void main(String[] args) {
		jdkDH();
		bcDH();
	}
	
	
	//jdk實作DH
	public static void jdkDH(){
		try {
			//初始化發送方密鑰
			KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH");
			senderKeyPairGenerator.initialize(512);
			KeyPair senderKeyPair=senderKeyPairGenerator.generateKeyPair();
			//發送方公鑰,發送給收方(網絡,檔案)
			byte[] senderPublicKeyEnc=senderKeyPair.getPublic().getEncoded();
			
			//初始化接收方密鑰
			KeyFactory receiverKeyFactory=KeyFactory.getInstance("DH");
			X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc);
			PublicKey receiverPublicKey=receiverKeyFactory.generatePublic(x509EncodedKeySpec);
			DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams();
			KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH");
			receiverKeyPairGenerator.initialize(dhParameterSpec);
			KeyPair receiverKeyPair=receiverKeyPairGenerator.generateKeyPair();
			PrivateKey reveiverPrivateKey=receiverKeyPair.getPrivate();
			byte[] receiverPublicKeyEnc=receiverKeyPair.getPublic().getEncoded();
			
			//密鑰建構
			KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH");
			receiverKeyAgreement.init(reveiverPrivateKey);
			receiverKeyAgreement.doPhase(receiverPublicKey, true);
			SecretKey receiverDesKey=receiverKeyAgreement.generateSecret("DES");
			
			KeyFactory senderKeyFactory=KeyFactory.getInstance("DH");
			x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc);
			PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec);
			KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH");
			senderKeyAgreement.init(senderKeyPair.getPrivate());
			senderKeyAgreement.doPhase(senderPublicKey, true);
			SecretKey senderDesKey=senderKeyAgreement.generateSecret("DES");
			if(Objects.equals(receiverDesKey, senderDesKey)){
				System.out.println("雙方密鑰相同");
			}
			
			//加密
			Cipher cipher=Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
			byte[] result=cipher.doFinal(STR.getBytes());
			System.out.println("jdk DH encode: "+Base64.encodeBase64String(result));
			
			
			//解密
			cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
			result=cipher.doFinal(result);
			System.out.println("jdk DH decode: "+new String(result));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	//bc實作DH算法
	public static void bcDH(){
		try {
			Security.addProvider(new BouncyCastleProvider());
			//初始化發送方密鑰
			KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH","BC");
			senderKeyPairGenerator.getProvider();
			senderKeyPairGenerator.initialize(512);
			KeyPair senderKeyPair=senderKeyPairGenerator.generateKeyPair();
			//發送方公鑰,發送給收方(網絡,檔案)
			byte[] senderPublicKeyEnc=senderKeyPair.getPublic().getEncoded();
			
			//初始化接收方密鑰
			KeyFactory receiverKeyFactory=KeyFactory.getInstance("DH");
			X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc);
			PublicKey receiverPublicKey=receiverKeyFactory.generatePublic(x509EncodedKeySpec);
			DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams();
			KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH","BC");
			receiverKeyPairGenerator.getProvider();
			receiverKeyPairGenerator.initialize(dhParameterSpec);
			KeyPair receiverKeyPair=receiverKeyPairGenerator.generateKeyPair();
			PrivateKey reveiverPrivateKey=receiverKeyPair.getPrivate();
			byte[] receiverPublicKeyEnc=receiverKeyPair.getPublic().getEncoded();
			
			//密鑰建構
			KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH");
			receiverKeyAgreement.init(reveiverPrivateKey);
			receiverKeyAgreement.doPhase(receiverPublicKey, true);
			SecretKey receiverDesKey=receiverKeyAgreement.generateSecret("DES");
			
			KeyFactory senderKeyFactory=KeyFactory.getInstance("DH");
			x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc);
			PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec);
			KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH");
			senderKeyAgreement.init(senderKeyPair.getPrivate());
			senderKeyAgreement.doPhase(senderPublicKey, true);
			SecretKey senderDesKey=senderKeyAgreement.generateSecret("DES");
			if(Objects.equals(receiverDesKey, senderDesKey)){
				System.out.println("雙方密鑰相同");
			}
			
			//加密
			Cipher cipher=Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
			byte[] result=cipher.doFinal(STR.getBytes());
			System.out.println("bc DH encode: "+Base64.encodeBase64String(result));
			
			
			//解密
			cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
			result=cipher.doFinal(result);
			System.out.println("bc DH decode: "+new String(result));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
           

運作的結果:

雙方密鑰相同
jdk DH encode: XbmK/tkwVlYao3lhJvLWqceJ8QiYkODa
jdk DH decode: one type of security:DH
雙方密鑰相同
bc DH encode: Ehu42tOe7AmwMLOAAf2S4/1pwnX+91Iy
bc DH decode: one type of security:DH
           

2.jdk實作RSA算法:

package com.samlai.security.asyEncry;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
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 org.apache.commons.codec.binary.Base64;

public class RSAStudy {
	/**
	 * 非對稱加密算法 --RSA
	 * 基于大數因子分解
	 * 	唯一廣泛接受并實作
	 * 	資料加密&數字簽名
	 * 	公鑰加密 私鑰解密
	 * 	私鑰加密 公鑰解密
	 */
	private static String STR = "one type of security:RSA";
	
	public static void main(String[] args) {
		jdkRSA();
	}
	
	//jdk實作RSA加密
	public static void jdkRSA(){
		try {
			//1.初始化密鑰
			KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
			keyPairGenerator.initialize(512);
			KeyPair keyPair=keyPairGenerator.generateKeyPair();
			RSAPublicKey rsaPublicKey=(RSAPublicKey)keyPair.getPublic();
			RSAPrivateKey rsaPrivate=(RSAPrivateKey)keyPair.getPrivate();
			//列印出來的公鑰是比私鑰短較多的,公鑰公開,較短較容易儲存
			System.out.println("public Key: "+Base64.encodeBase64String(rsaPublicKey.getEncoded()));
			System.out.println("private Key: "+Base64.encodeBase64String(rsaPrivate.getEncoded()));
			
			
			//2.私鑰加密,公鑰解密---加密
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivate.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(STR.getBytes());
			System.out.println("私鑰加密,公鑰解密---加密: "+Base64.encodeBase64String(result));
			
			//3.私鑰加密,公鑰解密---解密
			X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			keyFactory=KeyFactory.getInstance("RSA");
			PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
			cipher=Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, publicKey);
			result=cipher.doFinal(result);
			System.out.println("私鑰加密,公鑰解密---解密: "+new String(result));
			
			
			//4.公鑰加密,私鑰解密 --- 加密[與上面非常的相近的]
			x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded());
			keyFactory=KeyFactory.getInstance("RSA");
			publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			result=cipher.doFinal(result);
			System.out.println("公鑰加密,私鑰解密 --- 加密: "+Base64.encodeBase64String(result));
			
			//5.公鑰加密,私鑰解密 --- 解密
			pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivate.getEncoded());
			keyFactory=KeyFactory.getInstance("RSA");
			privateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			cipher=Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			result=cipher.doFinal(result);
			System.out.println("公鑰加密,私鑰解密 --- 解密: "+new String(result));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
           

運作的結果:

public Key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM0TUZSywLpr8e3UGhCM84/LQT+LS64OUXTFn9O5Kt/dOg+eiYdBKSON1cfVJWAsEAuIKYwFwl2z1PfxBkZ01r0CAwEAAQ==
private Key: MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAzRNRlLLAumvx7dQaEIzzj8tBP4tLrg5RdMWf07kq3906D56Jh0EpI43Vx9UlYCwQC4gpjAXCXbPU9/EGRnTWvQIDAQABAkBolsG0pLXGXec09EeWyUwuueq9Db27N3Izq9anlHhZUv/PLIg83/Ucxl5NTDFfxPiBHqtYWUsAprOvxUqORzABAiEA/DK5wwaH7kOf+EE0ytMzlb2rwYM7Semx6OhrM23eVUECIQDQKr0i1LpRU2caCS5F3wc+FkrZF1ajZBA6EsNDUQm2fQIgKyJd5T5Tt2u3i5VTezE+TGkhXDqexFiFBkniM+yhr0ECIQCxm4V77lx5ftt8z1B3tO6M/qAl0U/OYFWn9tI64S2UUQIhAOh4v+zANLyfdFKNeau/zIeRLGYXzDd8lUg2KQuHPzB4
私鑰加密,公鑰解密---加密: Oy+z3Ncym67f7tYYoulFDfjTn3tQK3YQ+Dx/UhBljsSC2WTf2ZnlT6+EK+rqSyqkOK93w00tNoeGrYdlWMAlSw==
私鑰加密,公鑰解密---解密: one type of security:RSA
公鑰加密,私鑰解密 --- 加密: uLndrx+xnmR6en3f4gfEnY9u9vrf4UnDIUcM5+zXc4ykSBk628x0vKT+UuRYBY30Pyh60aoBz0FLbuimGBKQNw==
公鑰加密,私鑰解密 --- 解密: one type of security:RSA
           

RSA運用的流程如下:

非對稱加密算法-DH,RSA,ElGamal

3.ElGamal算法實作

當密鑰大于128時,代碼會抛出java.security.InvalidKeyException: Illegal key size or default parametersIllegal key size or default parameters是指密鑰長度是受限制的,java運作時環境讀到的是受限的policy檔案。檔案位于${java_home}/jre/lib/security。這種限制是因為美國對軟體出口的控制。

條件:因為ElGamal加密的長度為8的倍數,160-16384位,由于from us是以對加密長度有進行限制的,(大于128位時)是以本身我們本地的jdk是對這些檔案是有限制,故需要下載下傳額外的jar檔案:US_export_policy.jar,local_policy.jar 替換的本地的java的jdk目錄下的jre的security下2jar包就可以正确執行ElGamal代碼了

參考url:http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters

package com.samlai.security.asyEncry;


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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


import javax.crypto.Cipher;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class ElGamalStudy {
	
	/**
	 * 沒有jdk實作,bc提供
	 * 公鑰加密算法
	 * 密鑰長度:8的倍數 160>
	 * 
	 */
	private static String STR = "one type of security:ElGamal";
	public static void main(String[] args) {
		bcElGamal();
	}
	//jdk實作RSA加密
	public static void bcElGamal(){
		try {
			Security.addProvider(new BouncyCastleProvider());
			//初始化密鑰
			AlgorithmParameterGenerator algorithmParameterGenerator=AlgorithmParameterGenerator.getInstance("ElGamal");
			algorithmParameterGenerator.init(256);
			AlgorithmParameters algorithmParameters=algorithmParameterGenerator.generateParameters();
			DHParameterSpec dhParameterSpec=(DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
			KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("ElGamal");
			keyPairGenerator.initialize(dhParameterSpec,new SecureRandom());
			KeyPair keyPair=keyPairGenerator.generateKeyPair();
			//建構對應的密鑰對
			PublicKey elGamalPublicKey=keyPair.getPublic();
			PrivateKey elGamalPrivateKey=keyPair.getPrivate();
			
			System.out.println("Public Key: "+Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
			System.out.println("Private Key: "+Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));;
			
			
			//步驟是:
			/**
			 * 1.在接收者上進行建構密鑰對就是公鑰跟私鑰
			 * 2.由接收者進行釋出公鑰,再由釋出者進行公鑰進行加密資料,再進行傳輸加密資料
			 * 3.接收者進行接收資料,由私鑰進行解密
			 */
			
			//公鑰加密,私鑰解密 ----- 加密
//			X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
//			KeyFactory keyFactory=KeyFactory.getInstance("ElGamal");
//			PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec);
			Cipher cipher=Cipher.getInstance("ElGamal");
			cipher.init(Cipher.ENCRYPT_MODE, elGamalPublicKey);
			byte[] result=cipher.doFinal(STR.getBytes());
			System.out.println("ElGamals算法,公鑰加密,私鑰解密-----加密: "+Base64.encodeBase64String(result));
			
//			PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
//			keyFactory=KeyFactory.getInstance("ElGamal");
//			PrivateKey privateKey=keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			cipher=Cipher.getInstance("ElGamal");
			cipher.init(Cipher.DECRYPT_MODE, elGamalPrivateKey);
			result=cipher.doFinal(result);
			System.out.println("ElGamals算法,公鑰加密,私鑰解密-----解密: "+new String(result));
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
           

運作結果:

Public Key: MHcwUAYGKw4HAgEBMEYCIQDLb7VPLae2lzgRPOjD8dXsxxsuDaZVEdXjknwg4b2g/wIhAIdAvANdNVDdJ7JZoPZBpzWzKe9PA94xpPe59+fARTE4AyMAAiAG6zKE1VmQofKM6+oIYAYE4+sze9UT5eYPOx4rdAlBbQ==
Private Key: MHkCAQAwUAYGKw4HAgEBMEYCIQDLb7VPLae2lzgRPOjD8dXsxxsuDaZVEdXjknwg4b2g/wIhAIdAvANdNVDdJ7JZoPZBpzWzKe9PA94xpPe59+fARTE4BCICIAUlzfqi879n8oJfQcIDUniu4yaJ1JRA5G0RIj58XuCE
ElGamals算法,公鑰加密,私鑰解密-----加密: ToLmNsaIM422cRKXOoJbyPy2ta2lzhVR1bmlEGv/+VuAkKeVpqj5XKjE1wMWVQCHP5t6UTBPIcPAdNQbydhxXQ==
ElGamals算法,公鑰加密,私鑰解密-----解密: one type of security:ElGamal
           
非對稱加密算法-DH,RSA,ElGamal