美文网首页JAVA工具类
RSA签名验签工具类

RSA签名验签工具类

作者: 爪哇驿站 | 来源:发表于2020-08-25 16:45 被阅读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));
    
        }
    

    相关文章

      网友评论

        本文标题:RSA签名验签工具类

        本文链接:https://www.haomeiwen.com/subject/ivrzjktx.html