【Java小工匠聊密码学】--非对称加密--ElGamal
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 目录中。
- 洛谷P3388 【模板】割点(割顶)(tarjan求割点)
- 每天学一点Docker(3)(制作你的第一个容器)
- 1635: [Usaco2007 Jan]Tallest Cow 最高的牛
- 1653: [Usaco2006 Feb]Backward Digit Sums
- 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场
- 1682: [Usaco2005 Mar]Out of Hay 干草危机
- 1637: [Usaco2007 Mar]Balanced Lineup
- AutoFac在项目中的应用
- 每天学一点Docker(5)——了解Docker架构
- 跨站请求伪造(CSRF/XSRF)
- 我这么玩Web Api(一)
- 1624: [Usaco2008 Open] Clear And Present Danger 寻宝之路
- 点双连通分量与割点
- 1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- tp5(thinkPHP5)框架连接数据库的方法示例
- CI框架附属类用法分析
- ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
- PHP封装的page分页类定义与用法完整示例
- Swoole实现异步投递task任务案例详解
- Keras预训练的ImageNet模型实现分类操作
- 通过实例解析Python RPC实现原理及方法
- PHP实现的支付宝支付功能示例
- 为Plesk PHP7启用Oracle OCI8扩展方法总结
- PHP模版引擎原理、定义与用法实例
- python如何查看安装了的模块
- Linux下源码包安装Swoole及基本使用操作图文详解
- python实现简易版学生成绩管理系统
- PHP中localeconv()函数的用法
- 解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题