代碼參考URL:http://www.imooc.com/learn/288
1.非對稱加密算法--DH
流程說明參考的文章:http://blog.csdn.net/sunny_sailor/article/details/7445649
DH的流程:
1.甲方建構密鑰對兒,将公鑰公布給乙方,将私鑰保留;雙方約定資料加密算法;乙方通過甲方公鑰建構密鑰對兒,将公鑰公布給甲方,将私鑰保留。
2.甲方使用私鑰、乙方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰加密資料,發送給乙方加密後的資料;乙方使用私鑰、甲方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰對資料解密。
3.乙方使用私鑰、甲方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰加密資料,發送給甲方加密後的資料;甲方使用私鑰、乙方公鑰、約定資料加密算法建構本地密鑰,然後通過本地密鑰對資料解密。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISO0ETNwETM1ETOwIDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
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運用的流程如下:
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