java 非对称加密算法

慕课网学习笔记
参考:java加密算法


      • DH密钥交换算法
      • 非对称加密算法RSA
      • Elgamal算法


加密密钥分为公钥和私钥。可以使用公钥加密私钥解密,也可以使用私钥加密公钥解密。非对称加密算法主要有:DH(Diffie-Hellman)密钥交换算法、RSA(基于因子分解)、Elgamal(基于离散对数)、ECC(Elliptical Curve Cryptography,椭圆曲线加密)。

DH(密钥交换)算法

如何安全地传送密钥是对称加密算法的症结所在。密钥交换算法是通过构建本地密钥来解决对称加密算法中的密钥传递的问题的。
这里写图片描述

实现该算法的步骤和所需要的类如下:

  1. 初始化发送方密钥
    -KeyPairGenerator
    -KeyPair(密钥载体,密钥对,包括公约和私钥)
    -PublicKey
  2. 初始化接收方密钥
    -KeyFactory(可以生成公钥和私钥)
    -X509EncodedKeySpec(根据ASN.1标准进行密钥编码)
    -DHPublicKey
    -DHParameterSpec
    -KeyPairGenerator
    -PrivateKey
  3. 密钥构建
    -KeyAgreement(提供密钥一致性或密钥交换协议的功能)
    -SecretKey(生成一个分组的秘密密钥)
    -KeyFactory
    -X509EncodedKeySpec
    -PublicKey
  4. 加解密
    -Cipher(JCE框架的核心)

具体实现:

package dh;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Base64;

public class JavaDH {

    private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串

    public static void main(String[] args) throws Exception {
        System.out.println("初始字符串:" + src);
        jdkDH();
    }

    /** JDK实现密钥交换算法 */
    public static void jdkDH() throws Exception{

        //1.初始化发送方密钥
        KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("dh");
        senderKeyPairGenerator.initialize(512);//密钥长度512
        KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
        byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();//发送方公钥(需要把这个发送给)

        //2.初始化接收方密钥
        KeyFactory receiverkeyFactory = KeyFactory.getInstance("dh");
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
        PublicKey receiverPublicKey = receiverkeyFactory.generatePublic(x509EncodedKeySpec);
        DHParameterSpec dhParameterSpec = ((DHPublicKey)receiverPublicKey).getParams();
        KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("dh");
        receiverKeyPairGenerator.initialize(dhParameterSpec);
        KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
        PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();

        //3.密钥构建
        KeyAgreement receiverkeyAgreement = KeyAgreement.getInstance("dh");
        receiverkeyAgreement.init(receiverPrivateKey);
        receiverkeyAgreement.doPhase(receiverPublicKey, true);
        SecretKey receiverDesKey = receiverkeyAgreement.generateSecret("des");
        byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();

        KeyFactory senderKeyFactory = KeyFactory.getInstance("dh");
        x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
        PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
        KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("dh");
        senderKeyAgreement.init(senderKeyPair.getPrivate());
        senderKeyAgreement.doPhase(senderPublicKey, true);
        SecretKey senderDesKey = senderKeyAgreement.generateSecret("des");
        if (Objects.equals(senderDesKey,receiverDesKey)) {
            System.out.println("双方密钥相同");
        }

        //4.加密
        Cipher cipher = Cipher.getInstance("des");
        cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
        byte[] result = cipher.doFinal(src.getBytes());
        System.out.println("密钥交换算法加密:" + Base64.encodeBase64String(result));

        //5.解密
        cipher.init(cipher.DECRYPT_MODE, receiverDesKey);
        result = cipher.doFinal(result);
        System.out.println("密钥交换算法解密:" + new String(result));
    }
}

运行结果:
java 非对称加密算法_第1张图片

java 非对称加密算法_第2张图片

非对称加密算法——RSA

RSA是唯一被广泛接受并实现的通用算法。
java 非对称加密算法_第3张图片

在RSA算法中公钥的长度远远小于私钥的长度。以下是其java实现:

package rsa;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;


public class JavaRSA {

    private static String src = "面向对象编程,object-oriented!@#*5"; // 需要加密的原始字符串

    public static void main(String[] args) throws Exception {

        System.out.println("初始字符串:" + src);
        jdkRSA();

    }

    public static void jdkRSA() throws Exception{
        //1.初始化密钥
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(512);//密钥长度为64的整数倍,最大是65536
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        System.out.println("RSA公钥:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
        System.out.println("RSA私钥:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

        //2.1私钥加密,公钥解密【加密】
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(src.getBytes());
        System.out.println("JDK RSA私钥加密:" + Base64.encodeBase64String(result));

        //2.2私钥加密,公钥解密【解密】
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
        keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        result = cipher.doFinal(result);
        System.out.println("JDK RSA公钥解密:" + new String(result));

        //3.1公钥加密,私钥解密【加密】
        x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
        keyFactory = KeyFactory.getInstance("RSA");
        publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        result = cipher.doFinal(src.getBytes());
        System.out.println("JDK RSA公钥加密:" + Base64.encodeBase64String(result));

        //3.2公约加密,私钥解密【解密】
        pkcs8EncodedKeySpec =  new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
        keyFactory = KeyFactory.getInstance("RSA");
        privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        result = cipher.doFinal(result);
        System.out.println("JDK RSA私钥解密:" + new String(result));
    }

}

运行结果:
java 非对称加密算法_第4张图片

RSA有两种模式公钥加密私钥解密和私钥加密公钥解密两种模式,其序列图如下:
java 非对称加密算法_第5张图片

Elgamal算法

和RSA不同的是它只提供公钥加密,它依靠BouncyCastle实现。
java 非对称加密算法_第6张图片

java 非对称加密算法_第7张图片

package elgamal;

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.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
 * 非对称加密算法——ELGamal算法
 * 对于:“Illegal key size or default parameters”异常,是因为美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。
 * Java 7 无政策限制文件:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html,
 * 下载后得到UnlimitedJCEPolicyJDK7.zip,解压替换%JAVA_HOME%/jre/lib/security的两个文件即可
 * @author gaopengfei
 *
 */
public class JavaELGamal {

    private static String src = "object-oriented!@#*5"; // 需要加密的原始字符串

    public static void main(String[] args) throws Exception {
        System.out.println("初始字符串:" + src);
        bouncyCastleELGamal();
    }

    /**
     * Bouncy Castle实现ELGamal,这种算法和RSA算法的区别是只能公钥加密,私钥解密
     * */
    private static void bouncyCastleELGamal() throws Exception{

        Security.addProvider(new BouncyCastleProvider());//加入对Bouncy Castle的支持

        //1.初始化发送方密钥
        AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance("ELGamal");
        algorithmParameterGenerator.init(256);//初始化参数生成器
        AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();//生成算法参数
        DHParameterSpec dhParameterSpec = (DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);//构建参数材料
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ELGamal");//实例化密钥对生成器
        //初始化密钥对生成器
        keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //公钥和私钥
        PublicKey elGamalPublicKey = keyPair.getPublic();
        PrivateKey elGamalPrivateKey = keyPair.getPrivate();
        System.out.println("ELGamal公钥:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
        System.out.println("ELGamal私钥:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));

        //2.加密【公钥加密】
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
        KeyFactory keyFactory = KeyFactory.getInstance("ELGamal");
        elGamalPublicKey = (PublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance("ELGamal","BC");
        cipher.init(Cipher.ENCRYPT_MODE, elGamalPublicKey);
        byte[] result = cipher.doFinal(src.getBytes());
        System.out.println("ELGamal公钥加密:" + Base64.encodeBase64String(result));

        //3.解密【私钥解密】
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
        keyFactory = KeyFactory.getInstance("ELGamal");
        elGamalPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        cipher.init(Cipher.DECRYPT_MODE, elGamalPrivateKey);
        result = cipher.doFinal(result);
        System.out.println("ELGamal私钥解密:" + new String(result));

//        //加密【私钥加密】
//        pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
//        keyFactory = KeyFactory.getInstance("ELGamal");
//        elGamalPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//        cipher.init(Cipher.ENCRYPT_MODE, elGamalPrivateKey);
//        result = cipher.doFinal(src.getBytes());
//        System.out.println("ELGamal私钥加密:" + Base64.encodeBase64String(result));
//        
//        //解密【公钥解密】
//        x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
//        keyFactory = KeyFactory.getInstance("ELGamal");
//        elGamalPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//        cipher.init(Cipher.DECRYPT_MODE, elGamalPublicKey);
//        result = cipher.doFinal(result);
//        System.out.println("ELGamal解密:" + new String(result));
    }
}

你可能感兴趣的:(java,二三事)