欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JAVA加密算法- 非對稱加密算法(DH,RSA)的詳細介紹

 更新時間:2016年11月01日 09:28:33   作者:我有切糕  
這篇文章主要介紹了JAVA加密算法- 非對稱加密算法(DH,RSA),詳細介紹了DH,RSA的用法和示例,需要的朋友可以了解一下。

非對稱密碼概念

1、與對稱加密算法的主要差別在于,加密和解密的密鑰不相同,一個公開(公鑰),一個保密(私鑰)。主要解決了對稱加密算法密鑰分配管理的問題,提高了算法安全性。

2、非對稱加密算法的加密、解密的效率比較低。在算法設計上,非對稱加密算法對待加密的數(shù)據(jù)長度有著苛刻的要求。例如RSA算法要求待加密的數(shù)據(jù)不得大于53個字節(jié)。

3、非對稱加密算法主要用于 交換對稱加密算法的密鑰,而非數(shù)據(jù)交換

4、java6提供實現(xiàn)了DH和RSA兩種算法。Bouncy Castle提供了E1Gamal算法支持。除了上述三種算法還有一個ECC算法,目前沒有相關的開源組件提供支持

需要兩個密鑰進行加密或解密,分為公鑰和私鑰

特點:安全性高,速度慢

用途

【密鑰交換(DH)】

雙方在沒有確定共同密鑰的情況下,生成密鑰,不提供加密工作,加解密還需要其他對稱加密算法實現(xiàn)

DH算法示例

import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

//1 生成源密鑰
//2 把源公鑰交給目標,目標通過源公鑰,生成目標公鑰和私鑰
//3 把目標公鑰交給源
//4 雙方使用對方的公鑰和和自己的私鑰,生成本地密鑰
//5 如果雙方生成本地密鑰相同則完成密鑰交換
public class DHUtil {

  public static final String PUBLIC_KEY = "DH_Public_Key";
  public static final String PRIVATE_KEY = "DH_Private_key";

  /**
   * 生成源密鑰對
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initSourceKey() throws Exception{
    //創(chuàng)建KeyPairGenerator的實例,選用DH算法
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");

    //初始化密鑰長度,默認1024,可選范圍512-65536 & 64的倍數(shù)
    keyPairGenerator.initialize(1024);

    //生成密鑰對
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    //將密鑰對放入Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   * 通過源公鑰 生成 目標密鑰對
   * @param sourcePublicKey
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initTargetKey(byte[] sourcePublicKey) throws Exception {

    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    //通過源公鑰,生成keySpec,使用KeyFactory生成源PublicKey相關信息
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(sourcePublicKey);
    DHPublicKey sourcePublic = (DHPublicKey) keyFactory.generatePublic(keySpec);

    DHParameterSpec dhPublicKeyParams = sourcePublic.getParams();

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
    keyPairGenerator.initialize(dhPublicKeyParams);

    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic();
    DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate();

    //將密鑰對放入Map
    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, dhPublicKey);
    keyMap.put(PRIVATE_KEY, dhPrivateKey);
    return keyMap;
  }

  /**
   * 使用一方的公鑰和另一方的私鑰,生成本地密鑰
   * @return
   */
  public static byte[] generateLocalSecretKey(byte[] aPublicKey, byte[] bPrivateKey) throws Exception{
    KeyFactory keyFactory = KeyFactory.getInstance("DH");

    //通過A公鑰,生成keySpec,使用KeyFactory生成A PublicKey相關信息
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(aPublicKey);
    PublicKey publicKey = keyFactory.generatePublic(keySpec);

    //通過B私鑰,生成B PrivateKey相關信息
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bPrivateKey);
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

    //通過KeyAgreement對A的PublicKey和B的PrivateKey進行加密
    KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
    keyAgreement.init(privateKey);
    keyAgreement.doPhase(publicKey,true);


    return keyAgreement.generateSecret("AES").getEncoded();//算法使用對稱加密算法(DES,DESede,AES)
    //return keyAgreement.generateSecret();        // 也可以不選擇算法,使用默認方法計算
  }

  //獲取公鑰字節(jié)數(shù)組
  public static byte[] getPublicKey(Map<String,Object> map){
    return ((DHPublicKey) map.get(PUBLIC_KEY)).getEncoded();
  }

  //獲取私鑰字節(jié)數(shù)組
  public static byte[] getPrivateKey(Map<String,Object> map){
    return ((DHPrivateKey) map.get(PRIVATE_KEY)).getEncoded();
  }

  public static void main(String[] args) throws Exception {

    byte[] source_public_key;
    byte[] source_private_key;
    byte[] source_local_key;

    byte[] target_public_key;
    byte[] target_private_key;
    byte[] target_local_key;

    Map<String, Object> sourceKey = initSourceKey();
    source_public_key = getPublicKey(sourceKey);
    source_private_key = getPrivateKey(sourceKey);

    System.out.println("源公鑰:"+BytesToHex.fromBytesToHex(source_public_key));
    System.out.println("源私鑰:"+BytesToHex.fromBytesToHex(source_private_key));

    Map<String, Object> targetKey = initTargetKey(getPublicKey(sourceKey));
    target_public_key = getPublicKey(targetKey);
    target_private_key = getPrivateKey(targetKey);

    System.out.println("目標公鑰:"+BytesToHex.fromBytesToHex(target_public_key));
    System.out.println("目標私鑰:"+BytesToHex.fromBytesToHex(target_private_key));

    source_local_key = generateLocalSecretKey(target_public_key, source_private_key);
    target_local_key = generateLocalSecretKey(source_public_key, target_private_key);

    System.out.println("源本地密鑰:"+BytesToHex.fromBytesToHex(source_local_key));
    System.out.println("目標本地密鑰:"+BytesToHex.fromBytesToHex(target_local_key));
  }
}

【加密/解密(RSA)】【數(shù)字簽名(RSA)】

RSA算法晚于DH算法,這五個字母全都是人名首字母.DH算法是第一個非對稱密碼體系.

RSA算法運算速度慢,不適宜加密大量數(shù)據(jù).一種解決方案是,將RSA跟對稱加密方式混合使用,將數(shù)據(jù)使用對稱加密方式加密,對稱加密的密鑰使用RSA算法加密,因為密鑰很短,所以時間費不了太多.實際上,對稱加密方式唯一的弊端就是密鑰不好傳遞,對稱加密方式也很難破解.

RSA的適用情景一:

(1)服務器生成一個公鑰和一個私鑰,把公鑰公開了.

(2)客戶端使用公鑰把數(shù)據(jù)進行加密,上交服務器.別人是沒法理解加密后的數(shù)據(jù)的.

(3)服務器使用私鑰將數(shù)據(jù)解密,查看用戶提交的數(shù)據(jù).

這種情景下,公鑰像是一個信箱,每個人都可以往這個信箱里面放信,但是這個信箱里面的信只有掌握信箱鑰匙的人才能開箱查看.

RSA適用情景二:

(1)皇上生成一個公鑰和一個密鑰,把公鑰公開了.

(2)皇上發(fā)布了一封詔書,昭告天下.詔書右下角有兩串數(shù)字,第一串數(shù)字是一個隨機串,第二串數(shù)字是用私鑰加密第一串數(shù)字所得的結果.

(3)有人不相信這詔書是皇上寫的,就把第二串數(shù)字使用公鑰解密,解密之后發(fā)現(xiàn)跟第一串數(shù)字一樣,說明確實是皇上寫的,因為一般人沒有密鑰,也就沒法加密那些能夠用公鑰解密的數(shù)據(jù).

這種情境下,公鑰用于解密,私鑰用于加密,這可以用于發(fā)布公告時,證明這個公告確實是某個人發(fā)的.相當于簽名.

實際上,簽名沒有必要特別長,一般情況下,簽名是定長的,要想定長,可以使用MessageDigest算法,如MD5和SHA系列.所以就有了多種簽名算法,如MD5withRSA等.

RSA 加密/解密 示例

import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA加密工具
 */
public class RSAUtil {

  public static final String PUBLIC_KEY = "RSA_Public_Key";
  public static final String PRIVATE_KEY = "RSA_Private_Key";

  /**
   * 初始化密鑰
   * @return
   * @throws Exception
   */
  public static Map<String,Object> initKey() throws Exception{
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(1024);//512-65536 & 64的倍數(shù)
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

    Map<String,Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
  }

  public static RSAPublicKey getPublicKey(Map<String,Object> keyMap) {
    return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
  }

  public static RSAPrivateKey getPrivateKey(Map<String,Object> keyMap){
    return (RSAPrivateKey) keyMap.get(PRIVATE_KEY);
  }

  /**
   * 使用公鑰對數(shù)據(jù)進行加密
   * @param data
   * @param publicKey
   * @return
   * @throws Exception
   */
  public static byte[] encrypt(byte[] data, RSAPublicKey publicKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE,publicKey);
    return cipher.doFinal(data);
  }

  /**
   * 使用私鑰解密
   * @param data
   * @param privateKey
   * @return
   * @throws Exception
   */
  public static byte[] decrypt(byte[] data, RSAPrivateKey privateKey) throws Exception{
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE,privateKey);
    return cipher.doFinal(data);
  }

  public static void main(String[] args) throws Exception {
    String data = "周杰倫-東風破";
    Map<String, Object> keyMap = initKey();

    byte[] miwen = encrypt(data.getBytes(),getPublicKey(keyMap));
    System.out.println("加密后的內(nèi)容:"+BytesToHex.fromBytesToHex(miwen));

    byte[] plain = decrypt(miwen, getPrivateKey(keyMap));
    System.out.println("解密后的內(nèi)容:"+new String(plain));

  }
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論