密码技术学习(6.2.3)-非对称加密在Java中的使用-ElGamal算法

版权声明:转载请注明出处 https://blog.csdn.net/laozhaishaozuo/article/details/81975763
  • ElGamal算法

ElGamal算法

ElGamal算法,是一种较为常见的加密算法,它是基于1985年提出的公钥密码体制和椭圆曲线加密体系。百度百科

就像之前说的,ElGamal算法也是基于数学难题,不过ElGamal是基于离散对数。它跟RSA算法一样,既能应用于数据加密也能应用于数字签名。 
在Jdk8中本身并没有提供ElGamal算法的支持,我们可以使用Bouncy Castle 加密组件。

ElGamalCoder

import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.Key;
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 java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ElGamalParameterSpec;

/**
 * ElGamal 编码组件<br>
 * jdk 不支持 Bouncy Castle支持
 * 
 * @author shaozuo
 * @date 2018/08/01
 */
public final class ElGamalCoder {

    public static final String ALGORITHM_NAME = "ElGamal";

    private ElGamalCoder() {

    }

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private static final int KEY_SIZE = 256;
    private static final String PUBLIC_KEY = "public_key";
    private static final String PRIVATE_KEY = "private_key";

    /**
     * 初始化公钥
     * 
     * @return Map 密钥map
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
        AlgorithmParameterGenerator parameterGenerator = AlgorithmParameterGenerator
                .getInstance(ALGORITHM_NAME);
        parameterGenerator.init(KEY_SIZE);

        AlgorithmParameters parameters = parameterGenerator.generateParameters();

        ElGamalParameterSpec spec = parameters.getParameterSpec(ElGamalParameterSpec.class);

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_NAME);
        keyPairGenerator.initialize(spec, new SecureRandom());

        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    public static byte[] getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }

    public static byte[] getPublicKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }

    /**
     * 使用公钥加密数据
     * 
     * @param data
     *            待加密数据
     * @param encodedPublicKey
     *            公钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] encyptByPublicKey(byte[] data, byte[] encodedPublicKey)
            throws GeneralSecurityException {
        X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(encodedPublicKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PublicKey publicKey = factory.generatePublic(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        System.out.println(data.length);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密数据
     * 
     * @param data
     *            待解密数据
     * @param encodedPublicKey
     *            私钥
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] decyptByPrivateKey(byte[] data, byte[] encodedPrivateKey)
            throws GeneralSecurityException {
        PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
        KeyFactory factory = KeyFactory.getInstance(ALGORITHM_NAME);
        PrivateKey privateKey = factory.generatePrivate(encodedKeySpec);

        Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

}

ElGamalCoderTest

import static org.junit.Assert.assertEquals;

import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.junit.Test;

public class ElGamalCoderTest {
    // 公钥
    private byte[] publicKey;
    // 私钥
    private byte[] privateKey;

    String rawStrForPub = "ElGamal加密";

    @Before
    public final void initKey() throws Exception {
        Map<String, Object> keyMap = ElGamalCoder.initKey();
        publicKey = ElGamalCoder.getPublicKey(keyMap);
        privateKey = ElGamalCoder.getPrivateKey(keyMap);

        System.out.println("公钥: " + Base64.encodeBase64String(publicKey));
        System.out.println("私钥: " + Base64.encodeBase64String(privateKey));

    }

    @Test
    public void test() throws Exception {

        System.out.println("待加密数据:" + rawStrForPub);
        System.out.println("原文:" + rawStrForPub);

        byte[] encodeData = ElGamalCoder.encyptByPublicKey(rawStrForPub.getBytes(), publicKey);
        System.out.println("加密数据: " + Base64.encodeBase64String(encodeData));

        byte[] decodeData = ElGamalCoder.decyptByPrivateKey(encodeData, privateKey);
        String output = new String(decodeData);
        System.out.println("解密数据:" + output);

        assertEquals(rawStrForPub, output);
    }
}

参考资料

关于本章内容,参考了一下书籍和文章

  1. Java加密与解密的艺术 链接
  2. ElGamal算法百度百科
  3. Jdk支持的算法官方文档
  4. Bouncy Castle

本系列其他文章

密码技术学习系列文章

猜你喜欢

转载自blog.csdn.net/laozhaishaozuo/article/details/81975763
今日推荐