RSA加密算法工具类

1. RSA加密算法介绍

RSA加密是一种非对称加密算法,由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年首次公开提出。RSA是他们三人姓氏的首字母组成的。

RSA算法基于一个数学上的事实:将两个大质数相乘很容易,但是想要将其乘积分解成原始的质数因子却非常困难。这就是所谓的“陷门函数TDF”的概念,是RSA加密安全性的基础。

加密和签名

非对称加密算法(如RSA)正确的使用方法是:

  • 公钥加密,私钥解密。
  • 私钥签名,公钥验签。

这里想专门讲一下加密与签名的区别

  • 加密:对一段明文进加密,只有用指定的密钥才能解密,防止数据被窃取,泄漏
  • 签名:对一段明文进行签名,通过指定的密钥来验证签名,防止数据被篡改

加密很容易理解,基本上不会出现误解。

通常误解出现在对签名的理解上,有很多人把签名也理解成加密(虽然本质上仍然是加密,但签名的目的不同,技术实现也有所不同),认为只要签名了,数据就不出被泄漏了,这是很大的一个误解。

划重点:签名的作用不是防泄密,而是防篡改

如何理解防篡改?给大家举个例子:

你经常给你的女朋友写信,里面有绵绵情话,有个快递员很坏,喜欢偷拆看别人的信,看完后再放回去。有一天,你发现你给女朋友写信的内容被曝光了,你意识到肯定是有人偷看了你写的信,于是你决定:

对信件内容进行加密

你采取了一套加密算法,如明文 I love you,会被转化为密文:324678967702

你把解密的密钥给了女友,这样只有她能解密信件内容,这样快递员即使偷看了信,也不知道里面写的是啥。哈哈,你的目的达到了。

但是这个快递员真的很坏,他心怀不满,他说你不是不让我看你的信的内容吗?那么我就把你的信件给改了,比如,把 I love you 的密文:324678967702 给改成 1234567890,你女朋友收到信后,解密出 1234567890 的结果可能是:你欠我的一万块钱什么时候还。你女朋友很生气的问你,你信里都写的啥呀,莫名其妙的。你意识到,信件的内容肯定是被篡改了。你要防止别人篡改,你又有了新的想法。

对信息内容追加签名

你每次写完信,除了对信件内容进行加密外,还会用一套算法,针对信件明文生成一个签名(一般不会对明文直接签名,先会用哈希算法对明文进行摘要,然后对摘要进行加密,这个密文就叫签名),这套算法会保证:只要信件明文有任何改动,生成的签名都是不一样的。 这样就做到了防篡改吗?是的,回到故事中,你的女友收到信件其实包含两个密文,一个是明文加密后的内容,我们称之为密文 ,一个是明文摘要加密后的内容,我们称之为签名。她收到你的信后,先要进行验签操作。 即先用私钥解密密文,得到解密后的明文。那这个明文与原来的明文一致吗?他用同样的算法对收到明文做摘要,我为记为摘要 2,然后再用公钥解密签名,得到摘要 1,如果摘要 2 与摘要 1 相同,那么就说明信件明文或密文没有被篡改。如果两个摘要不同,那么她马上明白,密文不可信,被篡改过。即验签不通过。

这里用到的就是签名算法,这使得:

  1. 第一,任何人不能篡改内容,只要篡改了,签名就会不同,验签就会失败。
  2. 第二,不能伪造签名(中间人在篡改内容后,用自己私钥伪造一个签名),因为同样会验签失败。

而且用来做签名的密钥是一对非对称密钥,公私钥是成对的,用私钥生成的签名,只有用对应的公钥才能验签通过。(思考,为什么非要使用非对称密钥呢?用对称密钥签名不可以吗?)

这下任何人拿你的信件都没有办法了,即不能知道你信件的内容,也不能通过篡改信件来行骗或破坏你们的关系,从此你和女朋友过上了幸福美好的生活。

但是,故事就这么结束了吗?回到我们在前面提到的思考题,为什么非要使用非对称密钥来做签名呢?用对称密钥来做签名不可以吗?

先回答,再解释:可以,用对称密钥来做签名也是可以的,但是安全性不够,不方便传输。关键点在于上面提到的第二点,如果中间人不仅篡改内容,而且还拿到了你的签名密钥,伪造签名怎么办?

继续讲故事,假设你和女朋友用的是对称密钥对信件进行签名(签名过程是一样的,只不过用的对称密钥),你总要把这个对称密钥告诉你的女朋友吧,或者这个密钥生成时一式两份,你和女友各执行一份。这个快递员不仅很坏,而且智商很高,他又窃听了你和你女朋友的电话,或入室盗窃,总之偷走了密钥,(唉,这个快递员确实不简单,简直 TMD 就是一特工),他不仅篡改了你的信,而且也篡改了你的签名,即用篡改后的内容,再生成一个签名,替换掉你原来的签名,这样篡改后的内容摘要和签名不就对应上了吗?(真是道高一尺,魔高一丈)那么我就认怂了吗?当然不能,关键在于如何保证密钥不被泄露?我决定定期更换密钥,每次我都用不同的密钥与女友通信,但是你怎么将更新的密钥与女友同步呢?要知道这个快递员可是即坏又厉害呢!他可以窃听一切你和女友的通信噢。

解决方法就是非对称密钥,我可以每次都生成一个密钥对,但是我只传输公钥给女友,不传输私钥。女友也是一样,每次都生成一个密钥对,只传输公钥给我,私钥自己保留。这样我就可以:用女友给我的公钥加密信件内容,再用我自己的私钥对信件内容做签名,女友可以:**用自己的私钥解密信件内容,再用我的公钥对信件内容做验签,**这样即使这个坏快递员拿到了公钥,也没有什么用,他可以用公钥随意加密任何内容,发送给任何人,但因为他拿不到私钥,就无法对内容进行签名,在安全等级高的通信中,没有签名的内容是不可信的。至于非对称密钥为什么会有这种特性,涉及高等数字知识,我也说不清,有兴趣的可以自行深入研究。

至此,我们理解了:**签名与加密完全是两个概念,也不是必须一起都实现才安全,要根据需求而定。**例如,我传输了一个下单信息:买一杯奶茶,这个信息并不是什么机密,但是要防止被人篡改改成:买 2 杯可乐,所以只需要对内容做签名防篡改就可以了,并不需要加密。

为什么在使用非对称加密算法(如 RSA)时,正确的使用方法是公钥加密,私钥解密。

理解了加密和签名的区别,我们再来说说非对称加密中加密的实现为什么必须是公钥加密,私钥解密才是安全的。而签名却是私钥签名,公钥验签。

在 python 中的 rsa 加密实现中,根本就不支持公钥解密。(好多 java 小伙伴也许会说,我们在项目中私钥加密,公钥解密,用的好好的,难道说 java 没考虑到安全?从存在即合理的角度看,java 支持这么做一定是有应用场景的)。难道是 python 太 low 了?为什么不允许私钥加密呢?

私钥和公钥的关系,相当于钥匙和锁的关系。

私钥 = 钥匙,公钥 = 锁,私钥只有一把自己保存,而公钥锁可以复制很多把。

当要传输隐私数据时,就给对方一把锁,让对方把重要的隐私数据锁起来,传给你,然后你用私钥解锁。因为私钥在你手上,所以只有你能解锁。

而公钥之所以叫公钥,意思是可以公开给任何人。任何人拿到一把锁都是没有意义,所以对锁的定义就是不能打开钥匙,即不能用私钥加密,公钥解密(切记,我说的是加密场景下,不能用私钥加密,公钥解密,加签的场景正好相反,恰恰是私钥加密,公钥解密,不过我们通常会说成私钥加签,公钥验签)。

java 的小伙伴可能会这么说,我们的接口安全是这么实现的,服务端保存私钥,客户端保存公钥:

  1. 客户端请求接口时,用公钥加密,服务端收到信息用私钥解密
  2. 服务端返回的内容用私钥加密,客户端收到后,用公钥解密

这样用一对非对称密钥就可以完成整个交互的加密过程了,并不像你说的公钥可以公开给任何人,我们的公钥也是保密的,只给到指定的人或客户端。这里的第 2 步,其实是把公钥当私钥用了,来个了公私钥角色互换。也没有人说这么做不可以,反正只要保证 “私钥” 不泄漏就可以。

为了保证灵活性,所以 java 允许这么做,而 python 就要严格一点。

无论如何,我们永远要记住,私钥代表着你身份和权力,请保护好你的私钥。

说到这里,签名就好理解了,一定是私钥签名,公钥验签。毕竟私钥才能代表你的身份,你签名的文件,可以分发给任何人,也就是说任何人都需要拿到公钥来验证签名。如果反过来就不行了,任何拿到公钥的人都可以冒充你进行签名,那可是不行的。

RSA加密解密工具类

pom.xml

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.58</version>
    </dependency>
    <dependency>
        <groupId>com.zgc.cfca</groupId>
        <artifactId>SADK</artifactId>
        <version>3.5.2.1</version>
    </dependency>
    <dependency>
        <groupId>com.zgc.cfca</groupId>
        <artifactId>logback-cfca-jdk1.6</artifactId>
        <version>4.1.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15to18</artifactId>
        <version>1.68</version>
    </dependency>

    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-crypto</artifactId>
        <version>5.7.2</version>
    </dependency>

    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.1.0</version>
    </dependency>

java 代码

package com.ajc.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.*;
@Slf4j
public class RSAUtils {
	
	/**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    
    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

    /**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";
    
    /**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 245;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 256;

    public static final String PARAM_EQUAL = "=";

    public static final String PARAM_AND = "&";


    /**
     * 生成密钥对(公钥和私钥)
     * @return
     * @throws Exception
     */
    public static Map<String, Object> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * 用私钥对信息生成数字签名
     * @param body body传参内容(进行指定排序处理)
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static String signByMapSort(JSONObject body, String privateKey) throws Exception {
        String param = getMapStr(body);
        log.info("加签参数: " + param);
        // 参数加签
        String sign = getSign(param, privateKey);
        // 加签sign值
        log.info("sign值: " + sign);
        // 根据sign 解签结果
//        log.info(verifySign(body, PUBLIC_KEY, sign));
        return sign;
    }

    /**
     * 获取map字符串。以key=value&...形式返回
     *
     * @param map
     * @return
     */
    private static String getMapStr(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        map = sortMapByKey(map);
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object obj = entry.getValue();
            String key = entry.getKey();
            if (null != obj && !"".equals(obj) && !key.equals("sign")) {
                sb.append(key);
                sb.append(PARAM_EQUAL);
                if (obj instanceof Map) {
                    sb.append(PARAM_AND);
                    sb.append(getMapStr((Map<String, Object>) obj));
                } else {
                    sb.append(obj);
                }
                sb.append(PARAM_AND);
            }
        }

        String params = sb.toString();
        if (sb.toString().endsWith(PARAM_AND)) {
            params = sb.substring(0, sb.length() - 1);
        }
        return params;
    }

    /**
     * 对Object进行List<NameValuePair>转换后按key进行升序排序
     *
     * @param
     * @return
     */
    public static Map<String, Object> sortMapByKey(Map<String, Object> order) {
        if (order == null) {
            return null;
        }

        Map<String, Object> parameters = new TreeMap<String, Object>(new Comparator<String>() {
            public int compare(String obj1, String obj2) {
                return obj1.compareToIgnoreCase(obj2);
            }
        });
        parameters.putAll(order);

        return parameters;
    }

    /**
     * 用私钥对信息生成数字签名
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String getSign(String content, String privateKey) throws Exception {
        byte[] data = content.getBytes(StandardCharsets.UTF_8);
        byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return java.util.Base64.getEncoder().encodeToString(signature.sign());
    }

    private static String sortFieldString(String data) {
        if (Objects.isNull(data) || "".equals(data)) {
            return "";
        }

        if (data.startsWith("[")) {
            return data;
        }

        JSONObject jsonObject = JSONObject.parseObject(data);
        SortedMap<String, Object> map = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        for (String key : jsonObject.keySet()) {
            if ("extMap".equals(key)) {
                map.put(key, sortExtMapField(JSONObject.toJSONString(jsonObject.get(key))));
            } else {
                String value = jsonObject.getString(key);
                map.put(key, value);
            }
        }

        log.info("排序后字段内容: " + JSONObject.toJSONString(map));
        return JSONObject.toJSONString(map);
    }

    private static Object sortExtMapField(String data) {
        if (Objects.isNull(data) || "".equals(data)) {
            return "";
        }

        JSONObject jsonObject = JSONObject.parseObject(data);
        SortedMap<String, Object> map = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        for (String key : jsonObject.keySet()) {
            String value = jsonObject.getString(key);
            map.put(key, value);
        }

        log.info("extMap 排序后字段内容: " + JSONObject.toJSONString(map));
        return map;
    }

    /**
     * 校验数字签名
     * @param data 已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @param sign 数字签名
     * @return
     * @throws Exception
     * 
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = java.util.Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(java.util.Base64.getDecoder().decode(sign));
    }

    /**
     * 私钥解密
     * @param encryptedData 已加密数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
            throws Exception {
        byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        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 decryptedData;
    }

    /**
     * 公钥解密
     * @param encryptedData 已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
            throws Exception {
        byte[] keyBytes = java.util.Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicK);
        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 decryptedData;
    }

    /**
     * 公钥加密
     * @param data 源数据
     * @param publicKey 公钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey)
            throws Exception {
        byte[] keyBytes = java.util.Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        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 = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 私钥加密
     * @param data 源数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
            throws Exception {
        byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateK);
        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 = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 获取私钥
     * @param keyMap 密钥对
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return java.util.Base64.getEncoder().encodeToString(key.getEncoded());
    }

    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return java.util.Base64.getEncoder().encodeToString(key.getEncoded());
    }

//    public static Map<String, String> getRSAKeyPair() throws PKIException {
//        Map<String, String> keyMap = new HashMap<String, String>();
//        final String deviceName = JCrypto.JSOFT_LIB;
//        JCrypto.getInstance().initialize(deviceName, null);
//        final Session session = JCrypto.getInstance().openSession(deviceName);
//
//        KeyPair keypair = KeyUtil.generateKeyPair(new Mechanism(Mechanism.RSA), 2048, session);
//        PrivateKey priKey = keypair.getPrivate();
//        PublicKey pubKey = keypair.getPublic();
//
//        String publicKey = new String(cfca.sadk.util.Base64.encode(pubKey.getEncoded()));
//        keyMap.put(EncryConstants.PUBLIC_KEY, publicKey);
		 log.info("RSAPublicKeyPair: " + publicKey);
//        String privateKey = new String(cfca.sadk.util.Base64.encode(priKey.getEncoded()));
//        keyMap.put(EncryConstants.PRIVATE_KEY, privateKey);
		 log.info("RSAPrivateKeyPair: " + privateKey);
//        return keyMap;
//    }


    /**
     * 私钥加密
     * @param data 加密数据
     * @return privateKey
     * @throws Exception
     */
    public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
        byte[] encryptArr = encryptByPrivateKey(java.util.Base64.getEncoder().encode(data.getBytes("UTF-8")), privateKey);
        return java.util.Base64.getEncoder().encodeToString(encryptArr);
    }

    /**
     * 私钥解密
     * @param encryptedData 加密数据
     * @return privateKey
     * @throws Exception
     */
    public static String decryptByPrivateKey(String encryptedData, String privateKey)
            throws Exception {
        byte[] decryptArr = decryptByPrivateKey(java.util.Base64.getDecoder().decode(encryptedData), privateKey);
        return new String(java.util.Base64.getDecoder().decode(decryptArr), "UTF-8");
    }

    /**
     * 公钥加密
     * @param data 源数据
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, String publicKey)
            throws Exception {
        byte[] encryptArr = encryptByPublicKey(java.util.Base64.getEncoder().encode(data.getBytes("UTF-8")), publicKey);
        return java.util.Base64.getEncoder().encodeToString(encryptArr);
    }

    /**
     * 公钥解密
     * @param encryptedData 已加密数据
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    public static String decryptByPublicKey(String encryptedData, String publicKey)
            throws Exception {
        byte[] decryptArr = decryptByPublicKey(java.util.Base64.getDecoder().decode(encryptedData), publicKey);
        return new String(java.util.Base64.getDecoder().decode(decryptArr), "UTF-8");
    }
    
    public static void main(String[] args) throws Exception {
//        Map<String,Object> map = genKeyPair();
//        String privateKey = getPrivateKey(map);
//        String publicKey = getPublicKey(map);

//    	String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK4QzvU8gHsX0ZJoxCJKitmjJyMU0TnP0XURjaWOFSw3k1WWfS/eKE433BFLhxdG8rfrE7ql1bUETWh1RjK9PFoio/3wpLzdS7ZoboP4ITGTy4zSDeZwcCtXE/fsKTiy1wPnBOuEHPCdt2lu4yoi0kS17UvzfO5g0ardwk2LdA9/AgMBAAECgYBRRJu7t8GsttQr7SoVcIQfVKNDJ8b/nN2IMOfXMd0ExfXN8fME1E4xJrdig8bQwVk1MVYGwMJkP1v8tzRNIDj6fqKe9Ewa1SKKdT63fEMzSn0Pa43ppNjJWr3oIzciLxIxPKjjtKPh8nBAAuupq49jgfP22S6JumlIQ342yw/kMQJBAOOGSEhhjUHHfhrvpwF3H/Ugai11tEuQB7S+NlH/nwZuVdEnkG735PhptzqvZ2R2tGbU1A7ajWUoA7TbO/OGP+UCQQDD2b470q4EDbPg69b/k8z/9/l9tlsM19rINU2qbuWscHENdq2l0pz8phOhjkx2spVvT65Q/IM2CT5e2KAqa/OTAkBwId7/5SwD7jilN9U78KTMX1RU4TyhPPO/TTtiQDP0rG4Y7YHOXtf24csO3iF7rtEMGPoF9ApZf1YMTTwHsfNNAkBKcmqtstgTEmJeDUgcvsIeStS7xKW3rBWuJRTwxFbpxZQz2fkIH5ctMrQjpUPLmvbS6ScKAfKeh8T9qLq5ZW+hAkARefA/jJt1tcZpBYUCNzxX8dbNYkH5nmIaO4kfKkLkiIObltqlSvTVXsHiazCCCXk1iY+x9kRz184tmPbUBKYf";
//		String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuEM71PIB7F9GSaMQiSorZoycjFNE5z9F1EY2ljhUsN5NVln0v3ihON9wRS4cXRvK36xO6pdW1BE1odUYyvTxaIqP98KS83Uu2aG6D+CExk8uM0g3mcHArVxP37Ck4stcD5wTrhBzwnbdpbuMqItJEte1L83zuYNGq3cJNi3QPfwIDAQAB";
		//body的值jsonarray
//		String s = "[{\"needPdf\":\"1\",\"nsrsbh\":\"913201023532898821\"}]";
//		log.info("明文:" + s);
		/*String sign = RSAUtils.sign(s.getBytes(), privateKey);
		boolean b = RSAUtils.verify(s.getBytes("UTF-8"), publicKey, sign);
		log.info(b);*/

        String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKeA4ysPqkGbkbHKjM2E/n/ZMpTeqrcx9yIH/91o6x2+l6EzJnnT6eFETpJWN8Tek9rPaPKpeYG3gY4HxVhm+Syjc251wyAsiFWBxASk39qgFr+uE6XAyM0tqo/zftQbWRa/VSsJew7zfrc6jScWEqDYAZ4mjPc+QGcbolpuAfWtAgMBAAECgYBFz4/eOI8q/N2CDfsVBOLVAf700MCxzV9EjbTz4HBtWyvzAVB94fZN7pwYnVps8J8KyPrieAOuLn8OZOq452HdrbfDbX+Zly5pm9HFLouJyk7KpSLSkfqJzoZvgIofBUKltg1fmh7txTPBvo26CVXou4QJsWHvJJTvFQatyX8cgQJBAN/TOhcZ0ygrmWraa5ulXI6Act+EIAqwGdxYBUIVLwEWT6fcu9iq3xhWeKCVU9j3VaCFx1AowLPFgITfGo50m/ECQQC/lQWW2V8ZPn3fbucRgcuP1Dl2dttP43d+FUhwbWqy9eBycsbPNAYNt4Dhd2ENm31wnHZ+Z/UFvwq1+a1hM+F9AkAWKVryGJuAubhqDRBki937OhqlqPZnOIKG/6wdm+1YhTYD3+Y1kM2gIke1VrPDotG2oChY9oAGDMMp5NFDU6ZxAkBFopf2faoYVeOQrBHnBiOEcuI0Ef2jKw3K0VeULeEjjUV4tAlZVRKCN9nrmeW3+XV90hEr3wNrhEYTYN5JP39NAkEAyjM18FCWAYd1lXEEJuF5/uSqMBC2PLIOTGWzqGXpKT+ly7fIktEYLPjgWdq9zdI4mGSYa6afhsZGom5O35X95g==";
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCngOMrD6pBm5GxyozNhP5/2TKU3qq3MfciB//daOsdvpehMyZ50+nhRE6SVjfE3pPaz2jyqXmBt4GOB8VYZvkso3NudcMgLIhVgcQEpN/aoBa/rhOlwMjNLaqP837UG1kWv1UrCXsO8363Oo0nFhKg2AGeJoz3PkBnG6JabgH1rQIDAQAB";

        /*byte[] jiami =  RSAUtils.encryptByPublicKey(Base64.getEncoder().encode(s.getBytes("UTF-8")), publicKey);
        byte[] jiemi = RSAUtils.decryptByPrivateKey(jiami, privateKey);
        log.info("公钥加密,私钥解密----解密后:" + new String(Base64.getDecoder().decode(jiemi), "UTF-8"));*/


        /*byte[] jiami1 =  RSAUtils.encryptByPrivateKey(Base64.getEncoder().encode(s.getBytes("UTF-8")), privateKey);
        byte[] jiemi1 = RSAUtils.decryptByPublicKey(jiami1, publicKey);
        log.info("私钥加密,公钥解密----解密后:" + new String(Base64.getDecoder().decode(jiemi1), "UTF-8"));*/


        String s = "[{\"needPdf\":\"1\",\"nsrsbh\":\"913201023532898821\"}]";
        log.info("明文:" + s);

        byte[] jiami1 =  RSAUtils.encryptByPrivateKey(java.util.Base64.getEncoder().encode(s.getBytes("UTF-8")), privateKey);
        String str = java.util.Base64.getEncoder().encodeToString(jiami1);
        log.info(str);
        // 模拟接到请求参数进行解密
        byte[] jiemi1 = RSAUtils.decryptByPublicKey(java.util.Base64.getDecoder().decode(str), publicKey);
        log.info("私钥加密,公钥解密----解密后:" + new String(Base64.getDecoder().decode(jiemi1), "UTF-8"));
    }

}
以下是一个简单的Java RSA工具类的示例代码: ```java import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; public class RSAUtils { private static final String RSA_ALGORITHM = "RSA"; public static KeyPair generateKeyPair() throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM); keyPairGenerator.initialize(2048); return keyPairGenerator.genKeyPair(); } public static String encrypt(String plainText, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plainText.getBytes()); return Base64.encodeBase64String(encryptedBytes); } public static String decrypt(String encryptedText, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance(RSA_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] encryptedBytes = Base64.decodeBase64(encryptedText); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes); } public static PublicKey getPublicKey(byte[] publicKeyBytes) throws Exception { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); return keyFactory.generatePublic(keySpec); } public static PrivateKey getPrivateKey(byte[] privateKeyBytes) throws Exception { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); return keyFactory.generatePrivate(keySpec); } } ``` 使用示例: ```java public class Main { public static void main(String[] args) { try { // 生成密钥对 KeyPair keyPair = RSAUtils.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); // 加密 String plainText = "Hello, RSA!"; String encryptedText = RSAUtils.encrypt(plainText, publicKey); System.out.println("Encrypted Text: " + encryptedText); // 解密 String decryptedText = RSAUtils.decrypt(encryptedText, privateKey); System.out.println("Decrypted Text: " + decryptedText); } catch (Exception e) { e.printStackTrace(); } } } ``` 请注意,这只是一个简单的示例,用于演示RSA加密和解密过程。在实际应用中,您需要更加严格的错误处理和安全性措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值