非對稱加密演算法(3):ElGamal
阿新 • • 發佈:2019-01-25
一.ElGamal:ElGamal演算法,是一種較為常見的加密演算法,它是基於1985年提出的公鑰密碼體制和橢圓曲線加密體系。既能用於資料加密也能用於數字簽名,其安全性依賴於計算有限域上離散對數這一難題。在加密過程中,生成的密文長度是明文的兩倍,且每次加密後都會在密文中生成一個隨機數K,在密碼中主要應用離散對數問題的幾個性質:求解離散對數(可能)是困難的,而其逆運算指數運算可以應用平方-乘的方法有效地計算。
二.注意!!!
原因:Illegal key size or default parameters是指金鑰長度是受限制的,java執行時環境讀到的是受限的policy檔案。檔案位於${java_home}/jre/lib/security, 這種限制是因為美國對軟體出口的控制。
解決方案:替換 ${java_home}/jre/lib/security 的 local_policy.jar 和 US_export_policy.jar ,不同的jdk版本的替換檔案不一致,具體參看下面的lian:
三.具體的實現(java):
import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.DHParameterSpec; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class ElGamal { public static void main(String[] args) throws Exception { String src = "歐陽草帽"; KeyPair keyPair = getKeyPair(); //公鑰 PublicKey publicKey = getPublicKey(keyPair); //私鑰 PrivateKey privateKey = getPrivateKey(keyPair); byte[] publicKeyEnc = publicKey.getEncoded(); byte[] privateKeyEnc = privateKey.getEncoded(); System.out.println("祕鑰 :"+Base64.encodeBase64String(privateKeyEnc)); System.out.println("公鑰 :"+Base64.encodeBase64String(publicKeyEnc)); //加密資料 byte[] result = ensrypt(src, publicKeyEnc); System.out.println("加密的資料 :"+Base64.encodeBase64String(result)); result = decrypt(privateKeyEnc, result); System.out.println("解密資料:"+new String(result)); } /** * 解密資料 * @param privateKeyEnc :私鑰 * @param result : 解密資料 * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws IllegalBlockSizeException * @throws BadPaddingException */ public static byte[] decrypt(byte[] privateKeyEnc, byte[] result) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyFactory keyFactory = KeyFactory.getInstance("ElGamal"); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyEnc); PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, priKey); result = cipher.doFinal(result); return result; } /** * 加密資料 * @param src : 加密資料 * @param publicKeyEnc : 公鑰 * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws NoSuchPaddingException * @throws InvalidKeyException * @throws IllegalBlockSizeException * @throws BadPaddingException */ public static byte[] ensrypt(String src, byte[] publicKeyEnc) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyFactory keyFactory=KeyFactory.getInstance("ElGamal"); //初始化公鑰 //金鑰材料轉換 X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(publicKeyEnc); //產生公鑰 PublicKey pubKey=keyFactory.generatePublic(x509KeySpec); //資料加密 Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, pubKey); byte [] result = cipher.doFinal(src.getBytes()); return result; } /** * 獲取私鑰 * @param keyPair * @return */ public static PrivateKey getPrivateKey(KeyPair keyPair) { PrivateKey privateKey= keyPair.getPrivate(); return privateKey; } /** * 獲取公鑰 * @param keyPair * @return */ public static PublicKey getPublicKey(KeyPair keyPair) { PublicKey publicKey= keyPair.getPublic(); return publicKey; } private static KeyPair getKeyPair() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidAlgorithmParameterException { //加入對BouncyCastle支援 Security.addProvider(new BouncyCastleProvider()); AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance("ElGamal"); //初始化引數生成器 apg.init(256); //生成演算法引數 AlgorithmParameters params=apg.generateParameters(); //構建引數材料 DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class); //例項化金鑰生成器 KeyPairGenerator kpg=KeyPairGenerator.getInstance("ElGamal") ; //初始化金鑰對生成器 kpg.initialize(elParams,new SecureRandom()); KeyPair keyPair=kpg.generateKeyPair(); return keyPair; } }