JAVA工具类

RSA签名验签工具类

2020-08-25  本文已影响0人  爪哇驿站
一、引入相关架包(该架包主要用于解析PKCS1证书,若使用PKCS8证书无需引入)
<dependency>
    <groupId>bouncycastle</groupId>
    <artifactId>bcprov-jdk15</artifactId>
    <version>140</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpg-jdk16</artifactId>
    <version>1.46</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.65</version>
</dependency>
二、SecretUtil工具类
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

public class SecretUtil {
    private static Logger logger = LoggerFactory.getLogger(SecretUtil.class);

    public static final String CHARSET = "UTF-8"; // 或者 GBK

    // 设置公钥,私钥长度
    public static final int KEY_SIZE = 2048;

    public static final String PUBLIC_KEY_NAME = "publicKey";
    public static final String PRIVATE_KEY_NAME = "privateKey";

    // 定义加密算法,有DES、DESede(即3DES)、Blowfish
    public static final String ALGORITHM_3DES = "DESede";
    public static final String ALGORITHM_RSA = "RSA";
    public static final String SIGNATURE_ALGORITHM_SHA256 = "SHA256withRSA";
    public static final String SUMMARY_ALGORITHM_SHA256 = "SHA-256";

    // transformation的格式是“算法/工作模式/填充模式”
    public static final String TRANSFORMATION = "DESede/ECB/PKCS5Padding"; // 或者 DESede/CBC/PKCS5Padding

    // 默认3des加密密码
    public static final String DEFAULT_SYMMETRIC_KEY = "4f6b7316a2154a15572394da3dc476644f6b7316a2154a15";

    /**
     * 根据字符串生成密钥字节数组
     *
     * @param keyStr 密钥字符串
     * @return 密钥
     * @throws Exception
     */
    public static SecretKey build3DesKey(String keyStr) throws Exception {
        byte[] key = new byte[24];    //声明一个24位的字节数组,默认里面都是0
        byte[] temp = keyStr.getBytes(CHARSET);    //将字符串转成字节数组
        // 执行数组拷贝, System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)
        if (key.length > temp.length) {
            //如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, temp.length);
        } else {
            //如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中
            System.arraycopy(temp, 0, key, 0, key.length);
        }
        // DESedeKeySpec会帮你生成24位秘钥,key可以是任意长度
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM_3DES);
        SecretKey secretKey = keyFactory.generateSecret(spec);
        return secretKey;
    }

    /**
     * 3DES 加密
     *
     * @param key     密钥
     * @param content 加密内容
     * @return 密文
     */
    public static String encryptBy3Des(String key, String content) {
        if (content == null)
            return "";
        try {
            SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(key), ALGORITHM_3DES);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] res = cipher.doFinal(content.getBytes(CHARSET));
            //encodeBase64会对字符串3位一组自动补全,因而最后可能会出现 == 或者 =
            return Base64.encodeBase64String(res);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 3DES 加密
     *
     * @param content 明文
     * @return 密文
     */
    public static String encryptBy3Des(String content) {
        return encryptBy3Des(DEFAULT_SYMMETRIC_KEY, content);
    }

    /**
     * 3DES 解密
     *
     * @param key     密钥
     * @param content 解密内容
     * @return 明文
     */
    public static String decodeBy3Des(String key, String content) {
        if (StringUtils.isEmpty(content))
            return "";
        try {
            SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(key), ALGORITHM_3DES);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] res = cipher.doFinal(Base64.decodeBase64(content));
            return new String(res, CHARSET);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 3DES 解密
     *
     * @param content 密文
     * @return 明文
     */
    public static String decodeBy3Des(String content) {
        return decodeBy3Des(DEFAULT_SYMMETRIC_KEY, content);
    }


    /**
     * 生成秘钥对
     *
     * @return map
     */
    public static Map<String, String> genRsaKeyPair() {
        Map<String, String> keyPairMap = new HashMap<String, String>();
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM_RSA);
            keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

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

            //获取公、私钥值
            String publicKeyValue = Base64.encodeBase64String(publicKey.getEncoded());
            String privateKeyValue = Base64.encodeBase64String(privateKey.getEncoded());

            //存入
            keyPairMap.put(PUBLIC_KEY_NAME, publicKeyValue);
            keyPairMap.put(PRIVATE_KEY_NAME, privateKeyValue);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return keyPairMap;
    }

    /**
     * 读取证书文件
     *
     * @param keyPath 证书文件路径
     * @return
     * @throws Exception
     */
    public static String readKeyFile(String keyPath) {
        FileInputStream fis = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(keyPath);
            br = new BufferedReader(new InputStreamReader(fis));
            String readLine;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                if (readLine.charAt(0) == '-') {
                    continue;
                } else {
                    sb.append(readLine);
                    sb.append('\r');
                }
            }
            return sb.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null)
                    fis.close();
                if (br != null)
                    br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 根据 PKCS8证书获取公钥
     *
     * @param key
     * @return
     */
    public static PublicKey getPublicKeyFromPKSC8(String key) {
        try {
            byte[] byteKey = Base64.decodeBase64(key);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据 PKCS8证书获取私钥
     *
     * @param key
     * @return
     */
    public static PrivateKey getPrivateKeyFromPKSC8(String key) {
        try {
            byte[] byteKey = Base64.decodeBase64(key);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据 PKCS1证书获取公钥
     *
     * @param keyPath 证书路径
     * @return
     */
    public static PublicKey getPublicKeyFromPKSC1(String keyPath) {
        try {
            PEMParser pemParser = new PEMParser(new FileReader(keyPath));
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            Object object = pemParser.readObject();
            KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
            return kp.getPublic();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据 PKCS1证书获取私钥
     *
     * @param keyPath 证书路径
     * @return
     */
    public static PrivateKey getPrivateKeyFromPKSC1(String keyPath) {
        try {
            PEMParser pemParser = new PEMParser(new FileReader(keyPath));
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            Object object = pemParser.readObject();
            KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
            return kp.getPrivate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * sha-256 摘要
     *
     * @param data
     * @return
     */
    public static String sha256(byte[] data) {
        try {
            MessageDigest md = MessageDigest.getInstance(SUMMARY_ALGORITHM_SHA256);
            return bytesToHex(md.digest(data));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * sha-256 摘要
     *
     * @param data
     * @return
     */
    public static String sha256(String data) {
        return sha256(data.getBytes());
    }


    /**
     * 签名
     *
     * @param privateKey  私钥
     * @param requestData 请求参数
     * @return
     */
    public static String sign(PrivateKey privateKey, String requestData) {
        String signature = null;
        try {
            Signature Sign = Signature.getInstance(SIGNATURE_ALGORITHM_SHA256);
            Sign.initSign(privateKey);
            Sign.update(requestData.getBytes(CHARSET));
            signature = Base64.encodeBase64String(Sign.sign());
            logger.info("===签名结果:" + signature);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return signature;
    }


    /**
     * 验签
     *
     * @param publicKey   公钥
     * @param requestData 请求参数
     * @param signature   签名
     * @return
     */
    public static boolean verifySign(PublicKey publicKey, String requestData, String signature) {
        boolean verifySignRes = false;
        try {
            Signature verifySign = Signature.getInstance(SIGNATURE_ALGORITHM_SHA256);
            verifySign.initVerify(publicKey);
            verifySign.update(requestData.getBytes(CHARSET));
            verifySignRes = verifySign.verify(Base64.decodeBase64(signature));
            logger.info("===验签结果:" + verifySignRes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return verifySignRes;
    }

    /**
     * 构建签名数据, 将 Map 转成 key1=value1&key2=value2...(按照字段名的ASCII 码从小到大排序,即字典序)
     *
     * @param params 请求参数
     * @return
     */
    public static String buildSignData(Map<String, String> params) {
        StringBuilder sb = new StringBuilder();
        // 将参数以参数名的字典升序排序
        Map<String, Object> sortParams = new TreeMap<String, Object>(params);
        // 遍历排序的字典,并拼接"key=value"格式
        for (Map.Entry<String, Object> entry : sortParams.entrySet()) {
            // 过滤空参
            if (entry.getValue() == null || entry.getValue() == "")
                continue;
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        if (!sortParams.isEmpty()) {
            sb.deleteCharAt(sb.length() - 1);
        }
        logger.info("===sign data:" + sb.toString());
        return sb.toString();
    }

    /**
     * hex转byte数组
     *
     * @param hex
     * @return
     */
    public static byte[] hexToBytes(String hex) {
        int m, n;
        int byteLen = hex.length() / 2; // 每两个字符描述一个字节
        byte[] ret = new byte[byteLen];
        for (int i = 0; i < byteLen; i++) {
            m = i * 2 + 1;
            n = m + 1;
            int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
            ret[i] = Byte.valueOf((byte) intVal);
        }
        return ret;
    }

    /**
     * byte数组转hex
     *
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        String hexArray = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            int bi = b & 0xff;
            sb.append(hexArray.charAt(bi >> 4));
            sb.append(hexArray.charAt(bi & 0xf));
        }
        return sb.toString();
    }


    /**
     * 生成随机字符串
     *
     * @return
     */
    public static String createNonceStr() {
        String sl = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 16; i++) {
            sb.append(sl.charAt(new Random().nextInt(sl.length())));
        }
        return sb.toString();
    }
}
三、使用示例
public static void main(String[] args) {
        String key = "123456";
        String msg = "13052515170";
        System.out.println("【加密前】:" + msg);

        //加密
        String cipherText = SecretUtil.encryptBy3Des(DEFAULT_SYMMETRIC_KEY, msg);
        System.out.println("【加密后】:" + cipherText);

        //解密
        String msgText = SecretUtil.decodeBy3Des(DEFAULT_SYMMETRIC_KEY, cipherText);
        System.out.println("【解密后】:" + msgText);

        //签名 验签
        Map<String, String> keyPairMap = genRsaKeyPair();
        System.out.println("生成公、私钥测试:"+keyPairMap);

        String publicKey = keyPairMap.get(PUBLIC_KEY_NAME);
        String privateKey = keyPairMap.get(PRIVATE_KEY_NAME);

        System.out.println("===开始RSA公、私钥测试===");
        String str = "alpha=001&beta=002&gamma=003";
        String sign = sign(getPrivateKeyFromPKSC8(privateKey), str);

        verifySign(getPublicKeyFromPKSC8(publicKey), str, sign);

        System.out.println(privateKey);
        System.out.println(">>>>>"+SecretUtil.encryptBy3Des(key, null));

        String a = bytesToHex("123".getBytes());
        byte[] bytes = hexToBytes(a);
        System.out.println(new String(bytes));

    }
上一篇下一篇

猜你喜欢

热点阅读