一.ElGamal:ElGamal算法,是一种较为常见的加密算法,它是基于1985年提出的公钥密码体制和椭圆曲线加密体系。既能用于数据加密也能用于数字签名,其安全性依赖于计算有限域上离散对数这一难题。在加密过程中,生成的密文长度是明文的两倍,且每次加密后都会在密文中生成一个随机数K,在密码中主要应用离散对数问题的几个性质:求解离散对数(可能)是困难的,而其逆运算指数运算可以应用平方-乘的方法有效地计算。
二.注意!!!
加密时抛出java.security.InvalidKeyException: Illegal key size or default parameters
原因: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:
JCE8: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
JCE7: http://www.oracle.com/technetwork/java/embedded/embedded-se/downloads/jce-7-download-432124.html
JCE6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
三.具体的实现(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;
}
}