这里写自定义目录标题
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 相同,那么就说明信件明文或密文没有被篡改。如果两个摘要不同,那么她马上明白,密文不可信,被篡改过。即验签不通过。
这里用到的就是签名算法,这使得:
- 第一,任何人不能篡改内容,只要篡改了,签名就会不同,验签就会失败。
- 第二,不能伪造签名(中间人在篡改内容后,用自己私钥伪造一个签名),因为同样会验签失败。
而且用来做签名的密钥是一对非对称密钥,公私钥是成对的,用私钥生成的签名,只有用对应的公钥才能验签通过。(思考,为什么非要使用非对称密钥呢?用对称密钥签名不可以吗?)
这下任何人拿你的信件都没有办法了,即不能知道你信件的内容,也不能通过篡改信件来行骗或破坏你们的关系,从此你和女朋友过上了幸福美好的生活。
但是,故事就这么结束了吗?回到我们在前面提到的思考题,为什么非要使用非对称密钥来做签名呢?用对称密钥来做签名不可以吗?
先回答,再解释:可以,用对称密钥来做签名也是可以的,但是安全性不够,不方便传输。关键点在于上面提到的第二点,如果中间人不仅篡改内容,而且还拿到了你的签名密钥,伪造签名怎么办?
继续讲故事,假设你和女朋友用的是对称密钥对信件进行签名(签名过程是一样的,只不过用的对称密钥),你总要把这个对称密钥告诉你的女朋友吧,或者这个密钥生成时一式两份,你和女友各执行一份。这个快递员不仅很坏,而且智商很高,他又窃听了你和你女朋友的电话,或入室盗窃,总之偷走了密钥,(唉,这个快递员确实不简单,简直 TMD 就是一特工),他不仅篡改了你的信,而且也篡改了你的签名,即用篡改后的内容,再生成一个签名,替换掉你原来的签名,这样篡改后的内容摘要和签名不就对应上了吗?(真是道高一尺,魔高一丈)那么我就认怂了吗?当然不能,关键在于如何保证密钥不被泄露?我决定定期更换密钥,每次我都用不同的密钥与女友通信,但是你怎么将更新的密钥与女友同步呢?要知道这个快递员可是即坏又厉害呢!他可以窃听一切你和女友的通信噢。
解决方法就是非对称密钥,我可以每次都生成一个密钥对,但是我只传输公钥给女友,不传输私钥。女友也是一样,每次都生成一个密钥对,只传输公钥给我,私钥自己保留。这样我就可以:用女友给我的公钥加密信件内容,再用我自己的私钥对信件内容做签名,女友可以:**用自己的私钥解密信件内容,再用我的公钥对信件内容做验签,**这样即使这个坏快递员拿到了公钥,也没有什么用,他可以用公钥随意加密任何内容,发送给任何人,但因为他拿不到私钥,就无法对内容进行签名,在安全等级高的通信中,没有签名的内容是不可信的。至于非对称密钥为什么会有这种特性,涉及高等数字知识,我也说不清,有兴趣的可以自行深入研究。
至此,我们理解了:**签名与加密完全是两个概念,也不是必须一起都实现才安全,要根据需求而定。**例如,我传输了一个下单信息:买一杯奶茶,这个信息并不是什么机密,但是要防止被人篡改改成:买 2 杯可乐,所以只需要对内容做签名防篡改就可以了,并不需要加密。
为什么在使用非对称加密算法(如 RSA)时,正确的使用方法是公钥加密,私钥解密。
理解了加密和签名的区别,我们再来说说非对称加密中加密的实现为什么必须是公钥加密,私钥解密才是安全的。而签名却是私钥签名,公钥验签。
在 python 中的 rsa 加密实现中,根本就不支持公钥解密。(好多 java 小伙伴也许会说,我们在项目中私钥加密,公钥解密,用的好好的,难道说 java 没考虑到安全?从存在即合理的角度看,java 支持这么做一定是有应用场景的)。难道是 python 太 low 了?为什么不允许私钥加密呢?
私钥和公钥的关系,相当于钥匙和锁的关系。
私钥 = 钥匙,公钥 = 锁,私钥只有一把自己保存,而公钥锁可以复制很多把。
当要传输隐私数据时,就给对方一把锁,让对方把重要的隐私数据锁起来,传给你,然后你用私钥解锁。因为私钥在你手上,所以只有你能解锁。
而公钥之所以叫公钥,意思是可以公开给任何人。任何人拿到一把锁都是没有意义,所以对锁的定义就是不能打开钥匙,即不能用私钥加密,公钥解密(切记,我说的是加密场景下,不能用私钥加密,公钥解密,加签的场景正好相反,恰恰是私钥加密,公钥解密,不过我们通常会说成私钥加签,公钥验签)。
java 的小伙伴可能会这么说,我们的接口安全是这么实现的,服务端保存私钥,客户端保存公钥:
- 客户端请求接口时,用公钥加密,服务端收到信息用私钥解密
- 服务端返回的内容用私钥加密,客户端收到后,用公钥解密
这样用一对非对称密钥就可以完成整个交互的加密过程了,并不像你说的公钥可以公开给任何人,我们的公钥也是保密的,只给到指定的人或客户端。这里的第 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"));
}
}