zoukankan      html  css  js  c++  java
  • RSA & AES & HMACSHA1 工具类

    AESUtil

    import com.xxx.common.BssException;
    import com.xxx.common.constants.CommonConstants;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.GeneralSecurityException;
    
    /**
     * AES 加密工具,密钥长度为128bit
     *
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    
    public class AESUtil {
        private AESUtil() {
        }
    
        private static final String AES_ALG = "AES";
    
        /**
         * AES算法
         */
        private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding";
    
        private static final byte[] AES_IV = initIv(AES_CBC_PCK_ALG);
    
        /**
         * 加密
         *
         * @param content
         * @param encryptType
         * @param encryptKey
         * @param charset
         * @return
         * @throws BssException
         */
        public static String encryptContent(String content, String encryptType, String encryptKey,
                                            String charset) throws BssException {
    
            if (AES_ALG.equals(encryptType)) {
    
                return aesEncrypt(content, encryptKey, charset);
    
            } else {
    
                throw new BssException("当前不支持该算法类型:encrypeType=" + encryptType);
            }
    
        }
    
        /**
         * 解密
         *
         * @param content
         * @param encryptType
         * @param encryptKey
         * @param charset
         * @return
         * @throws BssException
         */
        public static String decryptContent(String content, String encryptType, String encryptKey,
                                            String charset) throws BssException {
    
            if (AES_ALG.equals(encryptType)) {
    
                return aesDecrypt(content, encryptKey, charset);
    
            } else {
    
                throw new BssException("当前不支持该算法类型:encrypeType=" + encryptType);
            }
    
        }
    
        /**
         * AES加密,编码默认为UTF-8
         *
         * @param content
         * @param aesKey
         * @return
         * @throws BssException
         */
        public static String aesEncrypt(String content, String aesKey) throws BssException {
            return aesEncrypt(content, aesKey, CommonConstants.CHARSET_UTF8);
        }
    
        /**
         * AES加密
         *
         * @param content
         * @param aesKey
         * @param charset
         * @return
         * @throws BssException
         */
        private static String aesEncrypt(String content, String aesKey, String charset)
                throws BssException {
    
            try {
                Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
    
                IvParameterSpec iv = new IvParameterSpec(AES_IV);
                cipher.init(Cipher.ENCRYPT_MODE,
                        new SecretKeySpec(Base64.decodeBase64(aesKey.getBytes()), AES_ALG), iv);
    
                byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
                return new String(Base64.encodeBase64(encryptBytes));
            } catch (Exception e) {
                throw new BssException("AES加密失败:Aescontent = " + content + "; charset = "
                        + charset, e);
            }
    
        }
    
        /**
         * AES解密,编码默认为UTF-8
         *
         * @param content
         * @param key
         * @return
         * @throws BssException
         */
        public static String aesDecrypt(String content, String key) throws BssException {
            return aesDecrypt(content, key, CommonConstants.CHARSET_UTF8);
        }
    
    
        /**
         * AES解密
         *
         * @param content
         * @param key
         * @param charset
         * @return
         * @throws BssException
         */
        private static String aesDecrypt(String content, String key, String charset)
                throws BssException {
            try {
                Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
                IvParameterSpec iv = new IvParameterSpec(initIv(AES_CBC_PCK_ALG));
                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(key.getBytes()),
                        AES_ALG), iv);
    
                byte[] cleanBytes = cipher.doFinal(Base64.decodeBase64(content.getBytes()));
                return new String(cleanBytes, charset);
            } catch (Exception e) {
                throw new BssException("AES解密失败:Aescontent = " + content + "; charset = "
                        + charset, e);
            }
        }
    
        /**
         * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节).
         *
         * @param fullAlg
         * @return
         * @throws GeneralSecurityException
         */
        private static byte[] initIv(String fullAlg) {
    
            try {
                Cipher cipher = Cipher.getInstance(fullAlg);
                int blockSize = cipher.getBlockSize();
                byte[] iv = new byte[blockSize];
                for (int i = 0; i < blockSize; ++i) {
                    iv[i] = 0;
                }
                return iv;
            } catch (Exception e) {
    
                int blockSize = 16;
                byte[] iv = new byte[blockSize];
                for (int i = 0; i < blockSize; ++i) {
                    iv[i] = 0;
                }
                return iv;
            }
        }
    
        /**
         * 生成AES密钥
         * AES分组长度固定为128bit,密钥长度只有128、192和256bit三种
         *
         * @param length 密钥的长度
         * @return
         * @throws Exception
         */
        public static String generateDesKey(int length) throws Exception {
            //实例化
            KeyGenerator kgen;
            kgen = KeyGenerator.getInstance("AES");
            //设置密钥长度
            kgen.init(length);
            //生成密钥
            SecretKey skey = kgen.generateKey();
            //返回密钥的二进制编码
            byte[] bytes = skey.getEncoded();
            // 字节数组转字符串用二进制转16进制的方式
    //        return byteToHexString(bytes);
            // 使用base64转成字符串
            return new String(Base64.encodeBase64(bytes));
        }
    
        /**
         * byte数组转化为16进制字符串
         *
         * @param bytes
         * @return
         */
        public static String byteToHexString(byte[] bytes) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < bytes.length; i++) {
                String strHex = Integer.toHexString(bytes[i]);
                if (strHex.length() > 3) {
                    sb.append(strHex.substring(6));
                } else {
                    if (strHex.length() < 2) {
                        sb.append("0" + strHex);
                    } else {
                        sb.append(strHex);
                    }
                }
            }
            return sb.toString();
        }
    
    
        public static void main(String[] args) throws Exception {
            String key = generateDesKey(128);
            String cipher = aesEncrypt("xiaominiubi", key);
            String plain = aesDecrypt(cipher, key);
    
        }
    
    }


    BssException:

    /**
     * 自定义异常类
     *
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    public class BssException extends Exception {
    
        private static final long serialVersionUID = -238091758285157331L;
    
        private String errCode;
        private String errMsg;
    
        public BssException() {
            super();
        }
    
        public BssException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public BssException(String message) {
            super(message);
        }
    
        public BssException(Throwable cause) {
            super(cause);
        }
    
        public BssException(String errCode, String errMsg) {
            super(errCode + ":" + errMsg);
            this.errCode = errCode;
            this.errMsg = errMsg;
        }
    
        public String getErrCode() {
            return this.errCode;
        }
    
        public String getErrMsg() {
            return this.errMsg;
        }
    }

    RSA:

      密钥长度为1024位的话,最大加密明文大小为117,最大解密密文大小为128
      密钥长度为2048位的话,最大加密明文大小为245,最大解密密文大小为256

      示例中的密钥长度为1024位,推荐使用2048位

    生成2048位的RSA公私钥对:

    /**
         * 生成2048位的公私钥对
         *
         * @return
         * @throws BssException
         */
        public static Map<String, String> genRSAKeyPairs() throws NoSuchAlgorithmException {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            // keySize
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
            String priKey = Base64.encodeBase64String(privateKey.getEncoded());
            String pubKey = Base64.encodeBase64String(publicKey.getEncoded());
            Map<String, String> keyMap = new HashMap<>(4);
            keyMap.put("publicKey", pubKey);
            keyMap.put("privateKey", priKey);
            return keyMap;
        }

    RSAUtil:

    import com.xxx.common.BssException;
    import com.xxx.common.SignSourceData;
    import com.xxx.common.constants.CommonConstants;
    import org.apache.commons.lang3.StringUtils;
    
    import javax.crypto.Cipher;
    import java.io.*;
    import java.math.BigInteger;
    import java.security.*;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.*;
    
    /**
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    public class RSAUtil {
        private RSAUtil(){}
        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 117;
    
        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;
    
        /**
         * 公钥加密
         *
         * @param content   待加密内容
         * @param publicKey 公钥
         * @param charset   字符集,如UTF-8, GBK, GB2312
         * @return 密文内容
         * @throws BssException
         */
        public static String rsaEncrypt(String content, String publicKey,
                                        String charset) throws BssException {
            try {
                PublicKey pubKey = getPublicKeyFromX509(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(publicKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.ENCRYPT_MODE, pubKey);
                byte[] data = StringUtils.isEmpty(charset) ? content.getBytes()
                        : content.getBytes(charset);
                int inputLen = data.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段加密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                        cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(data, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * MAX_ENCRYPT_BLOCK;
                }
                byte[] encryptedData = Base64.encodeBase64(out.toByteArray());
                out.close();
    
                return StringUtils.isEmpty(charset) ? new String(encryptedData)
                        : new String(encryptedData, charset);
            } catch (Exception e) {
                throw new BssException("EncryptContent = " + content + ",charset = " + charset,
                        e);
            }
        }
    
        /**
         * 私钥解密
         *
         * @param content    待解密内容
         * @param privateKey 私钥
         * @param charset    字符集,如UTF-8, GBK, GB2312
         * @return 明文内容
         * @throws BssException
         */
        public static String rsaDecrypt(String content, String privateKey,
                                        String charset) throws BssException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(privateKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.DECRYPT_MODE, priKey);
                byte[] encryptedData = StringUtils.isEmpty(charset)
                        ? Base64.decodeBase64(content.getBytes())
                        : Base64.decodeBase64(content.getBytes(charset));
                int inputLen = encryptedData.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段解密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                        cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * MAX_DECRYPT_BLOCK;
                }
                byte[] decryptedData = out.toByteArray();
                out.close();
    
                return StringUtils.isEmpty(charset) ? new String(decryptedData)
                        : new String(decryptedData, charset);
            } catch (Exception e) {
                throw new BssException("EncodeContent = " + content + ",charset = " + charset, e);
            }
        }
    
        /**
         * rsa内容签名
         *
         * @param content
         * @param privateKey
         * @param charset
         * @return
         * @throws BssException
         */
        public static String rsaSign(String content, String privateKey, String charset,
                                     String signType) throws BssException {
    
            if (CommonConstants.SIGN_TYPE_RSA.equals(signType)) {
    
                return rsaSign(content, privateKey, charset);
            } else if (CommonConstants.SIGN_TYPE_RSA2.equals(signType)) {
    
                return rsa256Sign(content, privateKey, charset);
            } else {
    
                throw new BssException("Sign Type is Not Support : signType=" + signType);
            }
    
        }
    
        /**
         * sha256WithRsa 加签
         *
         * @param content
         * @param privateKey
         * @param charset
         * @return
         * @throws BssException
         */
        public static String rsa256Sign(String content, String privateKey,
                                        String charset) throws BssException {
    
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(privateKey.getBytes()));
    
                Signature signature = Signature
                        .getInstance(CommonConstants.SIGN_SHA256RSA_ALGORITHMS);
    
                signature.initSign(priKey);
    
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                byte[] signed = signature.sign();
    
                return new String(Base64.encodeBase64(signed));
            } catch (Exception e) {
                throw new BssException("RSAcontent = " + content + "; charset = " + charset, e);
            }
    
        }
    
        /**
         * sha1WithRsa 加签
         *
         * @param content
         * @param privateKey
         * @param charset
         * @return
         * @throws BssException
         */
        public static String rsaSign(String content, String privateKey,
                                     String charset) throws BssException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(privateKey.getBytes()));
    
                Signature signature = Signature
                        .getInstance(CommonConstants.SIGN_ALGORITHMS);
    
                signature.initSign(priKey);
    
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                byte[] signed = signature.sign();
    
                return new String(Base64.encodeBase64(signed));
            } catch (InvalidKeySpecException ie) {
                throw new BssException("RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", ie);
            } catch (Exception e) {
                throw new BssException("RSAcontent = " + content + "; charset = " + charset, e);
            }
        }
    
        /**
         * @param sortedParams
         * @return
         */
        public static String getSignContent(Map<String, String> sortedParams) {
            StringBuilder content = new StringBuilder();
            List<String> keys = new ArrayList<String>(sortedParams.keySet());
            Collections.sort(keys);
            int index = 0;
            for (String key : keys) {
                String value = sortedParams.get(key);
                if (StringUtil.areNotEmpty(key, value)) {
                    content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
                    index++;
                }
            }
            return content.toString();
        }
    
        public static SignSourceData extractSignContent(String str, int begin) {
            if (str == null) {
                return null;
            }
    
            int beginIndex = extractBeginPosition(str, begin);
            if (beginIndex >= str.length()) {
                return null;
            }
    
            int endIndex = extractEndPosition(str, beginIndex);
            return new SignSourceData(str.substring(beginIndex, endIndex), beginIndex, endIndex);
        }
    
        private static int extractBeginPosition(String responseString, int begin) {
            int beginPosition = begin;
            //找到第一个左大括号(对应响应的是JSON对象的情况:普通调用OpenAPI响应明文)
            //或者双引号(对应响应的是JSON字符串的情况:加密调用OpenAPI响应Base64串),作为待验签内容的起点
            while (beginPosition < responseString.length()
                    && responseString.charAt(beginPosition) != '{'
                    && responseString.charAt(beginPosition) != '"') {
                ++beginPosition;
            }
            return beginPosition;
        }
    
        private static int extractEndPosition(String responseString, int beginPosition) {
            //提取明文验签内容终点
            if (responseString.charAt(beginPosition) == '{') {
                return extractJsonObjectEndPosition(responseString, beginPosition);
            }
            //提取密文验签内容终点
            else {
                return extractJsonBase64ValueEndPosition(responseString, beginPosition);
            }
        }
    
        private static int extractJsonBase64ValueEndPosition(String responseString, int beginPosition) {
            for (int index = beginPosition; index < responseString.length(); ++index) {
                //找到第2个双引号作为终点,由于中间全部是Base64编码的密文,所以不会有干扰的特殊字符
                if (responseString.charAt(index) == '"' && index != beginPosition) {
                    return index + 1;
                }
            }
            //如果没有找到第2个双引号,说明验签内容片段提取失败,直接尝试选取剩余整个响应字符串进行验签
            return responseString.length();
        }
    
        private static int extractJsonObjectEndPosition(String responseString, int beginPosition) {
            //记录当前尚未发现配对闭合的大括号
            LinkedList<String> braces = new LinkedList<String>();
            //记录当前字符是否在双引号中
            boolean inQuotes = false;
            //记录当前字符前面连续的转义字符个数
            int consecutiveEscapeCount = 0;
            //从待验签字符的起点开始遍历后续字符串,找出待验签字符串的终止点,终点即是与起点{配对的}
            for (int index = beginPosition; index < responseString.length(); ++index) {
                //提取当前字符
                char currentChar = responseString.charAt(index);
    
                //如果当前字符是"且前面有偶数个转义标记(0也是偶数)
                if (currentChar == '"' && consecutiveEscapeCount % 2 == 0) {
                    //是否在引号中的状态取反
                    inQuotes = !inQuotes;
                }
                //如果当前字符是{且不在引号中
                else if (currentChar == '{' && !inQuotes) {
                    //将该{加入未闭合括号中
                    braces.push("{");
                }
                //如果当前字符是}且不在引号中
                else if (currentChar == '}' && !inQuotes) {
                    //弹出一个未闭合括号
                    braces.pop();
                    //如果弹出后,未闭合括号为空,说明已经找到终点
                    if (braces.isEmpty()) {
                        return index + 1;
                    }
                }
    
                //如果当前字符是转义字符
                if (currentChar == '\') {
                    //连续转义字符个数+1
                    ++consecutiveEscapeCount;
                } else {
                    //连续转义字符个数置0
                    consecutiveEscapeCount = 0;
                }
            }
    
            //如果没有找到配对的闭合括号,说明验签内容片段提取失败,直接尝试选取剩余整个响应字符串进行验签
            return responseString.length();
        }
    
    
        public static String rsaSign(Map<String, String> params, String privateKey,
                                     String charset) throws BssException {
            String signContent = getSignContent(params);
    
            return rsaSign(signContent, privateKey, charset);
    
        }
    
        public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
                                                        InputStream ins) throws Exception {
            if (ins == null || StringUtils.isEmpty(algorithm)) {
                return null;
            }
    
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
    
            byte[] encodedKey = StreamUtil.readText(ins).getBytes();
    
            encodedKey = Base64.decodeBase64(encodedKey);
    
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
        }
    
        public static String getSignCheckContentV1(Map<String, String> params) {
            if (params == null) {
                return null;
            }
    
            params.remove("sign");
            params.remove("sign_type");
    
            StringBuilder content = new StringBuilder();
            List<String> keys = new ArrayList<String>(params.keySet());
            Collections.sort(keys);
    
            for (int i = 0; i < keys.size(); i++) {
                String key = keys.get(i);
                String value = params.get(key);
                content.append((i == 0 ? "" : "&") + key + "=" + value);
            }
    
            return content.toString();
        }
    
        public static String getSignCheckContentV2(Map<String, String> params) {
            if (params == null) {
                return null;
            }
    
            params.remove("sign");
    
            StringBuilder content = new StringBuilder();
            List<String> keys = new ArrayList<String>(params.keySet());
            Collections.sort(keys);
    
            for (int i = 0; i < keys.size(); i++) {
                String key = keys.get(i);
                String value = params.get(key);
                content.append(i == 0 ? "" : "&").append(key).append("=").append(value);
            }
    
            return content.toString();
        }
    
        /**
         * 如果是RSA签名,请调用此方法进行验签
         *
         * @param params    待验签的从bss接收到的参数Map
         * @param publicKey bss公钥
         * @param charset   参数内容编码集
         * @return true:验签通过;false:验签不通过
         * @throws BssException
         */
        public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
                                         String charset) throws BssException {
            String sign = params.get("sign");
            String content = getSignCheckContentV1(params);
    
            return rsaCheckContent(content, sign, publicKey, charset);
        }
    
        public static boolean rsaCertCheckV1(Map<String, String> params, String bssPublicCertPath,
                                             String charset) throws BssException {
            String publicKey = getAlipayPublicKey(bssPublicCertPath);
            return rsaCheckV1(params, publicKey, charset);
        }
    
        /**
         * 如果是RSA或RSA2签名,请调用此方法进行验签
         *
         * @param params    待验签的从bss接收到的参数Map
         * @param publicKey bss公钥
         * @param charset   参数内容编码集
         * @param signType  指定采用的签名方式,RSA或RSA2
         * @return true:验签通过;false:验签不通过
         * @throws BssException
         */
        public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
                                         String charset, String signType) throws BssException {
            String sign = params.get("sign");
            String content = getSignCheckContentV1(params);
    
            return rsaCheck(content, sign, publicKey, charset, signType);
        }
    
        public static boolean rsaCertCheckV1(Map<String, String> params, String alipayPublicCertPath,
                                             String charset, String signType) throws BssException {
            String publicKey = getAlipayPublicKey(alipayPublicCertPath);
            return rsaCheckV1(params, publicKey, charset, signType);
        }
    
        public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
                                         String charset) throws BssException {
            String sign = params.get("sign");
            String content = getSignCheckContentV2(params);
    
            return rsaCheckContent(content, sign, publicKey, charset);
        }
    
        public static boolean rsaCertCheckV2(Map<String, String> params, String alipayPublicCertPath,
                                             String charset) throws BssException {
            String publicKey = getAlipayPublicKey(alipayPublicCertPath);
            return rsaCheckV2(params, publicKey, charset);
        }
    
        public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
                                         String charset, String signType) throws BssException {
            String sign = params.get("sign");
            String content = getSignCheckContentV2(params);
    
            return rsaCheck(content, sign, publicKey, charset, signType);
        }
    
        public static boolean rsaCertCheckV2(Map<String, String> params, String alipayPublicCertPath,
                                             String charset, String signType) throws BssException {
            String publicKey = getAlipayPublicKey(alipayPublicCertPath);
    
            return rsaCheckV2(params, publicKey, charset, signType);
        }
    
        public static boolean rsaCheck(String content, String sign, String publicKey, String charset,
                                       String signType) throws BssException {
    
            if (CommonConstants.SIGN_TYPE_RSA.equals(signType)) {
    
                return rsaCheckContent(content, sign, publicKey, charset);
    
            } else if (CommonConstants.SIGN_TYPE_RSA2.equals(signType)) {
    
                return rsa256CheckContent(content, sign, publicKey, charset);
    
            } else {
    
                throw new BssException("Sign Type is Not Support : signType=" + signType);
            }
    
        }
    
        public static boolean rsaCertCheck(String content, String sign, String alipayPublicCertPath, String charset,
                                           String signType) throws BssException {
            String publicKey = getAlipayPublicKey(alipayPublicCertPath);
            return rsaCheck(content, sign, publicKey, charset, signType);
        }
    
        public static boolean rsa256CheckContent(String content, String sign, String publicKey,
                                                 String charset) throws BssException {
            try {
                PublicKey pubKey = getPublicKeyFromX509("RSA",
                        new ByteArrayInputStream(publicKey.getBytes()));
    
                Signature signature = Signature
                        .getInstance(CommonConstants.SIGN_SHA256RSA_ALGORITHMS);
    
                signature.initVerify(pubKey);
    
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                return signature.verify(Base64.decodeBase64(sign.getBytes()));
            } catch (Exception e) {
                throw new BssException(
                        "RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
            }
        }
    
        public static boolean rsaCheckContent(String content, String sign, String publicKey,
                                              String charset) throws BssException {
            try {
                PublicKey pubKey = getPublicKeyFromX509("RSA",
                        new ByteArrayInputStream(publicKey.getBytes()));
    
                Signature signature = Signature
                        .getInstance(CommonConstants.SIGN_ALGORITHMS);
    
                signature.initVerify(pubKey);
    
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                return signature.verify(Base64.decodeBase64(sign.getBytes()));
            } catch (Exception e) {
                throw new BssException(
                        "RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
            }
        }
    
        public static PublicKey getPublicKeyFromX509(String algorithm,
                                                     InputStream ins) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
    
            StringWriter writer = new StringWriter();
            StreamUtil.io(new InputStreamReader(ins), writer);
    
            byte[] encodedKey = writer.toString().getBytes();
    
            encodedKey = Base64.decodeBase64(encodedKey);
    
            return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        }
    
        /**
         * 验签并解密
         * <p>
         * <b>目前适用于公众号</b><br>
         * params参数示例:
         * <br>{
         * <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16
         * /IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD
         * /ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD
         * /s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP
         * /jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
         * <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7
         * /mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=, sign_type=RSA,
         * <br>charset=UTF-8
         * <br>}
         * </p>
         *
         * @param params
         * @param bssPublicKey bss公钥
         * @param cusPrivateKey   合作方私钥
         * @param isCheckSign     是否验签
         * @param isDecrypt       是否解密
         * @return 解密后明文,验签失败则异常抛出
         * @throws BssException
         */
        public static String checkSignAndDecrypt(Map<String, String> params, String bssPublicKey,
                                                 String cusPrivateKey, boolean isCheckSign,
                                                 boolean isDecrypt) throws BssException {
            String charset = params.get("charset");
            String bizContent = params.get("biz_content");
            if (isCheckSign) {
                if (!rsaCheckV2(params, bssPublicKey, charset)) {
                    throw new BssException("rsaCheck failure:rsaParams=" + params);
                }
            }
    
            if (isDecrypt) {
                return rsaDecrypt(bizContent, cusPrivateKey, charset);
            }
    
            return bizContent;
        }
    
        /**
         * 验签并解密
         * <p>
         * <b>目前适用于公众号</b><br>
         * params参数示例:
         * <br>{
         * <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16
         * /IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD
         * /ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD
         * /s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP
         * /jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
         * <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7
         * /mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=, sign_type=RSA,
         * <br>charset=UTF-8
         * <br>}
         * </p>
         *
         * @param params
         * @param bssPublicKey    bss公钥
         * @param cusPrivateKey   合作方私钥
         * @param isCheckSign     是否验签
         * @param isDecrypt       是否解密
         * @return 解密后明文,验签失败则异常抛出
         * @throws BssException
         */
        public static String checkSignAndDecrypt(Map<String, String> params, String bssPublicKey,
                                                 String cusPrivateKey, boolean isCheckSign,
                                                 boolean isDecrypt, String signType) throws BssException {
            String charset = params.get("charset");
            String bizContent = params.get("biz_content");
            if (isCheckSign) {
                if (!rsaCheckV2(params, bssPublicKey, charset, signType)) {
                    throw new BssException("rsaCheck failure:rsaParams=" + params);
                }
            }
    
            if (isDecrypt) {
                return rsaDecrypt(bizContent, cusPrivateKey, charset);
            }
    
            return bizContent;
        }
    
    
        /**
         * 从公钥证书中提取公钥序列号
         *
         * @param certPath 公钥证书存放路径,例如:/home/admin/cert.crt
         * @return 公钥证书序列号
         * @throws BssException
         */
        public static String getCertSN(String certPath) throws BssException {
            InputStream inputStream = null;
            try {
                inputStream = new FileInputStream(certPath);
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update((cert.getIssuerX500Principal().getName() + cert.getSerialNumber()).getBytes());
                String certSN = new BigInteger(1, md.digest()).toString(16);
                //BigInteger会把0省略掉,需补全至32位
                certSN = fillMD5(certSN);
                return certSN;
    
            } catch (NoSuchAlgorithmException e) {
                throw new BssException(e);
            } catch (IOException e) {
                throw new BssException(e);
            } catch (CertificateException e) {
                throw new BssException(e);
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    throw new BssException(e);
                }
            }
        }
    
        private static String fillMD5(String md5) {
            return md5.length() == 32 ? md5 : fillMD5("0" + md5);
        }
    
        /**
         * 从公钥证书中提取公钥
         *
         * @param alipayPublicCertPath 公钥证书存放路径,例如:/home/admin/cert.crt
         * @return 公钥
         * @throws BssException
         */
        public static String getAlipayPublicKey(String alipayPublicCertPath) throws BssException {
            InputStream inputStream = null;
            try {
                inputStream = new FileInputStream(alipayPublicCertPath);
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
                PublicKey publicKey = cert.getPublicKey();
                return Base64.encodeBase64String(publicKey.getEncoded());
            } catch (IOException e) {
                throw new BssException(e);
            } catch (CertificateException e) {
                throw new BssException(e);
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    throw new BssException(e);
                }
            }
        }
    
        //    public static String getSignatureContent(RequestParametersHolder requestHolder) {
    //        return getSignContent(getSortedMap(requestHolder));
    //    }
    //
    //    public static Map<String, String> getSortedMap(RequestParametersHolder requestHolder) {
    //        Map<String, String> sortedParams = new TreeMap<String, String>();
    //        AlipayHashMap appParams = requestHolder.getApplicationParams();
    //        if (appParams != null && appParams.size() > 0) {
    //            sortedParams.putAll(appParams);
    //        }
    //        AlipayHashMap protocalMustParams = requestHolder.getProtocalMustParams();
    //        if (protocalMustParams != null && protocalMustParams.size() > 0) {
    //            sortedParams.putAll(protocalMustParams);
    //        }
    //        AlipayHashMap protocalOptParams = requestHolder.getProtocalOptParams();
    //        if (protocalOptParams != null && protocalOptParams.size() > 0) {
    //            sortedParams.putAll(protocalOptParams);
    //        }
    //
    //        return sortedParams;
    //    }
    }

     RSAUtil简洁版:

    import com.xxx.common.BssException;
    import com.xxx.common.constants.CommonConstants;
    import org.apache.commons.lang3.StringUtils;
    
    import javax.crypto.Cipher;
    import java.io.*;
    import java.security.KeyFactory;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    
    /**
     * RSA 加解密签名工具类
     * 密钥长度为1024位的话,最大加密明文大小为117,最大解密密文大小为128
     * 密钥长度为2048位的话,最大加密明文大小为245,最大解密密文大小为256
     *
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    public class RSAUtil {
    
        private RSAUtil() {
        }
    
        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 245;
    
        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 256;
    
    
        /**
         * 公钥加密,默认字符集 UTF-8
         *
         * @param content   待加密内容
         * @param publicKey 公钥
         * @return 密文内容
         * @throws BssException
         */
        public static String rsaEncrypt(String content, String publicKey) throws BssException {
            return rsaEncrypt(content, publicKey, CommonConstants.CHARSET_UTF8);
        }
    
        /**
         * 公钥加密
         *
         * @param content   待加密内容
         * @param publicKey 公钥
         * @param charset   字符集,如UTF-8, GBK, GB2312
         * @return 密文内容
         * @throws BssException
         */
        public static String rsaEncrypt(String content, String publicKey, String charset) throws BssException {
            try {
                PublicKey pubKey = getPublicKeyFromX509(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(publicKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.ENCRYPT_MODE, pubKey);
                byte[] data = StringUtils.isEmpty(charset) ? content.getBytes()
                        : content.getBytes(charset);
                int inputLen = data.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段加密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                        cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(data, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * MAX_ENCRYPT_BLOCK;
                }
                byte[] encryptedData = Base64.encodeBase64(out.toByteArray());
                out.close();
    
                return StringUtils.isEmpty(charset) ? new String(encryptedData) : new String(encryptedData, charset);
            } catch (Exception e) {
                throw new BssException("EncryptContent = " + content + ",charset = " + charset, e);
            }
        }
    
        /**
         * 私钥解密,默认字符集 UTF-8
         *
         * @param content    待解密内容
         * @param privateKey 私钥
         * @return 明文内容
         * @throws BssException
         */
        public static String rsaDecrypt(String content, String privateKey) throws BssException {
            return rsaDecrypt(content, privateKey, CommonConstants.CHARSET_UTF8);
        }
    
        /**
         * 私钥解密
         *
         * @param content    待解密内容
         * @param privateKey 私钥
         * @param charset    字符集,如UTF-8, GBK, GB2312
         * @return 明文内容
         * @throws BssException
         */
        public static String rsaDecrypt(String content, String privateKey, String charset) throws BssException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(privateKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.DECRYPT_MODE, priKey);
                byte[] encryptedData = StringUtils.isEmpty(charset)
                        ? Base64.decodeBase64(content.getBytes())
                        : Base64.decodeBase64(content.getBytes(charset));
                int inputLen = encryptedData.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段解密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                        cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * MAX_DECRYPT_BLOCK;
                }
                byte[] decryptedData = out.toByteArray();
                out.close();
    
                return StringUtils.isEmpty(charset) ? new String(decryptedData) : new String(decryptedData, charset);
            } catch (Exception e) {
                throw new BssException("EncodeContent = " + content + ",charset = " + charset, e);
            }
        }

      /** * rsa内容签名,默认字符集为UTF-8 * * @param content * @param privateKey * @return * @throws BssException */ public static String rsaSign(String content, String privateKey, String signType) throws BssException { return rsaSign(content, privateKey, CommonConstants.CHARSET_UTF8, signType); } /** * rsa内容签名 * * @param content * @param privateKey * @param charset * @return * @throws BssException */ public static String rsaSign(String content, String privateKey, String charset, String signType) throws BssException { if (CommonConstants.SIGN_TYPE_RSA.equals(signType)) { return rsaSign(content, privateKey, charset); } else if (CommonConstants.SIGN_TYPE_RSA2.equals(signType)) { return rsa256Sign(content, privateKey, charset); } else { throw new BssException("Sign Type is Not Support : signType=" + signType); } } /** * sha256WithRsa 加签,默认字符集为UTF-8 * * @param content * @param privateKey * @return * @throws BssException */ public static String rsa256Sign(String content, String privateKey) throws BssException { return rsa256Sign(content, privateKey, CommonConstants.CHARSET_UTF8); } /** * sha256WithRsa 加签 * * @param content * @param privateKey * @param charset * @return * @throws BssException */ public static String rsa256Sign(String content, String privateKey, String charset) throws BssException { try { PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM, new ByteArrayInputStream(privateKey.getBytes())); Signature signature = Signature .getInstance(CommonConstants.SIGN_SHA256RSA_ALGORITHMS); signature.initSign(priKey); if (StringUtils.isEmpty(charset)) { signature.update(content.getBytes()); } else { signature.update(content.getBytes(charset)); } byte[] signed = signature.sign(); return new String(Base64.encodeBase64(signed)); } catch (Exception e) { throw new BssException("RSAcontent = " + content + "; charset = " + charset, e); } } /** * sha1WithRsa 加签 * * @param content * @param privateKey * @param charset * @return * @throws BssException */ public static String rsa160Sign(String content, String privateKey, String charset) throws BssException { try { PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM, new ByteArrayInputStream(privateKey.getBytes())); Signature signature = Signature.getInstance(CommonConstants.SIGN_ALGORITHMS); signature.initSign(priKey); if (StringUtils.isEmpty(charset)) { signature.update(content.getBytes()); } else { signature.update(content.getBytes(charset)); } byte[] signed = signature.sign(); return new String(Base64.encodeBase64(signed)); } catch (InvalidKeySpecException ie) { throw new BssException("RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", ie); } catch (Exception e) { throw new BssException("RSAcontent = " + content + "; charset = " + charset, e); } } /** * @param sortedParams * @return */ public static String getSignContent(Map<String, String> sortedParams) { StringBuilder content = new StringBuilder(); List<String> keys = new ArrayList<String>(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (String key : keys) { String value = sortedParams.get(key); if (StringUtil.areNotEmpty(key, value)) { content.append(index == 0 ? "" : "&").append(key).append("=").append(value); index++; } } return content.toString(); } public static String rsaSign(Map<String, String> params, String privateKey, String charset) throws BssException { String signContent = getSignContent(params); return rsaSign(signContent, privateKey, charset); } public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception { if (ins == null || StringUtils.isEmpty(algorithm)) { return null; } KeyFactory keyFactory = KeyFactory.getInstance(algorithm); byte[] encodedKey = StreamUtil.readText(ins).getBytes(); encodedKey = Base64.decodeBase64(encodedKey); return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey)); } public static String getSignCheckContentV1(Map<String, String> params) { if (params == null) { return null; } params.remove("sign"); params.remove("sign_type"); StringBuilder content = new StringBuilder(); List<String> keys = new ArrayList<String>(params.keySet()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = params.get(key); content.append((i == 0 ? "" : "&") + key + "=" + value); } return content.toString(); } public static String getSignCheckContentV2(Map<String, String> params) { if (params == null) { return null; } params.remove("sign"); StringBuilder content = new StringBuilder(); List<String> keys = new ArrayList<String>(params.keySet()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = params.get(key); content.append(i == 0 ? "" : "&").append(key).append("=").append(value); } return content.toString(); } /** * 如果是RSA签名,请调用此方法进行验签 * * @param params 待验签的从bss接收到的参数Map * @param publicKey bss公钥 * @param charset 参数内容编码集 * @return true:验签通过;false:验签不通过 * @throws BssException */ public static boolean rsaCheckV1(Map<String, String> params, String publicKey, String charset) throws BssException { String sign = params.get("sign"); String content = getSignCheckContentV1(params); return rsaCheckContent(content, sign, publicKey, charset); } /** * 如果是RSA或RSA2签名,请调用此方法进行验签 * * @param params 待验签的从bss接收到的参数Map * @param publicKey bss公钥 * @param charset 参数内容编码集 * @param signType 指定采用的签名方式,RSA或RSA2 * @return true:验签通过;false:验签不通过 * @throws BssException */ public static boolean rsaCheckV1(Map<String, String> params, String publicKey, String charset, String signType) throws BssException { String sign = params.get("sign"); String content = getSignCheckContentV1(params); return rsaCheck(content, sign, publicKey, charset, signType); } public static boolean rsaCheckV2(Map<String, String> params, String publicKey, String charset) throws BssException { String sign = params.get("sign"); String content = getSignCheckContentV2(params); return rsaCheckContent(content, sign, publicKey, charset); } public static boolean rsaCheckV2(Map<String, String> params, String publicKey, String charset, String signType) throws BssException { String sign = params.get("sign"); String content = getSignCheckContentV2(params); return rsaCheck(content, sign, publicKey, charset, signType); } public static boolean rsaCheck(String content, String sign, String publicKey, String charset, String signType) throws BssException { if (CommonConstants.SIGN_TYPE_RSA.equals(signType)) { return rsaCheckContent(content, sign, publicKey, charset); } else if (CommonConstants.SIGN_TYPE_RSA2.equals(signType)) { return rsa256CheckContent(content, sign, publicKey, charset); } else { throw new BssException("Sign Type is Not Support : signType=" + signType); } } /** * RSA2签名方式验签,默认字符集为UTF-8 * * @param content * @param sign * @param publicKey * @return * @throws BssException */ public static boolean rsa256CheckContent(String content, String sign, String publicKey) throws BssException { return rsa256CheckContent(content, sign, publicKey, CommonConstants.CHARSET_UTF8); } /** * RSA2签名方式验签 * * @param content * @param sign * @param publicKey * @param charset * @return * @throws BssException */ public static boolean rsa256CheckContent(String content, String sign, String publicKey, String charset) throws BssException { try { PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes())); Signature signature = Signature.getInstance(CommonConstants.SIGN_SHA256RSA_ALGORITHMS); signature.initVerify(pubKey); if (StringUtils.isEmpty(charset)) { signature.update(content.getBytes()); } else { signature.update(content.getBytes(charset)); } return signature.verify(Base64.decodeBase64(sign.getBytes())); } catch (Exception e) { throw new BssException( "RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e); } } public static boolean rsaCheckContent(String content, String sign, String publicKey, String charset) throws BssException { try { PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes())); Signature signature = Signature .getInstance(CommonConstants.SIGN_ALGORITHMS); signature.initVerify(pubKey); if (StringUtils.isEmpty(charset)) { signature.update(content.getBytes()); } else { signature.update(content.getBytes(charset)); } return signature.verify(Base64.decodeBase64(sign.getBytes())); } catch (Exception e) { throw new BssException( "RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e); } } public static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance(algorithm); StringWriter writer = new StringWriter(); StreamUtil.io(new InputStreamReader(ins), writer); byte[] encodedKey = writer.toString().getBytes(); encodedKey = Base64.decodeBase64(encodedKey); return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); } /** * 验签并解密 * <p> * <b>目前适用于公众号</b><br> * params参数示例: * <br>{ * <br>biz_content=xxx * <br>sign=xxx, sign_type=RSA, * <br>charset=UTF-8 * <br>} * </p> * * @param params * @param bssPublicKey bss公钥 * @param cusPrivateKey 合作方私钥 * @param isCheckSign 是否验签 * @param isDecrypt 是否解密 * @return 解密后明文,验签失败则异常抛出 * @throws BssException */ public static String checkSignAndDecrypt(Map<String, String> params, String bssPublicKey, String cusPrivateKey, boolean isCheckSign, boolean isDecrypt) throws BssException { String charset = params.get("charset"); String bizContent = params.get("biz_content"); if (isCheckSign) { if (!rsaCheckV2(params, bssPublicKey, charset)) { throw new BssException("rsaCheck failure:rsaParams=" + params); } } if (isDecrypt) { return rsaDecrypt(bizContent, cusPrivateKey, charset); } return bizContent; } /** * 验签并解密 * <p> * <b>目前适用于公众号</b><br> * params参数示例: * <br>{ * <br>biz_content=xxx * <br>sign=xxx, sign_type=RSA, * <br>charset=UTF-8 * <br>} * </p> * * @param params * @param bssPublicKey bss公钥 * @param cusPrivateKey 合作方私钥 * @param isCheckSign 是否验签 * @param isDecrypt 是否解密 * @return 解密后明文,验签失败则异常抛出 * @throws BssException */ public static String checkSignAndDecrypt(Map<String, String> params, String bssPublicKey, String cusPrivateKey, boolean isCheckSign, boolean isDecrypt, String signType) throws BssException { String charset = params.get("charset"); String bizContent = params.get("biz_content"); if (isCheckSign) { if (!rsaCheckV2(params, bssPublicKey, charset, signType)) { throw new BssException("rsaCheck failure:rsaParams=" + params); } } if (isDecrypt) { return rsaDecrypt(bizContent, cusPrivateKey, charset); } return bizContent; } /** * 从公钥证书中提取公钥 * * @param publicCertPath 公钥证书存放路径,例如:/home/admin/cert.crt * @return 公钥 * @throws BssException */ public static String getCertPublicKey(String publicCertPath) throws BssException { InputStream inputStream = null; try { inputStream = new FileInputStream(publicCertPath); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); PublicKey publicKey = cert.getPublicKey(); return Base64.encodeBase64String(publicKey.getEncoded()); } catch (IOException e) { throw new BssException(e); } catch (CertificateException e) { throw new BssException(e); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { throw new BssException(e); } } } }

     私钥加密,公钥解密(用的不多):

    /**
         * 私钥加密,最大加密明文大小117,密钥长度为1024
         * 有的时候会使用私钥进行加密,公钥解密
         * 用私钥加密,相比私钥签名的好处是:既保证不被篡改性,又能缩短字符串长度
         *
         * @param content   待加密内容
         * @param privateKey 私钥
         * @return 密文内容
         * @throws BssException
         */
        public static String rsaEncryptByPriKey1024(String content, String privateKey) throws BssException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(privateKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.ENCRYPT_MODE, priKey);
                byte[] data = content.getBytes(CommonConstants.CHARSET_UTF8);
                int inputLen = data.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段加密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > 117) {
                        cache = cipher.doFinal(data, offSet, 117);
                    } else {
                        cache = cipher.doFinal(data, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * 117;
                }
                byte[] encryptedData = Base64.encodeBase64(out.toByteArray());
                out.close();
    
                return new String(encryptedData, CommonConstants.CHARSET_UTF8);
            } catch (Exception e) {
                throw new BssException("EncryptContent = " + content + ",charset = " + CommonConstants.CHARSET_UTF8, e);
            }
        }
    
        /**
         * 公钥解密,最大解密密文大小为128,密钥长度为1024
         *
         * @param content
         * @param publicKey
         * @return
         */
        public static String rsaDecryptByPubKey1024(String content, String publicKey) throws BssException {
            String charset = CommonConstants.CHARSET_UTF8;
            try {
                PublicKey pubKey = getPublicKeyFromX509(CommonConstants.RSA_ALGORITHM,
                        new ByteArrayInputStream(publicKey.getBytes()));
                Cipher cipher = Cipher.getInstance(CommonConstants.SIGN_TYPE_RSA);
                cipher.init(Cipher.DECRYPT_MODE, pubKey);
                byte[] encryptedData = StringUtils.isEmpty(charset)
                        ? Base64.decodeBase64(content.getBytes())
                        : Base64.decodeBase64(content.getBytes(charset));
                int inputLen = encryptedData.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offSet = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段解密
                while (inputLen - offSet > 0) {
                    if (inputLen - offSet > 128) {
                        cache = cipher.doFinal(encryptedData, offSet, 128);
                    } else {
                        cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offSet = i * 128;
                }
                byte[] decryptedData = out.toByteArray();
                out.close();
    
                return StringUtils.isEmpty(charset) ? new String(decryptedData) : new String(decryptedData, charset);
            } catch (Exception e) {
                throw new BssException("EncodeContent = " + content + ",charset = " + charset, e);
            }
        }

    BASE64:JDK1.8可以使用自带的Base64

    import org.apache.commons.codec.BinaryDecoder;
    import org.apache.commons.codec.BinaryEncoder;
    import org.apache.commons.codec.DecoderException;
    import org.apache.commons.codec.EncoderException;
    
    import java.io.UnsupportedEncodingException;
    
    /**
     * Provides Base64 encoding and decoding as defined by RFC 2045
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    public class Base64 implements BinaryEncoder, BinaryDecoder {
    
        /**
         * Chunk size per RFC 2045 section 6.8.
         *
         * <p>The {@value} character limit does not count the trailing CRLF, but counts
         * all other characters, including any equal signs.</p>
         *
         * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
         */
        static final int CHUNK_SIZE = 76;
    
        /**
         * Chunk separator per RFC 2045 section 2.1.
         *
         * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
         */
        static final byte[] CHUNK_SEPARATOR = "
    ".getBytes();
    
        /**
         * The base length.
         */
        static final int BASELENGTH = 255;
    
        /**
         * Lookup length.
         */
        static final int LOOKUPLENGTH = 64;
    
        /**
         * Used to calculate the number of bits in a byte.
         */
        static final int EIGHTBIT = 8;
    
        /**
         * Used when encoding something which has fewer than 24 bits.
         */
        static final int SIXTEENBIT = 16;
    
        /**
         * Used to determine how many bits data contains.
         */
        static final int TWENTYFOURBITGROUP = 24;
    
        /**
         * Used to get the number of Quadruples.
         */
        static final int FOURBYTE = 4;
    
        /**
         * Used to test the sign of a byte.
         */
        static final int SIGN = -128;
    
        /**
         * Byte used to pad output.
         */
        static final byte PAD = (byte) '=';
    
        // Create arrays to hold the base64 characters and a
        // lookup for base64 chars
        private static byte[] base64Alphabet       = new byte[BASELENGTH];
        private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
    
        // Populating the lookup and character arrays
        static {
            for (int i = 0; i < BASELENGTH; i++) {
                base64Alphabet[i] = (byte) -1;
            }
            for (int i = 'Z'; i >= 'A'; i--) {
                base64Alphabet[i] = (byte) (i - 'A');
            }
            for (int i = 'z'; i >= 'a'; i--) {
                base64Alphabet[i] = (byte) (i - 'a' + 26);
            }
            for (int i = '9'; i >= '0'; i--) {
                base64Alphabet[i] = (byte) (i - '0' + 52);
            }
    
            base64Alphabet['+'] = 62;
            base64Alphabet['/'] = 63;
    
            for (int i = 0; i <= 25; i++) {
                lookUpBase64Alphabet[i] = (byte) ('A' + i);
            }
    
            for (int i = 26, j = 0; i <= 51; i++, j++) {
                lookUpBase64Alphabet[i] = (byte) ('a' + j);
            }
    
            for (int i = 52, j = 0; i <= 61; i++, j++) {
                lookUpBase64Alphabet[i] = (byte) ('0' + j);
            }
    
            lookUpBase64Alphabet[62] = (byte) '+';
            lookUpBase64Alphabet[63] = (byte) '/';
        }
    
        private static boolean isBase64(byte octect) {
            if (octect == PAD) {
                return true;
            } else if (base64Alphabet[octect] == -1) {
                return false;
            } else {
                return true;
            }
        }
    
        /**
         * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet.
         *
         * @param arrayOctect byte array to test
         * @return true if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; false, otherwise
         */
        public static boolean isArrayByteBase64(byte[] arrayOctect) {
    
            arrayOctect = discardWhitespace(arrayOctect);
    
            int length = arrayOctect.length;
            if (length == 0) {
                // shouldn't a 0 length array be valid base64 data?
                // return false;
                return true;
            }
            for (int i = 0; i < length; i++) {
                if (!isBase64(arrayOctect[i])) {
                    return false;
                }
            }
            return true;
        }
    
        /**
         * Encodes binary data using the base64 algorithm but does not chunk the output.
         *
         * @param binaryData binary data to encode
         * @return Base64 characters
         */
        public static byte[] encodeBase64(byte[] binaryData) {
            return encodeBase64(binaryData, false);
        }
    
        /**
         * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
         *
         * @param binaryData binary data to encode
         * @return Base64 characters chunked in 76 character blocks
         */
        public static byte[] encodeBase64Chunked(byte[] binaryData) {
            return encodeBase64(binaryData, true);
        }
    
        /**
         * Decodes an Object using the base64 algorithm.  This method is provided in order to satisfy the requirements of the Decoder interface,
         * and will throw a DecoderException if the supplied object is not of type byte[].
         *
         * @param pObject Object to decode
         * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] supplied.
         * @throws DecoderException if the parameter supplied is not of type byte[]
         */
        public Object decode(Object pObject) throws DecoderException {
            if (!(pObject instanceof byte[])) {
                throw new DecoderException("Parameter supplied to Base64 decode is not a byte[]");
            }
            return decode((byte[]) pObject);
        }
    
        /**
         * Decodes a byte[] containing containing characters in the Base64 alphabet.
         *
         * @param pArray A byte array containing Base64 character data
         * @return a byte array containing binary data
         */
        public byte[] decode(byte[] pArray) {
            return decodeBase64(pArray);
        }
    
        /**
         * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
         *
         * @param binaryData Array containing binary data to encode.
         * @param isChunked  if isChunked is true this encoder will chunk the base64 output into 76 character blocks
         * @return Base64-encoded data.
         */
        public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
            int lengthDataBits = binaryData.length * EIGHTBIT;
            int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
            int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
            byte encodedData[] = null;
            int encodedDataLength = 0;
            int nbrChunks = 0;
    
            if (fewerThan24bits != 0) {
                //data not divisible by 24 bit
                encodedDataLength = (numberTriplets + 1) * 4;
            } else {
                // 16 or 8 bit
                encodedDataLength = numberTriplets * 4;
            }
    
            // If the output is to be "chunked" into 76 character sections,
            // for compliance with RFC 2045 MIME, then it is important to
            // allow for extra length to account for the separator(s)
            if (isChunked) {
    
                nbrChunks =
                        (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
                encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
            }
    
            encodedData = new byte[encodedDataLength];
    
            byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
    
            int encodedIndex = 0;
            int dataIndex = 0;
            int i = 0;
            int nextSeparatorIndex = CHUNK_SIZE;
            int chunksSoFar = 0;
    
            //log.debug("number of triplets = " + numberTriplets);
            for (i = 0; i < numberTriplets; i++) {
                dataIndex = i * 3;
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                b3 = binaryData[dataIndex + 2];
    
                //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
    
                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);
    
                byte val1 =
                        ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 =
                        ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
                byte val3 =
                        ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
    
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                //log.debug( "val2 = " + val2 );
                //log.debug( "k4   = " + (k<<4) );
                //log.debug(  "vak  = " + (val2 | (k<<4)) );
                encodedData[encodedIndex + 1] =
                        lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex + 2] =
                        lookUpBase64Alphabet[(l << 2) | val3];
                encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
    
                encodedIndex += 4;
    
                // If we are chunking, let's put a chunk separator down.
                if (isChunked) {
                    // this assumes that CHUNK_SIZE % 4 == 0
                    if (encodedIndex == nextSeparatorIndex) {
                        System.arraycopy(
                                CHUNK_SEPARATOR,
                                0,
                                encodedData,
                                encodedIndex,
                                CHUNK_SEPARATOR.length);
                        chunksSoFar++;
                        nextSeparatorIndex =
                                (CHUNK_SIZE * (chunksSoFar + 1)) +
                                        (chunksSoFar * CHUNK_SEPARATOR.length);
                        encodedIndex += CHUNK_SEPARATOR.length;
                    }
                }
            }
    
            // form integral number of 6-bit groups
            dataIndex = i * 3;
    
            if (fewerThan24bits == EIGHTBIT) {
                b1 = binaryData[dataIndex];
                k = (byte) (b1 & 0x03);
                //log.debug("b1=" + b1);
                //log.debug("b1<<2 = " + (b1>>2) );
                byte val1 =
                        ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
                encodedData[encodedIndex + 2] = PAD;
                encodedData[encodedIndex + 3] = PAD;
            } else if (fewerThan24bits == SIXTEENBIT) {
    
                b1 = binaryData[dataIndex];
                b2 = binaryData[dataIndex + 1];
                l = (byte) (b2 & 0x0f);
                k = (byte) (b1 & 0x03);
    
                byte val1 =
                        ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
                byte val2 =
                        ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
    
                encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
                encodedData[encodedIndex + 1] =
                        lookUpBase64Alphabet[val2 | (k << 4)];
                encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
                encodedData[encodedIndex + 3] = PAD;
            }
    
            if (isChunked) {
                // we also add a separator to the end of the final chunk.
                if (chunksSoFar < nbrChunks) {
                    System.arraycopy(
                            CHUNK_SEPARATOR,
                            0,
                            encodedData,
                            encodedDataLength - CHUNK_SEPARATOR.length,
                            CHUNK_SEPARATOR.length);
                }
            }
    
            return encodedData;
        }
    
        /**
         * Decodes Base64 data into octects
         *
         * @param base64Data Byte array containing Base64 data
         * @return Array containing decoded data.
         */
        public static byte[] decodeBase64(byte[] base64Data) {
            // RFC 2045 requires that we discard ALL non-Base64 characters
            base64Data = discardNonBase64(base64Data);
    
            // handle the edge case, so we don't have to worry about it later
            if (base64Data.length == 0) {
                return new byte[0];
            }
    
            int numberQuadruple = base64Data.length / FOURBYTE;
            byte decodedData[] = null;
            byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
    
            // Throw away anything not in base64Data
    
            int encodedIndex = 0;
            int dataIndex = 0;
            {
                // this sizes the output array properly - rlw
                int lastData = base64Data.length;
                // ignore the '=' padding
                while (base64Data[lastData - 1] == PAD) {
                    if (--lastData == 0) {
                        return new byte[0];
                    }
                }
                decodedData = new byte[lastData - numberQuadruple];
            }
    
            for (int i = 0; i < numberQuadruple; i++) {
                dataIndex = i * 4;
                marker0 = base64Data[dataIndex + 2];
                marker1 = base64Data[dataIndex + 3];
    
                b1 = base64Alphabet[base64Data[dataIndex]];
                b2 = base64Alphabet[base64Data[dataIndex + 1]];
    
                if (marker0 != PAD && marker1 != PAD) {
                    //No PAD e.g 3cQl
                    b3 = base64Alphabet[marker0];
                    b4 = base64Alphabet[marker1];
    
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] =
                            (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                    decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
                } else if (marker0 == PAD) {
                    //Two PAD e.g. 3c[Pad][Pad]
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                } else if (marker1 == PAD) {
                    //One PAD e.g. 3cQ[Pad]
                    b3 = base64Alphabet[marker0];
    
                    decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                    decodedData[encodedIndex + 1] =
                            (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                }
                encodedIndex += 3;
            }
            return decodedData;
        }
    
        /**
         * Discards any whitespace from a base-64 encoded block.
         *
         * @param data The base-64 encoded data to discard the whitespace from.
         * @return The data, less whitespace (see RFC 2045).
         */
        static byte[] discardWhitespace(byte[] data) {
            byte groomedData[] = new byte[data.length];
            int bytesCopied = 0;
    
            for (int i = 0; i < data.length; i++) {
                switch (data[i]) {
                    case (byte) ' ':
                    case (byte) '
    ':
                    case (byte) '
    ':
                    case (byte) '	':
                        break;
                    default:
                        groomedData[bytesCopied++] = data[i];
                }
            }
    
            byte packedData[] = new byte[bytesCopied];
    
            System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
    
            return packedData;
        }
    
        /**
         * Discards any characters outside of the base64 alphabet, per the requirements on page 25 of RFC 2045 - "Any characters outside of the
         * base64 alphabet are to be ignored in base64 encoded data."
         *
         * @param data The base-64 encoded data to groom
         * @return The data, less non-base64 characters (see RFC 2045).
         */
        static byte[] discardNonBase64(byte[] data) {
            byte groomedData[] = new byte[data.length];
            int bytesCopied = 0;
    
            for (int i = 0; i < data.length; i++) {
                if (isBase64(data[i])) {
                    groomedData[bytesCopied++] = data[i];
                }
            }
    
            byte packedData[] = new byte[bytesCopied];
    
            System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
    
            return packedData;
        }
    
        // Implementation of the Encoder Interface
    
        /**
         * Encodes an Object using the base64 algorithm.  This method is provided in order to satisfy the requirements of the Encoder interface,
         * and will throw an EncoderException if the supplied object is not of type byte[].
         *
         * @param pObject Object to encode
         * @return An object (of type byte[]) containing the base64 encoded data which corresponds to the byte[] supplied.
         * @throws EncoderException if the parameter supplied is not of type byte[]
         */
        public Object encode(Object pObject) throws EncoderException {
            if (!(pObject instanceof byte[])) {
                throw new EncoderException(
                        "Parameter supplied to Base64 encode is not a byte[]");
            }
            return encode((byte[]) pObject);
        }
    
        /**
         * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base64 alphabet.
         *
         * @param pArray a byte array containing binary data
         * @return A byte array containing only Base64 character data
         */
        public byte[] encode(byte[] pArray) {
            return encodeBase64(pArray, false);
        }
    
        public static String encodeBase64String(byte[] input) {
            try {
                return new String(encodeBase64(input), "utf-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    
        public static byte[] decodeBase64String(String base64String) {
            try {
                return Base64.decodeBase64(base64String.getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    }

    StreamUtil:

    import java.io.*;
    
    /**
     * @author yangyongjie
     * @date 2019/10/23
     * @desc
     */
    public class StreamUtil {
        private static final int DEFAULT_BUFFER_SIZE = 8192;
    
        public static void io(InputStream in, OutputStream out) throws IOException {
            io(in, out, -1);
        }
    
        public static void io(InputStream in, OutputStream out, int bufferSize) throws IOException {
            if (bufferSize == -1) {
                bufferSize = DEFAULT_BUFFER_SIZE;
            }
    
            byte[] buffer = new byte[bufferSize];
            int amount;
    
            while ((amount = in.read(buffer)) >= 0) {
                out.write(buffer, 0, amount);
            }
        }
    
        public static void io(Reader in, Writer out) throws IOException {
            io(in, out, -1);
        }
    
        public static void io(Reader in, Writer out, int bufferSize) throws IOException {
            if (bufferSize == -1) {
                bufferSize = DEFAULT_BUFFER_SIZE >> 1;
            }
    
            char[] buffer = new char[bufferSize];
            int amount;
    
            while ((amount = in.read(buffer)) >= 0) {
                out.write(buffer, 0, amount);
            }
        }
    
        public static OutputStream synchronizedOutputStream(OutputStream out) {
            return new SynchronizedOutputStream(out);
        }
    
        public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) {
            return new SynchronizedOutputStream(out, lock);
        }
    
        public static String readText(InputStream in) throws IOException {
            return readText(in, null, -1);
        }
    
        public static String readText(InputStream in, String encoding) throws IOException {
            return readText(in, encoding, -1);
        }
    
        public static String readText(InputStream in, String encoding, int bufferSize)
                throws IOException {
            Reader reader = (encoding == null) ? new InputStreamReader(in) : new InputStreamReader(in,
                    encoding);
    
            return readText(reader, bufferSize);
        }
    
        public static String readText(Reader reader) throws IOException {
            return readText(reader, -1);
        }
    
        public static String readText(Reader reader, int bufferSize) throws IOException {
            StringWriter writer = new StringWriter();
    
            io(reader, writer, bufferSize);
            return writer.toString();
        }
    
        private static class SynchronizedOutputStream extends OutputStream {
            private OutputStream out;
            private Object lock;
    
            SynchronizedOutputStream(OutputStream out) {
                this(out, out);
            }
    
            SynchronizedOutputStream(OutputStream out, Object lock) {
                this.out = out;
                this.lock = lock;
            }
    
            public void write(int datum) throws IOException {
                synchronized (lock) {
                    out.write(datum);
                }
            }
    
            public void write(byte[] data) throws IOException {
                synchronized (lock) {
                    out.write(data);
                }
            }
    
            public void write(byte[] data, int offset, int length) throws IOException {
                synchronized (lock) {
                    out.write(data, offset, length);
                }
            }
    
            public void flush() throws IOException {
                synchronized (lock) {
                    out.flush();
                }
            }
    
            public void close() throws IOException {
                synchronized (lock) {
                    out.close();
                }
            }
        }
    }

    StringUtil:

    import java.util.UUID;
    
    /**
     * 自定义字符串工具类
     *
     * @author yangyongjie
     * @date 2019/9/24
     * @desc
     */
    public class StringUtil {
        private StringUtil() {
        }
    
        /**
         * 返回UUID
         *
         * @return
         */
        public static String getUUID() {
            return UUID.randomUUID().toString().replaceAll("-", "");
        }
    
        /**
         * 检查指定的字符串列表是否不为空。
         */
        public static boolean areNotEmpty(String... values) {
            boolean result = true;
            if (values == null || values.length == 0) {
                result = false;
            } else {
                for (String value : values) {
                    result &= !isEmpty(value);
                }
            }
            return result;
        }
    
        /**
         * 检查指定的字符串是否为空。
         * <ul>
         * <li>SysUtils.isEmpty(null) = true</li>
         * <li>SysUtils.isEmpty("") = true</li>
         * <li>SysUtils.isEmpty("   ") = true</li>
         * <li>SysUtils.isEmpty("abc") = false</li>
         * </ul>
         *
         * @param value 待检查的字符串
         * @return true/false
         */
        public static boolean isEmpty(String value) {
            int strLen;
            if (value == null || (strLen = value.length()) == 0) {
                return true;
            }
            for (int i = 0; i < strLen; i++) {
                if ((Character.isWhitespace(value.charAt(i)) == false)) {
                    return false;
                }
            }
            return true;
        }
    }

    CommonConstants:

    /**
     * 公共常量类
     *
     * @author yangyongjie
     * @date 2019/9/24
     * @desc
     */
    public class CommonConstants {
        private CommonConstants() {
        }
    
        public static final String STR_ONE = "1";
        public static final String STR_TWO = "2";
        public static final String STR_THREE = "3";
        public static final String STR_FOUR = "4";
    
        public static final int ONE = 1;
        public static final int TWO = 2;
        public static final int THREE = 3;
        public static final int FOUR = 4;
    
        public static final String SIGN_TYPE = "sign_type";
    
        /**
         * 签名类型
         */
        public static final String SIGN_TYPE_RSA = "RSA";
    
        public static final String SIGN_TYPE_RSA2 = "RSA2";
        /**
         * 签名算法
         */
    
        public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    
        public static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
    
        /**
         * 加密算法
         */
        public static final String RSA_ALGORITHM = "RSA";
    
        public static final String ENCRYPT_TYPE_AES = "AES";
    
        public static final String APP_ID = "app_id";
    
        public static final String CHARSET = "charset";
    
        /**
         * UTF-8字符集
         **/
        public static final String CHARSET_UTF8 = "UTF-8";
    
        /**
         * GBK字符集
         **/
        public static final String CHARSET_GBK = "GBK";
    
    }

    补充:

    HMAC-SHA1 加密算法工具类:

    package xxx.common.utils;
    
    import xxx.common.constants.CommonConstants;
    import org.apache.commons.lang3.StringUtils;
    
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    
    /**
     * HMAC-SHA1 加密算法工具类
     *
     * @author yangyongjie
     * @date 2019/11/6
     * @desc
     */
    public class HMACSHA1Util {
    
        private static final String HMAC_SHA_1 = "HmacSHA1";
    
        private static final String KEY = "iU5GSex1N81mzccVtns/3w==";
    
        /**
         * 生成签名
         *
         * @param message
         * @return
         * @throws Exception
         */
        public static String signature(String message) throws Exception {
            return signature(message, KEY);
        }
    
        /**
         * 签名
         *
         * @param message 签名的字符串
         * @param key     密钥
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         */
        public static String signature(String message, String key) throws Exception {
            byte[] byteMsg = message.getBytes(CommonConstants.CHARSET_UTF8);
            byte[] byteKey = key.getBytes(CommonConstants.CHARSET_UTF8);
            SecretKeySpec signKey = new SecretKeySpec(byteKey, HMAC_SHA_1);
            Mac mac = Mac.getInstance(HMAC_SHA_1);
            mac.init(signKey);
            byte[] encodeArray = mac.doFinal(byteMsg);
            return byte2HexString(encodeArray);
        }
    
        /**
         * 二进制转十六进制
         *
         * @param b
         * @return
         */
        public static String byte2HexString(byte[] b) {
            String r = "";
            for (int i = 0; i < b.length; i++) {
                String hex = Integer.toHexString(b[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                r = r + hex;
            }
            return r;
        }
    
        /**
         * 验签
         *
         * @param message
         * @param sign
         * @return
         */
        public static boolean checkSign(String message, String sign) throws Exception {
            String signature = signature(message, KEY);
            return StringUtils.equals(signature, sign);
        }
    
        public static void main(String[] args) {
            try {
                String msg = "partnerId=5514c2f0aa4a40759f9e326e3d662595&openId=xiaomifengxing&token=201911061839039096405ef79bbe444ca8efeb598c1d81f2d&code=liehuo";
                String sign = signature(msg);
                boolean pass = checkSign(msg, sign);
                System.out.println(pass);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
  • 相关阅读:
    在线学习VIM
    对三叉搜索树的理解
    Suffix Tree
    Skip list
    中文分词算法
    土豆的seo
    Gentle.NET文档(链接)
    a标签的link、visited、hover、active的顺序
    html dl dt dd标签元素语法结构与使用
    WEBZIP为什么打不开网页
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/11726450.html
Copyright © 2011-2022 走看看