1、什么是ElGamal
ElGamal算法,是一种较为常见的加密算法,它是基于1985年提出的公钥密码体制和椭圆曲线加密体系。既能用于数据加密也能用于数字签名,其安全性依赖于计算有限域上离散对数这一难题。在加密过程中,生成的密文长度是明文的两倍,且每次加密后都会在密文中生成一个随机数K,在密码中主要应用离散对数问题的几个性质:求解离散对数(可能)是困难的,而其逆运算指数运算可以应用平方-乘的方法有效地计算。也就是说,在适当的群G中,指数函数是单向函数。
2、ELGamal算法实现
package lzf.cipher.bc;
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.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
/**
* @author Java小工匠
*/
public class BCElGamalUtils {
public static final String ELGAMAL = "ElGamal";
public static KeyPair initKey() {
try {
// 加入对BouncyCastle支持
Security.addProvider(new BouncyCastleProvider());
// 初始化参数生成器
AlgorithmParameterGenerator apg = AlgorithmParameterGenerator.getInstance(ELGAMAL, "BC");
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;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 获取公钥
public static byte[] getPublicKey(KeyPair keyPair) {
byte[] bytes = keyPair.getPublic().getEncoded();
return bytes;
}
// 获取公钥
public static String getPublicKeyStr(KeyPair keyPair) {
byte[] bytes = keyPair.getPublic().getEncoded();
return Hex.toHexString(bytes);
}
// 获取私钥
public static byte[] getPrivateKey(KeyPair keyPair) {
byte[] bytes = keyPair.getPrivate().getEncoded();
return bytes;
}
// 获取私钥
public static String getPrivateKeyStr(KeyPair keyPair) {
byte[] bytes = keyPair.getPrivate().getEncoded();
return Hex.toHexString(bytes);
}
// 公钥加密
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
Security.addProvider(new BouncyCastleProvider());
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance(ELGAMAL);
// X509转公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
// 产生公钥
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
// 数据加密
Cipher cipher = Cipher.getInstance(ELGAMAL);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
// 私钥解密
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
Security.addProvider(new BouncyCastleProvider());
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(ELGAMAL);
// 生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 数据解密
Cipher cipher = Cipher.getInstance(ELGAMAL);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
public static void main(String[] args) throws Exception {
// 生成密钥对
KeyPair keyPair = initKey();
byte[] publicKey = getPublicKey(keyPair);
byte[] privateKey = getPrivateKey(keyPair);
System.out.println("公钥:" + Hex.toHexString(publicKey));
System.out.println("私钥:" + Hex.toHexString(privateKey));
String str = "JAVA小工匠";
System.out.println("原文:" + str);
byte[] encryptData = encrypt(str.getBytes(), publicKey);
System.out.println("加密数据:" + Hex.toHexString(encryptData));
byte[] decryptData = decrypt(encryptData, privateKey);
System.out.println("解密数据:" + new String(decryptData));
}
}
3、ELGamal 常见问题
如果上述代码出现 Illegal key size or default parameters 这样的错误。
因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。
解决办法
(1)下载策略文件
官方网站提供了JCE无限制权限策略文件的下载,或者可以查看JRE_HOME/lib/security/policy/unlimited 是否存在 local_policy.jar 和US_export_policy.jar
JDK6的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
(2) 拷贝JAR 包
将US_export_policy.jar和 local_policy.jar 拷贝的 JRE_HOME/lib/security 目录中。
如果读完觉得有收获的话,欢迎点赞、关注、加公众号【小工匠技术圈】
个人公众号,欢迎关注,查阅更多精彩历史!