非对称和对称加密结合

package test;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class ParseUtil {
    /**
     * AES算法名称
     */
    private final static String AES = "AES";
    /**
     * 算法
     */
    public final static String ALGORITHM = "RSA";
    /**
     * 哈希算法
     */
    public final static String HASH = "SHA";
    //
    /**
     * 签名哈希算法
     */
    public final static String SHA1WITHRSA = "SHA1withRSA";


    public static void main(String[] args) {

//        用户系统持有的秘钥
        String userPrivate = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJkxG9Xo1O/bnqZWTt4HgjNxlDgnNjFXm9ZJbxTOpoao6pCGcZzT1hHHUJSoMrYlQR3/qkjUwEr72G71aBdTa7KXATVs0ca2IfOA9HxNV13XlpikwDGzL0fERlRAj3eCPM6ykouOpLSoXZBtIS2dw0tlHn14ufWcmHVOyuhkPgIfAgMBAAECgYEAjFyCtKxw7pS7+Ix8FtOqaJhYxlqnPO6Yyu7d6KKv0hJTWbjVwGwYaJHHM24piNr5nxLyY2kMB6hZ1tDkXvsAYWZk3R4sf9t0+Qrwh3xwM2OhWpUlyeTCA16fxCloSVLrhiwvLZmjinVKybYTNUIvg7bFoVDK+YCOjoLvA+38agECQQDTt/pGhOudiHEVt+0QMGf1HvMLZWFjtxPQulVgmHXL95hh1y6Qyj39Q58xOQupig6rUcqOJE/4hLS8YXyQzX/PAkEAuTtv7s2DIwP4J0GqQ4gG69xEb/LLWqx8qajn2SinSH8V4bpd1z2O6gnqrpWdqvGFab86BGJxrq8TPRbJfnIcsQJBALcdmdbiYhMXjo91TBHDfDaS9S13GvuuvfG7J9rrIn8uf9qnzXunoGPr18UwDLkvUi61CFdWauCMjvGb86weQRsCQArbKe9ECjiGJgge+BynH0i5iyVIhJSW4WOMK7J1iIBeOmkVZCSWTgb3d9KtoCUBrMEK3Rqermz/g9AjwsFvbLECQEVekV8lUacnXehwU+wvNw+rD53E6cW7ntS142g4oH0TulASSi8w1IMTBrgE3OfPsoKQM67Tm8wzTiSubnMFCog=";
        String systemPubic = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnuJEgORIe4jROGM7MlKYqBT+nCid95oUoQYHyv0wXkxJehBCveqgxlC0Ql1MsKT96wz8aY2mduwCtyRyhYB+pyj6kLj/hkSk83p5jA5ylw/ATJ7C1v0tCW64qZ/u3K+Nw/yqDNTpeP8/9DoIsD4rOnkHbTckisbtijIo88sAyMQIDAQAB";

//        系统持有的秘钥
        String systemPrivate = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKe4kSA5Eh7iNE4YzsyUpioFP6cKJ33mhShBgfK/TBeTEl6EEK96qDGULRCXUywpP3rDPxpjaZ27AK3JHKFgH6nKPqQuP+GRKTzenmMDnKXD8BMnsLW/S0Jbripn+7cr43D/KoM1Ol4/z/0OgiwPis6eQdtNySKxu2KMijzywDIxAgMBAAECgYAEBo0NLfF+ZkWFHllQVb0LQyb89mRuRCssBS5+ShMkebY2KItR+uqwjfLq9AbeB3trkeYg1wQA8i0Y/ru+L9VyrqqEntqoWtoJtFc968/qu+Qt28gn/t85nEnchlvc1J7oSpdpNRfLxSjAqQ0xz7/dXcBDH9V3RHik+CTqSB06xQJBAP9+c+oCXEjUJzoR+WcDirA7kFnlk0Y3p+QslRvTEpLq9w1f26PQj/2Jqdu1/kUyzoA4B5esIcqWUUeCXmSv0JsCQQCoDZvxrsIRGPDM6xaaLugBfd5vuUTOztiNZm9XfOosn8s8imcJ2FUu0qRHKhsVbCmEd2AlVfLBE5T3QbzcllcjAkEAipYwEAY5wrN5l7E6RJuSNigJFApIibUU19srAo3KrHDRk6qkfEZcZJ2wymH8y9JUWw6JZ8dSCQ7ihdR8mUcY8wJAHOOKBTfngIzrCC75ibO6ilca39XXcD26mEQdq8p7bwRhKZ0ZLWYU7qGjP+CLG1mmoXDsBD8MJgi5uO+CCeGGRQJAA8kbFl1eSFnI367JPLZBd8GEvLmmw7N1NeVz7iJ30bYJ/5OOFWRxKkeTastTWJlkIvEK/srwJKQyk4tNZ67tcg==";
        String userPublic = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZMRvV6NTv256mVk7eB4IzcZQ4JzYxV5vWSW8UzqaGqOqQhnGc09YRx1CUqDK2JUEd/6pI1MBK+9hu9WgXU2uylwE1bNHGtiHzgPR8TVdd15aYpMAxsy9HxEZUQI93gjzOspKLjqS0qF2QbSEtncNLZR59eLn1nJh1TsroZD4CHwIDAQAB";
        //加密userId
        String userId = "3";
        byte[] bytes = RSAUtils.sign(Base64.decodeBase64(userPrivate), RSAUtils.mdigestSHA(userId.getBytes()));
        String cryptUserId = Base64.encodeBase64String(bytes);//加密后的userId

        //用户系统加密数据示例
        String cyptContent = encryptSample(userPrivate, systemPubic, "用户加密测试数据",Long.valueOf(userId));

        //用户系统解密数据示例
        String data =encryptSample(systemPrivate, userPublic, "用户解密测试数据",Long.valueOf(userId));//系统加密数据
        String plainContent = decryptSample(systemPubic, userPrivate, data);//用户系统解密

        System.out.println("加密内容:" + cyptContent);
        System.out.println("解密内容:" + plainContent);
    }


    /**
     * 生成密钥
     *
     * @return
     */
    public static byte[] initkey() {
        SecretKey secretKey = null;
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(AES);
            keyGen.init(128);
            secretKey = keyGen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return secretKey.getEncoded();
    }

    /**
     * AES加密
     *
     * @param data
     * @param key
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key) {
        byte[] cipherBytes = null;
        try {
            SecretKey secretKey = new SecretKeySpec(key, AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            cipherBytes = cipher.doFinal(data);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return cipherBytes;
    }

    /**
     * AES解密
     *
     * @param data
     * @param key
     * @return
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        byte[] plainBytes = null;
        try {
            SecretKey secretKey = new SecretKeySpec(key, AES);
            Cipher cipher = Cipher.getInstance(AES);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            plainBytes = cipher.doFinal(data);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return plainBytes;
    }

    /**
     * 使用RSA公钥加密数据
     *
     * @param pubKeyInByte 打包的byte[]形式公钥
     * @param data         要加密的数据
     * @return 加密数据
     */
    public static byte[] encryptByRSA(byte[] pubKeyInByte, byte[] data) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyInByte);
            PublicKey publicKey = keyFactory.generatePublic(pubSpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 用RSA私钥解密
     *
     * @param privateKeyInByte 私钥打包成byte[]形式
     * @param data             要解密的数据
     * @return 解密数据
     */
    public static byte[] decryptByRSAPrivateKey(byte[] privateKeyInByte, byte[] data) {
        try {
            PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(
                    privateKeyInByte);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PrivateKey privateKey = keyFactory.generatePrivate(privSpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 生成数字摘要
     * @param source
     * @return
     */
    public static byte[] mdigestSHA(byte[] source) {
        try {
            MessageDigest thisMD = MessageDigest.getInstance(HASH);
            byte[] digest = thisMD.digest(source);
            return digest;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 使用私钥加密数据(发送数据采用私钥签名)
     * 用一个已打包成byte[]形式的私钥加密数据,即数字签名
     *
     * @param privateKeyInByte 打包成byte[]的私钥
     * @param source           要签名的数据,一般应是数字摘要
     * @return 签名 byte[]
     */
    public static byte[] sign(byte[] privateKeyInByte, byte[] source) {
        try {
            PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKeyInByte);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PrivateKey privateKey = keyFactory.generatePrivate(privateSpec);
            Signature signature = Signature.getInstance(SHA1WITHRSA);
            signature.initSign(privateKey);
            signature.update(source);
            return signature.sign();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 验证签名(接收数据使用发送方公钥验证签名)
     *
     * @param publicKeyInByte 二进制公钥
     * @param source           源数据
     * @param sign             数字签名
     * @return 验证结果
     */
    public static boolean verify(byte[] publicKeyInByte, byte[] source, byte[] sign) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            Signature signature = Signature.getInstance(SHA1WITHRSA);
            X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(publicKeyInByte);
            PublicKey publicKey = keyFactory.generatePublic(pubSpec);
            signature.initVerify(publicKey);
            signature.update(source);
            return signature.verify(sign);
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 加密示例
     * @param userPrivateKey
     * @param sysPublicKey
     * @param content
     * @return
     */
    public static String encryptSample(String userPrivateKey, String sysPublicKey, String content,Long userId) {
        SendData data = new SendData();
        //生成AES密钥
        byte[] AESKeyBytes = ParseUtil.initkey();

        //RSA公钥加密AES密钥
        byte[] cipherKeyBytes = ParseUtil.encryptByRSA(Base64.decodeBase64(sysPublicKey), AESKeyBytes);
        //加密文本
        byte[] cipherTextBytes = ParseUtil.encrypt(content.getBytes(), AESKeyBytes);
        //签名(通过加密文本获取数字摘要,然后对摘要通过用户私钥进行签名)
        byte[] signBytes = ParseUtil.sign(Base64.decodeBase64(userPrivateKey), ParseUtil.mdigestSHA(cipherTextBytes));

        data.setAESKeyString(Base64.encodeBase64String(cipherKeyBytes));
        data.setCyptContent(Base64.encodeBase64String(cipherTextBytes));
        data.setSign(Base64.encodeBase64String(signBytes));
        data.setUserId(userId);
        return JsonUtil.toJson(data);
    }

    /**
     * 解密示例
     * @param userPublicKey
     * @param sysPrivateKey
     * @param cyptContent
     * @return
     */
    public static String decryptSample(String userPublicKey, String sysPrivateKey, String cyptContent) {
        ReceiveData data = JsonUtil.fromJson(cyptContent, ReceiveData.class);

        //从base64中获取字节数组
        //RSA公钥加密AES密钥
        byte[] cipherKeyBytes = Base64.decodeBase64(data.getAESKeyString());
        //加密文本
        byte[] cipherTextBytes = Base64.decodeBase64(data.getCyptContent());
        //签名(通过加密文本获取数字摘要,然后对摘
        byte[] signBytes = Base64.decodeBase64(data.getSign());

        //验证签名
        boolean isValid = ParseUtil.verify(Base64.decodeBase64(userPublicKey),
                ParseUtil.mdigestSHA(cipherTextBytes),
                signBytes);

        if (isValid) {
            //RSA私钥解密AES密钥
            byte[] AESKeyBytes = decryptByRSAPrivateKey(Base64.decodeBase64(sysPrivateKey), cipherKeyBytes);
            if (AESKeyBytes != null) {
                byte[] plainText = decrypt(cipherTextBytes, AESKeyBytes);
                return new String(plainText);
            }
        }
        return null;
    }

    /**
     * json转换工具
     */
    public static class JsonUtil {

        private static final ObjectMapper JSON_MAPPER;

        static {
            JSON_MAPPER = new ObjectMapper();
            JSON_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            JSON_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }

        public static String toJson(Object obj) {
            try {
                return JSON_MAPPER.writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return null;
        }

        public static <T> T fromJson(String json, Class<T> cla) {
            try {
                return JSON_MAPPER.readValue(json, cla);
            } catch (Exception e) {
                e.printStackTrace();
                //LOG.error("error on fromJson", e);
            }
            return null;
        }
    }

    /**
     * 企业方接收数据格式
     */
    public static class ReceiveData {
        private final String status = "success";
        private String sign;
        private String cyptContent;
        private String AESKeyString;

        public String getStatus() {
            return status;
        }

        public String getSign() {
            return sign;
        }

        public void setSign(String sign) {
            this.sign = sign;
        }

        public String getCyptContent() {
            return cyptContent;
        }

        public void setCyptContent(String cyptContent) {
            this.cyptContent = cyptContent;
        }

        public String getAESKeyString() {
            return AESKeyString;
        }

        public void setAESKeyString(String AESKeyString) {
            this.AESKeyString = AESKeyString;
        }
    }

    /**
     * 企业方发送数据格式
     */
    public static class SendData {

        private Long userId;
        private String sign;
        private String cyptContent;
        private String AESKeyString;

        public Long getUserId() {
            return userId;
        }

        public void setUserId(Long userId) {
            this.userId = userId;
        }

        public String getSign() {
            return sign;
        }

        public void setSign(String sign) {
            this.sign = sign;
        }

        public String getCyptContent() {
            return cyptContent;
        }

        public void setCyptContent(String cyptContent) {
            this.cyptContent = cyptContent;
        }

        public String getAESKeyString() {
            return AESKeyString;
        }

        public void setAESKeyString(String AESKeyString) {
            this.AESKeyString = AESKeyString;
        }
    }

}
原文地址:https://www.cnblogs.com/guozhigang/p/10775730.html