JAVA加解密17-非對稱加密算法-ElGamal算法

一、概述
1.ElGamal算法和ECC算法基于離散對數(shù)問題
2.這個是一個單向的過程。雖然密鑰對構(gòu)造簡單,但是只是乙方向另外一方單向傳送數(shù)據(jù)進行加解密,不能反向操作
3.這里只有“公鑰加密、私鑰解密”這個過程
4.ElGamal不足之處就是 密文會成倍增長
5.ElGamal和RSA最大不同就是他們構(gòu)造密鑰對的方式不同。還有就是是否為雙向加解密

二、模型分析
以甲方向乙方發(fā)送數(shù)據(jù)為模型
1.甲方構(gòu)造密鑰對(公鑰+私鑰),公布公鑰給乙方
2.這里甲方?jīng)]法給乙方發(fā)送數(shù)據(jù)了,只有乙方能給甲方傳送數(shù)據(jù)
3.乙方用公鑰對數(shù)據(jù)進行加密,傳送給甲方,甲方用私鑰對數(shù)據(jù)進行解密

三、代碼實現(xiàn)

package com.ca.test;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.Key;
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 java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
 * 非對稱加密算法ElGamal算法組件
 * 非對稱算法一般是用來傳送對稱加密算法的密鑰來使用的。相對于RSA算法,這個算法只支持私鑰加密公鑰解密
 * @author kongqz
 * */
public class ElGamalCoder {
    //非對稱密鑰算法
    public static final String KEY_ALGORITHM="ElGamal";
    
    
    /**
     * 密鑰長度,DH算法的默認密鑰長度是1024
     * 密鑰長度必須是8的倍數(shù),在160到16384位之間
     * */
    private static final int KEY_SIZE=256;
    //公鑰
    private static final String PUBLIC_KEY="ElGamalPublicKey";
    
    //私鑰
    private static final String PRIVATE_KEY="ElGamalPrivateKey";
    
    /**
     * 初始化密鑰對
     * @return Map 甲方密鑰的Map
     * */
    public static Map<String,Object> initKey() throws Exception{
        //加入對BouncyCastle支持
        Security.addProvider(new BouncyCastleProvider());
        AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
        //初始化參數(shù)生成器
        apg.init(KEY_SIZE);
        //生成算法參數(shù)
        AlgorithmParameters params=apg.generateParameters();
        //構(gòu)建參數(shù)材料
        DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
        
        //實例化密鑰生成器
        KeyPairGenerator kpg=KeyPairGenerator.getInstance(KEY_ALGORITHM) ;
        
        //初始化密鑰對生成器
        kpg.initialize(elParams,new SecureRandom());
        
        KeyPair keyPair=kpg.generateKeyPair();
        //甲方公鑰
        PublicKey publicKey= keyPair.getPublic();
        //甲方私鑰
        PrivateKey privateKey= keyPair.getPrivate();
        //將密鑰存儲在map中
        Map<String,Object> keyMap=new HashMap<String,Object>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
        
    }
    
    
    /**
     * 公鑰加密
     * @param data待加密數(shù)據(jù)
     * @param key 密鑰
     * @return byte[] 加密數(shù)據(jù)
     * */
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
        
        //實例化密鑰工廠
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
        //初始化公鑰
        //密鑰材料轉(zhuǎn)換
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
        //產(chǎn)生公鑰
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
        
        //數(shù)據(jù)加密
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }
    /**
     * 私鑰解密
     * @param data 待解密數(shù)據(jù)
     * @param key 密鑰
     * @return byte[] 解密數(shù)據(jù)
     * */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
        //取得私鑰
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私鑰
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
        //數(shù)據(jù)解密
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }
    
    /**
     * 取得私鑰
     * @param keyMap 密鑰map
     * @return byte[] 私鑰
     * */
    public static byte[] getPrivateKey(Map<String,Object> keyMap){
        Key key=(Key)keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }
    /**
     * 取得公鑰
     * @param keyMap 密鑰map
     * @return byte[] 公鑰
     * */
    public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
        Key key=(Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }
    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        //初始化密鑰
        //生成密鑰對
        Map<String,Object> keyMap=ElGamalCoder.initKey();
        //公鑰
        byte[] publicKey=ElGamalCoder.getPublicKey(keyMap);
        
        //私鑰
        byte[] privateKey=ElGamalCoder.getPrivateKey(keyMap);
        System.out.println("公鑰:/n"+Base64.encodeBase64String(publicKey));
        System.out.println("私鑰:/n"+Base64.encodeBase64String(privateKey));
        
        System.out.println("================密鑰對構(gòu)造完畢,甲方將公鑰公布給乙方,開始進行加密數(shù)據(jù)的傳輸=============");
        String str="ElGamal密碼交換算法";
        System.out.println("/n===========甲方向乙方發(fā)送加密數(shù)據(jù)==============");
        System.out.println("原文:"+str);
        
        //乙方使用公鑰對數(shù)據(jù)進行加密
        byte[] code2=ElGamalCoder.encryptByPublicKey(str.getBytes(), publicKey);
        System.out.println("===========乙方使用公鑰對數(shù)據(jù)進行加密==============");
        System.out.println("加密后的數(shù)據(jù):"+Base64.encodeBase64String(code2));
        
        
        //甲方使用私鑰對數(shù)據(jù)進行解密
        byte[] decode2=ElGamalCoder.decryptByPrivateKey(code2, privateKey);
        
        System.out.println("甲方解密后的數(shù)據(jù):"+new String(decode2));
    }
}
控制臺輸出:
公鑰:
MHgwUAYGKw4HAgEBMEYCIQD0uq+9qH/RFRMgdsbGP9scyNhsDF51I40kDUGYfDs9LwIhAMxG0VQV
ZBaqTMZzLeFGYO2SBQX2UMAnuiBzLhKEcPh1AyQAAiEA2eL2mHUbsm/3p9wNRLSaikuOmkRoIbbp
Ltvj8Lok3OE=
私鑰:
MHkCAQAwUAYGKw4HAgEBMEYCIQD0uq+9qH/RFRMgdsbGP9scyNhsDF51I40kDUGYfDs9LwIhAMxG
0VQVZBaqTMZzLeFGYO2SBQX2UMAnuiBzLhKEcPh1BCICIHkLWWt3E212XnDAMZonNEE4tDbDtkVV
9GOHK/rBjAQi
================密鑰對構(gòu)造完畢,甲方將公鑰公布給乙方,開始進行加密數(shù)據(jù)的傳輸=============
===========甲方向乙方發(fā)送加密數(shù)據(jù)==============
原文:ElGamal密碼交換算法
===========乙方使用公鑰對數(shù)據(jù)進行加密==============
加密后的數(shù)據(jù):d9HzNTy1AnEk9c7f6cUs7B6QRbHnMSd3666pfqlffC+ziJj0jYCcmV4Jso8eU1gTs57z8pjJB23j
mCB1A8uFjw==
甲方解密后的數(shù)據(jù):ElGamal密碼交換算法

四、總結(jié)
1.這個是一個單向傳遞數(shù)據(jù)的過程,這個和RSA不同,RSA的公鑰私鑰都可以用來做加解密數(shù)據(jù)的
2.這里java6不支持ElGamal算法,BouncyCastle支持這個算法
3.這里的公鑰私鑰長度幾乎一致
4.這里只有“公鑰加密、私鑰解密”這一個原則

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容