RSA加密算法工具类

这里写自定义目录标题

  • 1. RSA加密算法介绍
    • 加密和签名
      • **划重点:签名的作用不是防泄密,而是防篡改**
        • **对信件内容进行加密**
        • **对信息内容追加签名**
      • 为什么在使用非对称加密算法(如 RSA)时,正确的使用方法是公钥加密,私钥解密。
  • 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>() {@Overridepublic 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>() {@Overridepublic 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"));}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/38727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Redisson实现分布式锁详解

摘要 在分布式系统中&#xff0c;保证多个进程或线程对共享资源的互斥访问是非常重要的。本文将介绍如何使用Redisson库来实现分布式锁&#xff0c;以及它的优势和使用场景。 1. 分布式锁的基本概念 在分布式系统中&#xff0c;由于多个节点可能同时访问同一个资源&#xff…

python 的全局列表通过append到别的列表,被append的列表修改元素的值,原来列表元素也跟着改变。

问题&#xff1a; qq [[4],[8]] def test(aa):bb []bb.append(aa[0])bb[0][0] - 2 test(qq) print(qq) [[2],[8]]原因&#xff1a; append 是将存储位置赋值给列表&#xff0c;列表改变意味着原来的列表也要改变。 append() 方法用于在列表末尾添加新的对象。 语法 append(…

插值查找 python

插值查找&#xff0c;也被称为插值搜索&#xff0c;是一种在有序数组中查找某一特定元素的搜索算法。它是对二分查找的一种改进&#xff0c;通过计算元素在数组中的近似位置来减少比较次数&#xff0c;从而提高搜索效率。 原理&#xff1a; 插值查找的基本思想是&#xff0c;根…

Scala的宝藏库:探索常用的第三方库及其应用

Scala的宝藏库&#xff1a;探索常用的第三方库及其应用 Scala&#xff0c;作为一种多范式的编程语言&#xff0c;不仅拥有强大的内置功能&#xff0c;还得益于其丰富的第三方库生态系统。这些库扩展了Scala的能力&#xff0c;帮助开发者在不同领域构建高效、可维护的应用程序。…

平安养老险陕西分公司参加2024上半年省级单位驻富平帮扶团联席会

6月28日&#xff0c;平安养老险陕西分公司工会副主席武媛携驻村工作队赴富平县庄里镇永安村参加2024上半年度省级单位驻富平帮扶团联席会议。 会议由省委金融办副主任、省委金融工委委员李嘉辉及省委金融办选派挂职干部、富平县副县长席玮共同主持。 会上&#xff0c;席玮县长带…

【vue avue】初始化代码 和 增删改查

这里是目录! 一、初始化页面1. 有 avue ,js 补 option2.显隐列二、弹窗1. 新增 - 表单1.1 必填1.2 清除 rules 提示2.编辑三、启用、禁用、删除1.1 菜单左上角1.2 操作栏删除一、初始化页面 Code<template> <basic-container><avue-crud:table-loading="…

Java类的加载过程

加载&#xff08;Loading&#xff09;&#xff1a; 这是类加载过程的第一个阶段。在这个阶段&#xff0c;Java 虚拟机&#xff08;JVM&#xff09;找到并读取类的二进制数据&#xff0c;通常是 .class 文件。这些数据从文件系统、网络、zip 包、jar 文件或其他形式的二进制数据…

吴恩达机器学习 第三课 week2 推荐算法(下)

目录 01 学习目标 02 基于内容的过滤算法 03 实现“电影推荐系统” 3.1 问题描述 3.2 算法实现 04 大项目&#xff08;数据很大&#xff09;的推荐方法※ 4.1 方法原理 4.2 实施示例 05 总结 01 学习目标 &#xff08;1&#xff09;理解基于内容的过滤算法&#xff08…

嵌入式问题分析思路

BUG解决总体思路: 1.1 定位bug范围及性质 要有效解决问题&#xff0c;首先要缩小范围&#xff0c;集中关注最近的代码变化。这有助于迅速定位可能引入问题的部分&#xff0c;避免无谓的时间浪费。检查最近的代码提交记录和修改日志&#xff0c;找出可能影响现有功能的变更。然…

Java 位运算详解

位运算是一种直接在二进制位上进行操作的方式。位运算符包括按位与 (&)、按位或 (|)、按位异或 (^)、按位非 (~)、左移 (<<)、右移 (>>) 和无符号右移 (>>>)。这些操作符用于操作整型数据类型&#xff0c;如 int 和 long。 一、按位与 (&) 按位…

如果使用Outlook 2024出现问题

大家好&#xff0c;才是真的好。 很多企业使用Domino服务器当作POP/IMAP邮箱服务器来使用&#xff0c;虽然这不能发挥Domino最佳效能&#xff0c;但也不失为一种简单用法。 另一种企业则使用Domino仅作为应用app平台&#xff0c;邮箱早已迁移至O365或其他平台&#xff0c;他们…

报销又乱又慢,财务如何解决报销困局?

费用报销是企业频繁发生的业务场景&#xff0c;不同的企业在费用报销的流程、标准、制度、管理上各有不同。作为一些公司日常运作中的薄弱环节&#xff0c;费用报销环节存在着较大的内控风险&#xff0c;如&#xff1a;费用报销滞后&#xff0c;造成会计信息的失真&#xff0c;…

【YOLOv5/v7改进系列】更换损失函数为CIOU、GIOU、SIOU、DIOU、EIOU、WIOUv1/v2/v3、Focal C/G/S/D/EIOU等

一、导言 在目标检测任务中&#xff0c;损失函数的主要作用是衡量模型预测的边界框&#xff08;bounding boxes&#xff09;与真实边界框之间的匹配程度&#xff0c;并指导模型学习如何更精确地定位和分类目标。损失函数通常由两部分构成&#xff1a;分类损失&#xff08;用于…

我的世界服务器-高版本服务器-MC服务器-生存服务器-RPG服务器-幻世星辰

生存为主&#xff0c;RPG乐趣为辅&#xff0c;重视每位玩家的建议&#xff0c;一起打造心目中的服务器&#xff0c;与小伙伴一起探险我的世界&#xff01; 服务器版本: 1.18.2 ~ 1.20.4 Q群&#xff1a; 338238381 服务器官网: 星辰毛毛雨-Minecraft高版本生存服务器我的世界…

springboot是否可以代替spring

Spring Boot不能直接代替Spring&#xff0c;但它是Spring框架的一个扩展和增强&#xff0c;提供了更加便捷和高效的开发体验。以下是关于Spring Boot和Spring关系的详细解释&#xff1a; Spring框架&#xff1a; Spring是一个广泛应用的开源Java框架&#xff0c;提供了一系列模…

EDI是什么?与ERP有何关系

EDI的发展过程 电子数据交换&#xff08;Electronic Data Interchange&#xff0c;EDI&#xff09;是一种通过电子方式传输商业文件的技术。EDI的历史可以追溯到20世纪60年代&#xff0c;当时企业开始使用计算机进行数据处理。最早的EDI系统是为解决大型企业间的信息交换问题而…

nccl 04 nvidia 官方小程序

1&#xff0c;代码重新编辑 为了地毯式地检查结果的正确性&#xff0c;这里修改了代码 主要步骤为 step1: data_p指向的空间中&#xff0c;分别生成随机数&#xff1b; step2: 分别拷贝到gpu的sendbuff的显存中&#xff1b; step3: 通过nccl_all_reduce sum&#xff1b;…

上海市计算机学会竞赛平台2023年6月月赛丙组选取子段(二)

题目描述 给定一个长度为&#x1d45b;n的序列 &#x1d44e;1,&#x1d44e;2,...,&#x1d44e;&#x1d45b;a1​,a2​,...,an​ &#xff0c;请问多少种方案&#xff0c;能够从中选取一个连续段&#xff0c;使得该子段内所有元素的值都相同&#xff1f; 输入格式 输入共…

掌握 Python 中 isinstance 的正确用法

&#x1f44b; 简介 isinstance() 函数用于判断一个对象是否是一个特定类型或者在继承链中是否是特定类型的实例。它常用于确保函数接收到的参数类型是预期的。 &#x1f4d6; 正文 1 语法 isinstance(object, classinfo) object参数是要检查的对象&#xff1b;classinfo参数…