总结Java中常用的加解密技术和代码简单实现

注意:建议阅读本文之前,先行阅读下面这篇文章,建立对密码学技术体系的整体认知:
https://blog.csdn.net/weixin_39190897/article/details/82223408

加密代码提供方

JDK:代码在java安装目录下的jre\lib\jce.jar包里;
CC:Apache公司提供的org.apache.commons.codec
主页: http://commons.apache.org/proper/commons-codec/
BC:org.bouncecastle
主页: http://www.bouncycastle.org/java.html
基本常用的使用JDK就够了。

maven引入外部依赖方式:

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
	<groupId>commons-codec</groupId>
	<artifactId>commons-codec</artifactId>
	<version>1.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.60</version>
</dependency>

加密分类

1、双向加密

双向加密即明文加密后形成的密文,可以通过逆向算法还原出明文。

(1)对称加密:即加密与解密用的是同一把秘钥,常用的对称加密技术有DES、AES、AES3、PBE等。
(2)非对称加密:加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA、DH、ElGamal等。

1.1、对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

需要对加密和解密使用相同密钥的加密算法。由于其速度,对称性加密通常在消息发送方需要加密大量数据时使用。

1.2、非对称加密

假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密。如果采用对称加密技术,那么加密与解密用的是同一把秘钥。除非B事先就知道A的秘钥,并且保存好,这样才可以解密A发来的消息。

由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题。而非对称技术的诞生就解决了这个问题。非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密。

扫描二维码关注公众号,回复: 8610910 查看本文章

这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道。这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开。而B想更换自己的密钥时也很方便,只须把公钥告诉大家就可以了。
贴张图:
RSA加解密过程解释

那么,既然非对称加密如此之好,对称加密就没有存在的必要了啊,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差。那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用

举个例子:

假如A要发送一个消息给B,对于发送方的A:
(1) A先生成一个对称秘钥,这个秘钥可以是随机生成的;
(2) A用B的公钥加密第一步生成的这个对称秘钥;
(3) A把加密过的对称秘钥发给B;
(4) A用第一步生成的这个对称秘钥加密实际要发的消息;
(5) A把用对称秘钥加密的消息发给B.

对于接收方B:
(1)他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥
(2)然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文

在这里插入图片描述
对称性加密代码贴上:

package com.pica.cloud.health.sms.server.mapper.symmetric_encryption;

import java.security.Key;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @Description AES算法测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:07
 * @ModifyDate 2019/7/29 15:07
 * @Params
 * @Return
 */
public class AESTest {
    public static final String src = "aes test";

    public static void main(String[] args) {
        jdkAES();
        bcAES();

    }

    /**
     * @Description 用jdk实现
     * @Author Chongwen.jiang
     * @Date 2019/7/29 15:09
     * @ModifyDate 2019/7/29 15:09
     * @Params []
     * @Return void
     */
    public static void jdkAES() {
        try {
            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128);
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] keyBytes = secretKey.getEncoded();

            // KEY转换
            Key key = new SecretKeySpec(keyBytes, "AES");

            // 加密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk aes encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = cipher.doFinal(result);
            System.out.println("jdk aes decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现
     * @Author Chongwen.jiang
     * @Date 2019/7/29 15:09
     * @ModifyDate 2019/7/29 15:09
     * @Params []
     * @Return void
     */
    public static void bcAES() {
        try {
            Security.addProvider(new BouncyCastleProvider());

            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BC");
            keyGenerator.getProvider();
            keyGenerator.init(128);
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] keyBytes = secretKey.getEncoded();

            // KEY转换
            Key key = new SecretKeySpec(keyBytes, "AES");

            // 加密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bc aes encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = cipher.doFinal(result);
            System.out.println("bc aes decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


package com.pica.cloud.health.sms.server.mapper.symmetric_encryption;

import java.security.Key;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @Description DES算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:11
 * @ModifyDate 2019/7/29 15:11
 * @Params
 * @Return
 */
public class DESTest {
    public static final String src = "des test";

    public static void main(String[] args) {
        jdkDES();
        bcDES();

    }

    /**
     * @Description 用jdk实现DES加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:38
     * @ModifyDate 2019/7/29 10:38
     * @Params []
     * @Return void
     */
    public static void jdkDES() {
        try {
            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] bytesKey = secretKey.getEncoded();

            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            Key convertSecretKey = factory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk des encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("jdk des decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现DES加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:38
     * @ModifyDate 2019/7/29 10:38
     * @Params []
     * @Return void
     */
    public static void bcDES() {
        try {
            Security.addProvider(new BouncyCastleProvider());

            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES", "BC");
            keyGenerator.getProvider();
            keyGenerator.init(56);
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] bytesKey = secretKey.getEncoded();

            // KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            Key convertSecretKey = factory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bc des encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("bc des decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


package com.pica.cloud.health.sms.server.mapper.symmetric_encryption;

import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @Description DES3算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:07
 * @ModifyDate 2019/7/29 15:07
 * @Params
 * @Return
 */
public class DES3Test {
    public static final String src = "3des test";

    public static void main(String[] args) {
        jdk3DES();
        bc3DES();

    }

    /**
     * @Description 用jdk实现DES3加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:39
     * @ModifyDate 2019/7/29 10:39
     * @Params
     * @Return
     */
    public static void jdk3DES() {
        try {
            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
            // 必须长度是:112或168
            // keyGenerator.init(168);
            keyGenerator.init(new SecureRandom());
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] bytesKey = secretKey.getEncoded();

            // KEY转换
            DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
            Key convertSecretKey = factory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk 3des encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("jdk 3des decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现DES3加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:40
     * @ModifyDate 2019/7/29 10:40
     * @Params
     * @Return
     */
    public static void bc3DES() {
        try {
            Security.addProvider(new BouncyCastleProvider());

            // 生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede", "BC");
            keyGenerator.getProvider();
            keyGenerator.init(168);
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            byte[] bytesKey = secretKey.getEncoded();

            // KEY转换
            DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
            Key convertSecretKey = factory.generateSecret(desKeySpec);

            // 加密
            Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bc 3des encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("bc 3des decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}


package com.pica.cloud.health.sms.server.mapper.symmetric_encryption;

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

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

/**
 * @Description PBE算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:08
 * @ModifyDate 2019/7/29 15:08
 * @Params
 * @Return
 */
public class PBETest {
    public static final String src = "pbe test";

    public static void main(String[] args) {
        jdkPBE();

    }

    /**
     * @Description 用jdk实现PBE加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:44
     * @ModifyDate 2019/7/29 10:44
     * @Params []
     * @Return void
     */
    public static void jdkPBE() {
        try {
            // 初始化盐
            SecureRandom random = new SecureRandom();
            byte[] salt = random.generateSeed(8);

            // 口令与密钥
            String password = "timliu";
            PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
            Key key = factory.generateSecret(pbeKeySpec);

            // 加密
            PBEParameterSpec pbeParameterSpac = new PBEParameterSpec(salt, 100);
            Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
            cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpac);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdk pbe encrypt:" + Hex.encodeHexString(result));

            // 解密
            cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpac);
            result = cipher.doFinal(result);
            System.out.println("jdk pbe decrypt:" + new String(result));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}


非对称性加密代码贴上:

package com.pica.cloud.health.sms.server.mapper.asymmetric_encryption;

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

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @Description RSA算法非对称性加密实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:17
 * @ModifyDate 2019/7/29 15:17
 * @Params 
 * @Return 
 */
public class RSATest {
    public static final String src = "rsa test";

    public static void main(String[] args) {
        jdkRSA();

    }

    /**
     * @Description jdk实现RSA非对称性加解密
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:45
     * @ModifyDate 2019/7/29 10:45
     * @Params []
     * @Return void
     */
    public static void jdkRSA() {
        try {
            // 1.初始化发送方密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
            System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

            // 2.私钥加密、公钥解密 ---- 加密
            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("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));

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


            // 4.公钥加密、私钥解密 ---- 加密
            X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
            PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
            Cipher cipher2 = Cipher.getInstance("RSA");
            cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
            byte[] result2 = cipher2.doFinal(src.getBytes());
            System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

            // 5.私钥解密、公钥加密 ---- 解密
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");
            PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
            Cipher cipher5 = Cipher.getInstance("RSA");
            cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
            byte[] result5 = cipher5.doFinal(result2);
            System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5));

        } catch (Exception e) {

            e.printStackTrace();
        }

    }

}

package com.pica.cloud.health.sms.server.mapper.asymmetric_encryption;

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 java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

/**
 * @Description RSA并发时间测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:18
 * @ModifyDate 2019/7/29 15:18
 * @Params 
 * @Return 
 */
public class RSAConcurrencyTest {
    public static final String src = "rsa test";

    private static byte[] result;

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

        RSA();

    }

    /**
     * @Description jdk实现:私钥加密、公钥解密: 并发时间测试
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:47
     * @ModifyDate 2019/7/29 10:47
     * @Params []
     * @Return void
     */
    public static void RSA() {
        try {
            long startTimes = System.currentTimeMillis();

            // 1.初始化发送方密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
            System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

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

            long endEncryptTime = System.currentTimeMillis();
            System.out.println("公钥加密、私钥解密 ---- 加密1个时间(单位毫秒):" + (endEncryptTime - startTimes));

            int decryptTimes = 200000;  // 并发解密的个数
            //创建一个可重用固定线程数的线程池
            ExecutorService pool = Executors.newCachedThreadPool(); // Executors.newFixedThreadPool(1000);

            for (int i = 0; i < decryptTimes; i++) {
                pool.execute(new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            // 3.私钥解密、公钥加密 ---- 解密
                            PKCS8EncodedKeySpec pkcs8EncodedKeySpec2 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
                            KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");

                            PrivateKey privateKey2 = keyFactory2.generatePrivate(pkcs8EncodedKeySpec2);
                            Cipher cipher2 = Cipher.getInstance("RSA");
                            cipher2.init(Cipher.DECRYPT_MODE, privateKey2);
                            byte[] result2 = cipher2.doFinal(result);
//							System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result2));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }));

            }

            pool.shutdown();

            while (true) {
                if (pool.isTerminated()) {
                    System.out.println("结束了!");
                    long endDencryptTime = System.currentTimeMillis();
                    long totalTimes = (endDencryptTime - endEncryptTime) / 1000;
                    System.out.println("公钥加密、私钥解密 ---- 并发:" + decryptTimes + "个解密时间(单位秒):" + totalTimes);
                    break;
                }
                Thread.sleep(200);
            }

        } catch (Exception e) {

            e.printStackTrace();
        }

    }


}


package com.pica.cloud.health.sms.server.mapper.asymmetric_encryption;

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

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;

/**
 * @Description DH算法测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:19
 * @ModifyDate 2019/7/29 15:19
 * @Params 
 * @Return 
 */
public class DHTest {
    public static final String src = "dh test";

    public static void main(String[] args) {
        jdkDH();

    }

    // jdk实现:
    public static void jdkDH() {
        try {
            // 1.初始化发送方密钥
            KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
            senderKeyPairGenerator.initialize(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();
            byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();

            // 3.密钥构建
            KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
            receiverKeyAgreement.init(receiverPrivateKey);
            receiverKeyAgreement.doPhase(receiverPublicKey, true);
            SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");

            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 (receiverDesKey.equals(senderDesKey)) {
                System.out.println("双方密钥相同。");
            }

            // 4.加密
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bc dh encrypt:" + Base64.encodeBase64String(result));

            // 5.解密
            cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
            result = cipher.doFinal(result);
            System.out.println("bc dh decrypt:" + new String(result));


        } catch (Exception e) {

            e.printStackTrace();
        }

    }

}


package com.pica.cloud.health.sms.server.mapper.asymmetric_encryption;

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;

/**
 * @Description ElGamal算法测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:19
 * @ModifyDate 2019/7/29 15:19
 * @Params
 * @Return
 */
public class ElGamalTest {

    public static final String src = "Elgamal test";

    public static void main(String[] args) {
        jdkElgamal();

    }

    /**
     * 对于:“Illegal key size or default parameters”异常,是因为美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。因此存在一些问题:
     * Java 6 无政策限制文件:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
     * Java 7 无政策限制文件:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
     * 我的时java7,自己安装的。
     * /Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home/jre/lib/security目录下,对应覆盖local_policy.jar和US_export_policy.jar两个文件。
     * <p>
     * 切换到%JDK_Home%\jre\lib\security目录下,对应覆盖local_policy.jar和US_export_policy.jar两个文件。同时,你可能有必要在%JRE_Home%\lib\security目录下,也需要对应覆盖这两个文件。
     */

    /**
     * @Description jdk实现:“私钥解密、公钥加密” , 对于:“私钥加密、公钥解密”有问题,因为Elgamal不支持
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:49
     * @ModifyDate 2019/7/29 10:49
     * @Params []
     * @Return void
     */
    public static void jdkElgamal() {
        try {
            // 加入对BouncyCastle支持
            Security.addProvider(new BouncyCastleProvider());

            // 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("Public Key:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
            System.out.println("Private Key:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));

            // 2.私钥解密、公钥加密 ---- 加密
            // 初始化公钥
            // 密钥材料转换
            X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
            // 实例化密钥工厂
            KeyFactory keyFactory2 = KeyFactory.getInstance("Elgamal");
            // 产生公钥
            PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
            // 数据加密
            // Cipher cipher2 = Cipher.getInstance("Elgamal");
            Cipher cipher2 = Cipher.getInstance(keyFactory2.getAlgorithm());
            cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
            byte[] result2 = cipher2.doFinal(src.getBytes());
            System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

            // 3.私钥解密、公钥加密 ---- 解密
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
            KeyFactory keyFactory5 = KeyFactory.getInstance("Elgamal");
            PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
            // Cipher cipher5 = Cipher.getInstance("Elgamal");
            Cipher cipher5 = Cipher.getInstance(keyFactory5.getAlgorithm());
            cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
            byte[] result5 = cipher5.doFinal(result2);
            System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result5));

			/*
			// 	私钥加密、公钥解密: 有问题
			// 4.私钥加密、公钥解密 ---- 加密
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
			KeyFactory keyFactory = KeyFactory.getInstance("Elgamal");
			PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			Cipher cipher = Cipher.getInstance("Elgamal");
			cipher.init(Cipher.ENCRYPT_MODE, privateKey);
			byte[] result = cipher.doFinal(src.getBytes());
			System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));
			
			// 5.私钥加密、公钥解密 ---- 解密
			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
			keyFactory = KeyFactory.getInstance("Elgamal");
			PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
			cipher = Cipher.getInstance("Elgamal");
			cipher.init(Cipher.DECRYPT_MODE, publicKey);
			result = cipher.doFinal(result);
			System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result));
			*/

        } catch (Exception e) {

            e.printStackTrace();
        }

    }

}


package com.pica.cloud.health.sms.server.mapper.asymmetric_encryption;


import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @Description 非对称加密算法ElGamal算法组件
 * 非对称算法一般是用来传送对称加密算法的密钥来使用的。相对于RSA算法,这个算法只支持私钥加密公钥解密
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:20
 * @ModifyDate 2019/7/29 15:20
 * @Params
 * @Return
 */
public class ElGamalTest2 {
	//非对称密钥算法
	public static final String KEY_ALGORITHM="ElGamal";

	/**
	 * 密钥长度,DH算法的默认密钥长度是1024
	 * 密钥长度必须是8的倍数,在160到16384位之间
	 * */
	private static final int KEY_SIZE=256;
	//公钥
	private static final String PUBLIC_KEY="ElGamalPublicKey";
	
	//私钥
	private static final String PRIVATE_KEY="ElGamalPrivateKey";
	
	/**
	 * 初始化密钥对
	 * @return Map 甲方密钥的Map
	 * */
	public static Map<String,Object> initKey() throws Exception{
		//加入对BouncyCastle支持
		Security.addProvider(new BouncyCastleProvider());
		AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
		//初始化参数生成器
		apg.init(KEY_SIZE);
		//生成算法参数
		AlgorithmParameters params=apg.generateParameters();
		//构建参数材料
		DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
		
		//实例化密钥生成器
		KeyPairGenerator kpg=KeyPairGenerator.getInstance(KEY_ALGORITHM) ;
		
		//初始化密钥对生成器
		kpg.initialize(elParams,new SecureRandom());
		
		KeyPair keyPair=kpg.generateKeyPair();
		//甲方公钥
		PublicKey publicKey= keyPair.getPublic();
		//甲方私钥
		PrivateKey privateKey= keyPair.getPrivate();
		//将密钥存储在map中
		Map<String,Object> keyMap=new HashMap<String,Object>();
		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
		
	}
	
	
	/**
	 * 公钥加密
	 * @param data 待加密数据
	 * @param key 密钥
	 * @return byte[] 加密数据
	 * */
	public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
		
		//实例化密钥工厂
		KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
		//初始化公钥
		//密钥材料转换
		X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
		//产生公钥
		PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
		
		//数据加密
		Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		return cipher.doFinal(data);
	}
	/**
	 * 私钥解密
	 * @param data 待解密数据
	 * @param key 密钥
	 * @return byte[] 解密数据
	 * */
	public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
		//取得私钥
		PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
		KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
		//生成私钥
		PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
		//数据解密
		Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}
	
	/**
	 * 取得私钥
	 * @param keyMap 密钥map
	 * @return byte[] 私钥
	 * */
	public static byte[] getPrivateKey(Map<String,Object> keyMap){
		Key key=(Key)keyMap.get(PRIVATE_KEY);
		return key.getEncoded();
	}
	/**
	 * 取得公钥
	 * @param keyMap 密钥map
	 * @return byte[] 公钥
	 * */
	public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
		Key key=(Key) keyMap.get(PUBLIC_KEY);
		return key.getEncoded();
	}

	/** main方法测试
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		//初始化密钥
		//生成密钥对
		Map<String,Object> keyMap=ElGamalTest2.initKey();
		//公钥
		byte[] publicKey=ElGamalTest2.getPublicKey(keyMap);
		
		//私钥
		byte[] privateKey=ElGamalTest2.getPrivateKey(keyMap);
		System.out.println("公钥:/n"+Base64.encodeBase64String(publicKey));
		System.out.println("私钥:/n"+Base64.encodeBase64String(privateKey));
		
		System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============");
		String str="ElGamal密码交换算法";
		System.out.println("/n===========甲方向乙方发送加密数据==============");
		System.out.println("原文:"+str);
		
		//乙方使用公钥对数据进行加密
		byte[] code2=ElGamalTest2.encryptByPublicKey(str.getBytes(), publicKey);
		System.out.println("===========乙方使用公钥对数据进行加密==============");
		System.out.println("加密后的数据:"+Base64.encodeBase64String(code2));
		
		
		//甲方使用私钥对数据进行解密
		byte[] decode2=ElGamalTest2.decryptByPrivateKey(code2, privateKey);
		
		System.out.println("甲方解密后的数据:"+new String(decode2));
	}
}




2、单向加密

单向加密只是对信息进行了摘要计算,不能通过算法逆向生成明文。

单向加密技术采用单向散列函数(或称为哈希(Hash)函数/散列函数),可将任意长度的消息散列形成固定长度的散列值(即消息摘要),用于被用户私钥加密后生成数字签名,保证数据的完整性和不可否认性。

单向加密从严格意思上说不能算是加密的一种,而只是摘要算法,常见的单向加密技术有BASE64(一种编码形式)、MD5、SHA、HMAC(消息认证码)。
单向加密代码贴上:

package com.pica.cloud.health.sms.server.mapper.base64;

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

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * @Description Base64加密测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 10:20
 * @ModifyDate 2019/7/29 10:20
 * @Params
 * @Return
 */
public class Base64Test {

	public static final String src = "巴啦啦能量 test";
	public static void main(String[] args) {
		jdkBase64();
		
		commonsCodesBase64();

		bouncyCastleBase64();
	}
	
	/**
	 * @Description 用jdk实现
	 * @Author Chongwen.jiang
	 * @Date 2019/7/29 10:18
	 * @ModifyDate 2019/7/29 10:18
	 * @Params []
	 * @Return void
	 */
	public static void jdkBase64() {
		try 
		{
			BASE64Encoder encoder = new BASE64Encoder();
			String encode = encoder.encode(src.getBytes());
			System.out.println("encode:" + encode);
			
			BASE64Decoder decoder = new BASE64Decoder();
			System.out.println("decode:" + new String(decoder.decodeBuffer(encode)));
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @Description 用Apache的common codes实现
	 * @Author Chongwen.jiang
	 * @Date 2019/7/29 10:18
	 * @ModifyDate 2019/7/29 10:18
	 * @Params []
	 * @Return void
	 */
	public static void commonsCodesBase64() {
		byte[] encodeBytes = Base64.encodeBase64(src.getBytes());
		System.out.println("common codes encode:" + new String(encodeBytes));
		
		byte[] dencodeBytes = Base64.decodeBase64(encodeBytes);
		System.out.println("common codes decode:" + new String(dencodeBytes));
		
	}

	/**
	 * @Description 用bouncy castle实现
	 * @Author Chongwen.jiang
	 * @Date 2019/7/29 10:18
	 * @ModifyDate 2019/7/29 10:18
	 * @Params []
	 * @Return void
	 */
	public static void bouncyCastleBase64() {
		byte[] encodeBytes = org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
		System.out.println("bouncy castle encode:" + new String(encodeBytes));
		
		byte[] dencodeBytes = org.bouncycastle.util.encoders.Base64.decode(encodeBytes);
		System.out.println("bouncy castle decode:" + new String(dencodeBytes));
		
	}

}


package com.pica.cloud.health.sms.server.mapper.message_digest;

import java.security.MessageDigest;
import java.security.Security;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * @Description MD5算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:01
 * @ModifyDate 2019/7/29 15:01
 * @Params 
 * @Return 
 */
public class MD5Test {

    public static final String src = "md5 test";

    public static void main(String[] args) {
        jdkMD5();
        jdkMD2();

        bcMD4();
        bcMD5();

        bc2jdkMD4();

        ccMD5();
        ccMD2();

    }

    /**
     * @Description 用jdk实现:MD5
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:57
     * @ModifyDate 2019/7/29 10:57
     * @Params []
     * @Return void
     */
    public static void jdkMD5() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] md5Bytes = md.digest(src.getBytes());
            System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用jdk实现:MD2
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:57
     * @ModifyDate 2019/7/29 10:57
     * @Params []
     * @Return void
     */
    public static void jdkMD2() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD2");
            byte[] md2Bytes = md.digest(src.getBytes());
            System.out.println("JDK MD2:" + Hex.encodeHexString(md2Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现:MD5
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:58
     * @ModifyDate 2019/7/29 10:58
     * @Params []
     * @Return void
     */
    public static void bcMD5() {
        MD5Digest digest = new MD5Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] md5Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md5Bytes, 0);
        System.out.println("bouncy castle MD5:" + org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));

    }

    /**
     * @Description 用bouncy castle实现:MD4
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:58
     * @ModifyDate 2019/7/29 10:58
     * @Params []
     * @Return void
     */
    public static void bcMD4() {
        MD4Digest digest = new MD4Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] md4Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md4Bytes, 0);
        System.out.println("bouncy castle MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
    }

    /**
     * @Description 用bouncy castle与jdk结合实现:MD4
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:58
     * @ModifyDate 2019/7/29 10:58
     * @Params []
     * @Return void
     */
    public static void bc2jdkMD4() {
        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("MD4");
            byte[] md4Bytes = md.digest(src.getBytes());
            System.out.println("bc and JDK MD4:" + Hex.encodeHexString(md4Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用common codes实现实现:MD5
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:58
     * @ModifyDate 2019/7/29 10:58
     * @Params []
     * @Return void
     */
    public static void ccMD5() {
        System.out.println("common codes MD5:" + DigestUtils.md5Hex(src.getBytes()));
    }

    /**
     * @Description 用common codes实现实现:MD2
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:58
     * @ModifyDate 2019/7/29 10:58
     * @Params []
     * @Return void
     */
    public static void ccMD2() {
        System.out.println("common codes MD2:" + DigestUtils.md2Hex(src.getBytes()));
    }

}


package com.pica.cloud.health.sms.server.mapper.message_digest;

import java.security.MessageDigest;
import java.security.Security;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.digests.SHA224Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.math.BigInteger;

/**
 * @Description SHA算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:04
 * @ModifyDate 2019/7/29 15:04
 * @Params 
 * @Return 
 */
public class SHATest {
    public static final String src = "sha test";

    public static void main(String[] args) {
        jdkSHA1();
        bcSHA1();
        bcSHA224();
        bcSHA224b();
        generateSha256();
        ccSHA1();

    }

    /**
     * @Description 用jdk实现:SHA1
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:56
     * @ModifyDate 2019/7/29 10:56
     * @Params []
     * @Return void
     */
    public static void jdkSHA1() {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(src.getBytes());
            System.out.println("jdk sha-1:" + Hex.encodeHexString(md.digest()));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现:SHA1
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:56
     * @ModifyDate 2019/7/29 10:56
     * @Params []
     * @Return void
     */
    public static void bcSHA1() {

        Digest digest = new SHA1Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] sha1Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(sha1Bytes, 0);
        System.out.println("bc sha-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
    }


    /**
     * @Description 用bouncy castle实现:SHA224
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:56
     * @ModifyDate 2019/7/29 10:56
     * @Params []
     * @Return void
     */
    public static void bcSHA224() {

        Digest digest = new SHA224Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] sha224Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(sha224Bytes, 0);
        System.out.println("bc sha-224:" + org.bouncycastle.util.encoders.Hex.toHexString(sha224Bytes));
    }

    /**
     * @Description 用bouncy castle与jdk结合实现:SHA224
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:56
     * @ModifyDate 2019/7/29 10:56
     * @Params []
     * @Return void
     */
    public static void bcSHA224b() {

        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("SHA224");
            md.update(src.getBytes());
            System.out.println("bc and JDK sha-224:" + Hex.encodeHexString(md.digest()));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void generateSha256() {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");

            md.update(src.getBytes("UTF-8")); // Change this to "UTF-16" if needed
            byte[] digest = md.digest();
            BigInteger bigInt = new BigInteger(1, digest);
            System.out.println("Sha256 hash: " + bigInt.toString(16));
        } catch (Exception e) {
            System.out.println(e.toString());
        }

    }

    /**
     * @Description 用common codes实现实现:SHA1
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:57
     * @ModifyDate 2019/7/29 10:57
     * @Params []
     * @Return void
     */
    public static void ccSHA1() {
        System.out.println("common codes SHA1 - 1 :" + DigestUtils.sha1Hex(src.getBytes()));
        System.out.println("common codes SHA1 - 2 :" + DigestUtils.sha1Hex(src));
    }


}


package com.pica.cloud.health.sms.server.mapper.message_digest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

/**
 * @Description HMAC算法实现测试类
 * @Author Chongwen.jiang
 * @Date 2019/7/29 15:04
 * @ModifyDate 2019/7/29 15:04
 * @Params
 * @Return
 */
public class HMACTest {
    public static final String src = "hmac test";

    public static void main(String[] args) {
        jdkHmacMD5();
        bcHmacMD5();

    }

    /**
     * @Description 用jdk实现:
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:59
     * @ModifyDate 2019/7/29 10:59
     * @Params []
     * @Return void
     */
    public static void jdkHmacMD5() {
        try {
            // 初始化KeyGenerator
            KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
            // 产生密钥
            SecretKey secretKey = keyGenerator.generateKey();
            // 获取密钥
            // byte[] key = secretKey.getEncoded();
            byte[] key = Hex.decodeHex(new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e'});

            // 还原密钥
            SecretKey restoreSecretKey = new SecretKeySpec(key, "HmacMD5");
            // 实例化MAC
            Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm());
            // 初始化MAC
            mac.init(restoreSecretKey);
            // 执行摘要
            byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
            System.out.println("jdk hmacMD5:" + Hex.encodeHexString(hmacMD5Bytes));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用bouncy castle实现
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:59
     * @ModifyDate 2019/7/29 10:59
     * @Params []
     * @Return void
     */
    public static void bcHmacMD5() {
        HMac hmac = new HMac(new MD5Digest());
        // 必须是16进制的字符,长度必须是2的倍数
        hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("123456789abcde")));
        hmac.update(src.getBytes(), 0, src.getBytes().length);

        // 执行摘要
        byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
        hmac.doFinal(hmacMD5Bytes, 0);
        System.out.println("bc hmacMD5:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5Bytes));

    }

}

3、数字签名证书

非对称加密已经灰常安全了,但是还有一个破绽:
服务器A公布了自己的公钥,我的电脑是用服务器A的公钥加密数据后再发给服务器A的;这时候服务器B侵入了我的电脑,把我用来加密的公钥换成了它的公钥,于是我发出去的数据就会被服务器B的私钥破解了。肿么防止公钥被篡改呢?
对,我们想到了前面的消息摘要,服务器A把公钥丢给我的时候,同时去CA申请一份数字证书,其实主要就是公钥的消息摘要,有了这份证书,当我再用公钥加密的时候,我就可以先验证一下当前的公钥是否确定是服务器A发送给我的。
数字签名代码贴上:

// Copyright 2016-2101 Pica.
package com.pica.cloud.health.sms.server.mapper.signature;

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

import java.security.*;
import java.security.interfaces.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @ClassName SignatureTest
 * @Description 数字签名测试类(RSA、DSA、ECDSA)
 * @Author Chongwen.jiang
 * @Date 2019/7/29 10:26
 * @ModifyDate 2019/7/29 10:26
 * @Version 1.0
 */
public class SignatureTest {
    public static final String SRC_RSA = "RSA security is security";

    public static final String SRC_DSA = "DSA security is security";

    public static final String SRC_ECDSA = "ECDSA security is security";

    public static void main(String[] args) {
        jdkRSA();

        jdkDSA();

        jdkECDSA();


    }

    /**
     * @Description 用java的jdk里面相关方法实现rsa的签名及签名验证
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:29
     * @ModifyDate 2019/7/29 10:29
     * @Params []
     * @Return void
     */
    public static void jdkRSA() {
        try {
            // 1.初始化密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();

            // 2.进行签名
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance("MD5withRSA");
            signature.initSign(privateKey);
            signature.update(SRC_RSA.getBytes());
            byte[] result = signature.sign();
            System.out.println("jdk rsa sign:" + Hex.encodeHexString(result) );

            // 3.验证签名
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
            keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            signature = Signature.getInstance("MD5withRSA");
            signature.initVerify(publicKey);
            signature.update(SRC_RSA.getBytes());
            boolean bool = signature.verify(result);
            System.out.println("jdk rsa verify:" + bool);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    /**
     * @Description 用java的jdk里面相关方法实现dsa的签名及签名验证
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:34
     * @ModifyDate 2019/7/29 10:34
     * @Params []
     * @Return void
     */
    public static void jdkDSA () {
        try {
            // 1.初始化密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
            keyPairGenerator.initialize(512);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            DSAPublicKey dsaPublicKey = (DSAPublicKey)keyPair.getPublic();
            DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate();

            // 2.进行签名
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("DSA");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance("SHA1withDSA");
            signature.initSign(privateKey);
            signature.update(SRC_DSA.getBytes());
            byte[] result = signature.sign();
            System.out.println("jdk dsa sign:" + Hex.encodeHexString(result) );

            // 3.验证签名
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());
            keyFactory = KeyFactory.getInstance("DSA");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            signature = Signature.getInstance("SHA1withDSA");
            signature.initVerify(publicKey);
            signature.update(SRC_DSA.getBytes());
            boolean bool = signature.verify(result);
            System.out.println("jdk dsa verify:" + bool);

        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    /**
     * @Description 用java的jdk里面相关方法实现ECDSA的签名及签名验证,要jdk7.x以上,ECDSA:椭圆曲线数字签名算法
     * @Author Chongwen.jiang
     * @Date 2019/7/29 10:34
     * @ModifyDate 2019/7/29 10:34
     * @Params []
     * @Return void
     */
    public static void jdkECDSA () {
        try {
            // 1.初始化密钥
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
            keyPairGenerator.initialize(256);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic();
            ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate();

            // 2.进行签名
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance("EC");
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Signature signature = Signature.getInstance("SHA1withECDSA");
            signature.initSign(privateKey);
            signature.update(SRC_ECDSA.getBytes());
            byte[] result = signature.sign();
            System.out.println("jdk ecdsa sign:" + Hex.encodeHexString(result) );

            // 3.验证签名
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded());
            keyFactory = KeyFactory.getInstance("EC");
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            signature = Signature.getInstance("SHA1withECDSA");
            signature.initVerify(publicKey);
            signature.update(SRC_ECDSA.getBytes());
            boolean bool = signature.verify(result);
            System.out.println("jdk ecdsa verify:" + bool);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

}

关于数字签名和非对称加密算法的使用,还看到一个非常棒的例子,分享给大家:
唉,这个月买了太多的书,到月底揭不开锅了。正巧在QQ上遇到了Clark:
1-2-3:“Clark,我需要200两纹银,能否借给我?”
Clark:“没问题。我这就给你转账。请给我一张借条。”
1-2-3:“太谢谢了,我这就用Word写一个借条给你。”
然后,我新建一个Word文档,写好借条,存盘。然后,然后怎么办呢?我不能直接把借条发送给Clark,原因有:

  1. 我无法保证Clark不会在收到借条后将“纹银200两”改为“纹银2000两”。
  2. 如果我赖账,Clark无法证明这个借条就是我写的。
  3. 普通的Word文档不能作为打官司的证据。
    好在我早就申请了数字证书。我先用我的私钥对借条进行加密,然后将加密后的密文用QQ发送给Clark。Clark收到了借条的密文后,在数字证书认证中心的网站上下载我的公钥,然后使用我的公钥将密文解密,发现确实写的是“借纹银200两”,Clark就可以把银子放心的借给我了,我也不会担心Clark会篡改我的借条,原因是:
  4. 由于我发给Clark的是密文,Clark无法进行修改。Clark倒是可以修改解密后的借条,但是Clark没有我的私钥,没法模仿我对借条进行加密。这就叫防篡改。
  5. 由于用我的私钥进行加密的借条,有且只有我的公钥可以解密。反过来讲,能用我的公钥解密的借条,一定是使用我的私钥加密的,而只有我才拥有我的私钥,这样Clark就可以证明这个借条就是我写的。这就叫防抵赖。
  6. 如果我一直赖着不还钱,Clark把我告上了法庭,这个用我的私钥加密过的Word文档就可以当作程堂证供。因为我国已经出台了《中华人民共和国电子签名法》,使数字签名具有了法律效力。
    您一定已经注意到了,这个使用我的私钥进行了加密的借条,具有了防篡改、防抵赖的特性,并且可以作为程堂证供,就跟我对这个借条进行了“签名”的效果是一样的。对了,“使用我的私钥对借条进行加密”的过程就叫做数字签名。
发布了36 篇原创文章 · 获赞 4 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/weixin_41205148/article/details/97637202