【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 目录中。


原文发布于微信公众号 - 小工匠技术圈(xgn177971793771)

原文发表时间:2018-07-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

分享一个 HTTPS A+ 的 nginx 配置

测试地址:https://www.ssllabs.com/ssltest/ nginx 配置,只贴出 SSL 相关,需要将配置放到 server {} 位置。 ...

2975
来自专栏静默虚空的博客

[Java 安全]消息摘要与数字签名

消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收...

2528
来自专栏吴伟祥

加密总结 原

DES(Data Encryption Standard):对称算法,数据加密标准,速度较快,适用于加密大量数据的场合;

1114
来自专栏菩提树下的杨过

RxJava2学习笔记(3)

接上回继续,今天来学习下zip(打包)操作 一、zip操作 @Test public void zipTest() { Obse...

4396
来自专栏码匠的流水账

java加解密实例

1212
来自专栏iOS 开发杂谈

HTTPS 之对称加密与非对称加密

加密 encryption 与解密 decryption 使用的是同样的密钥 secret key,对称加密是最快速、最简单的一种加密方式。加密和解密算法是公开...

2744
来自专栏安智客

Android O中对TEE加解密算法的新要求

我们都知道,Android中keystore机制中的keymaster需要在TEE实现。Google关于Android后续版本中keymaster中的加解密算法...

2645
来自专栏数据之美

pyDes 实现 Python 版的 DES 对称加密/解密

手头有个 Java 版的 DES 加密/解密程序,最近想着将其 Python 重构下,方便后续脚本解析,捣鼓了两下 pyDes 貌似很方便,不过据网上其他同学测...

7556
来自专栏小工匠技术圈

【Java小工匠聊密码学】--对称加密--AES

  AES加密算法是密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的...

1192
来自专栏静默虚空的博客

[Java 安全]加密算法

Base64编码 算法简述 定义 Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别。 Base64是一种很常见的编码规范...

7386

扫码关注云+社区

领取腾讯云代金券