当今重要的三类加密算法:非对称加密、对称加密以及哈希算法(HASH严格说不是加密算法,但由于其不可逆性,已成为加密算法中的一个重要构成部分)。
1976年以前,所有的加密方法都是同一种模式:加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法",使用相同的密钥,两次连续的对等加密运算后会恢复原始文字,也有很大的安全隐患。
1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法"。也正是因为这个算法的产生,人类终于可以实现非对称加密了:A给B发送信息
1.B要先生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
2.A获取B的公钥,然后用它对信息加密。
3.B得到加密后的信息,用私钥解密。
理论上如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的"非对称加密算法"。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是232个十进制位,也就是768个二进制位,因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全,当然量子计算机除外。
总结:
RSA加密算法是一种非对称加密算法,所谓非对称,就是指该算法加密和解密使用不同的密钥,即使用加密密钥进行加密、解密密钥进行解密。在RAS算法中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。
公钥与私钥是成对出现的;
私钥文件中包含了公钥数据,所以可以基于私钥导出公钥;
密钥越长,越难破解,所以2048位密钥比1024位密钥要更安全;
公钥和私钥都是密钥,被公开的那个就是公钥,没有被公开的那个就是私钥。
公钥和私钥都可以用于加解密操作,用公钥加密的数据只能由对应的私钥解密,反之亦然。
tips:
1、私钥用于签名、公钥用于验签
签名和加密作用不同,签名并不是为了保密,而是为了保证这个签名是由特定的某个人签名的,而不是被其它人伪造的签名,所以私钥的私有性就适合用在签名用途上。
私钥签名后,只能由对应的公钥解密,公钥又是公开的(很多人可持有),所以这些人拿着公钥来解密,解密成功后就能判断出是持有私钥的人做的签名,验证了身份合法性。
2、公钥用于加密、私钥用于解密,这才能起到加密作用
因为公钥是公开的,很多人可以持有公钥。若用私钥加密,那所有持有公钥的人都可以进行解密,这是不安全的!
若用公钥加密,那只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证的数据的安全性
虽然公钥和私钥都可以加解密,但是用法一般如下:
公钥加密、私钥解密、私钥签名、公钥验签。
下面介绍两种工具类:
1、公钥在客户端,私钥在服务端。公钥用于加密,私钥用于解密。
pom引包
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.10version>
dependency>
java工具类
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtils {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 获取密钥对
*
* @return 密钥对
*/
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
}
/**
* 获取私钥
*
* @param privateKey 私钥字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}
/**
* 获取公钥
*
* @param publicKey 公钥字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}
/**
* RSA加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().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.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return new String(Base64.encodeBase64String(encryptedData));
}
/**
* RSA解密
*
* @param data 待解密数据
* @param privateKey 私钥
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
}
/**
* 签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @return 签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
}
/**
* 验签
*
* @param srcData 原始字符串
* @param publicKey 公钥
* @param sign 签名
* @return 是否验签通过
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
public static void main(String[] args) {
try {
// 生成密钥对
KeyPair keyPair = getKeyPair();
// String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIb3B054H+Yw87yezuwaV0M+TXthoBmWtKHKer5M9u1/t/0/5ZwBDEaWnwowPyhkHWsZk7EPaL8Lgsl0h4/DUgJrH50y6ZvYmVgulxD3EDe46hywzBO62hT2wxEbARmN+8j//1xkTYXVxu7sbNV5d+4SxASe29OBqrukYys+NKuJAgMBAAECgYBh7vCDVRE4lH7YeJgHpNl7NsM8a0ukJcIuwGEuo2RuU8XrYyk2eWAx/GutFfNOWM8r/uQ3j8nfDvg5PHB9tipT9xxCnFgwOeMB2+/ofOXeicKI7UFyW1LWbEYOKe3QQmzWa3vXCn2LsVnBAHcbdHlz134wKr7VJc+t1QeU03EKgQJBAO0zmzFyDIk2iBJOxR5bRWMBmK6I7S9E364X3lEwOkK/WtTF+9H0E6tojxoGAnuLDI+K+Zf0xu5d5YARlWmlYXkCQQCRqTmQGjo9BGGpr2u0oF04yNek3G9e9ysXwQktDPmgnn4GsSrrp3mcb+Z1/2xfmW2fWwCcWiCSFwAo3YSb9KaRAkAB7dqEQ24wq33d0EAwKAPfc0LfoIN1T/UVwGHxfRfsNQwzEM0kfvyt9zK6vnPEt3PJsxKmlroLdD4KlZoGeu7ZAkAmD8cn3YKcURnIAjutrj3NycV3odZERWfwRBPGvt4311JtIzxo6ZFAjIj3CnBiJrBbdKcbM/3QzsvO4dt1+R7RAkEAgMDvRc3Um1mQqt3xoxT3VYUEh8LQxF72x+dsXrPzoggFLvCXSlA7WQJpyDqHK8x2HSXvazB82Ei1uro58sd0Hw==";
// String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG9wdOeB/mMPO8ns7sGldDPk17YaAZlrShynq+TPbtf7f9P+WcAQxGlp8KMD8oZB1rGZOxD2i/C4LJdIePw1ICax+dMumb2JlYLpcQ9xA3uOocsMwTutoU9sMRGwEZjfvI//9cZE2F1cbu7GzVeXfuEsQEntvTgaq7pGMrPjSriQIDAQAB";
System.out.println("私钥:" + privateKey);
System.out.println("公钥:" + publicKey);
// RSA加密
String data = "test";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("加密后内容:" + encryptData);
// RSA解密
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("解密后内容:" + decryptData);
// RSA签名
String sign = sign(data, getPrivateKey(privateKey));
// RSA验签
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.print("验签结果:" + result);
} catch (Exception e) {
e.printStackTrace();
System.out.print("加解密异常");
}
}
}
2、AB两个平台对接,双方相互交换公钥,自己保存私钥。
A加密:先用A的私钥加密,再用B的公钥加密;
B解密:先用B的私钥解密,再用A的公钥解密
package com.zwt.demo.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* RSA工具类
*/
public class RSAUtil {
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 获取公钥的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 获取私钥的key
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* 初始化密钥对生成器时,指定密钥大小的整数值(安全漏洞,长度至少为2048)
*/
private static final int KEY_PAIR_INIT_SIZE = 2048;
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 245;
/**
* RSA最大解密密文大小,
* RSA 位数 如果采用1024 上面最大加密和最大解密则须填写: 117 128
* RSA 位数 如果采用2048 上面最大加密和最大解密则须填写: 245 256
*/
private static final int MAX_DECRYPT_BLOCK = 256;
/**
* 生成密钥对(公钥和私钥)
*/
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(KEY_PAIR_INIT_SIZE);
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 keyMap 密钥对
* @return
*/
public static String getPrivateKey(Map<String, Object> keyMap) {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
/**
* 获取公钥
*
* @param keyMap 密钥对
* @return
*/
public static String getPublicKey(Map<String, Object> keyMap) {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
/**
* 私钥解密
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
*/
private static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(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);
return encryptData(encryptedData, cipher, MAX_DECRYPT_BLOCK);
}
/**
* 公钥解密
*
* @param encryptedData 已加密数据
* @param publicKey 公钥(BASE64编码)
*/
private static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(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);
return encryptData(encryptedData, cipher, MAX_DECRYPT_BLOCK);
}
/**
* 公钥加密
*
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
*/
private static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(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);
return encryptData(data, cipher, MAX_ENCRYPT_BLOCK);
}
/**
* 私钥加密
*
* @param data 源数据
* @param privateKey 私钥(BASE64编码)
*/
private static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(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);
return encryptData(data, cipher, MAX_ENCRYPT_BLOCK);
}
/**
* 加密数据
*
* @param data 源数据
* @param cipher Cipher
* @param maxBlock 最大加密明文、解密密文大小
*/
private static byte[] encryptData(byte[] data, Cipher cipher, int maxBlock)
throws IllegalBlockSizeException, BadPaddingException, IOException {
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxBlock) {
cache = cipher.doFinal(data, offSet, maxBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxBlock;
}
byte[] outData = out.toByteArray();
out.close();
return outData;
}
/**
* 解密方法
*
* @param encryptedData 密文
* @param privateKey 提供方私钥
* @param publicKey 调用方公钥
* @return 明文
*/
public static String decrypt(String encryptedData, String privateKey, String publicKey) throws Exception {
byte[] decryptDataBytes = Base64.decodeBase64(encryptedData);
decryptDataBytes = decryptByPrivateKey(decryptDataBytes, privateKey);
decryptDataBytes = decryptByPublicKey(decryptDataBytes, publicKey);
return new String(decryptDataBytes);
}
/**
* 加密方法
*
* @param plaintext 明文
* @param privateKey 调用方私钥
* @param publicKey 提供方公钥
* @return 密文
*/
public static String encrypt(String plaintext, String privateKey, String publicKey) throws Exception {
byte[] encrypt = encryptByPrivateKey(plaintext.getBytes(), privateKey);
encrypt = encryptByPublicKey(encrypt, publicKey);
return Base64.encodeBase64String(encrypt);
}
public static void main(String[] args) throws Exception {
// 生成钥匙对A
Map<String, Object> keyPairA = genKeyPair();
String privateKeyA = getPrivateKey(keyPairA);
String publicKeyA = getPublicKey(keyPairA);
// 生成钥匙对B
Map<String, Object> keyPairB = genKeyPair();
String privateKeyB = getPrivateKey(keyPairB);
String publicKeyB = getPublicKey(keyPairB);
// 待加密明文
String jsonStr = "{\"name\":\"Devin\",\"age\":\"20\",\"expiredTime\":\"2022-11-08 11:52:37\"}";
System.out.println("原数据:"+jsonStr);
// 加密后密文
String encryptedData = encrypt(jsonStr, privateKeyA, publicKeyB);
System.out.println("加密后:"+encryptedData);
// 解密后明文
System.out.println("解密后:"+decrypt(encryptedData, privateKeyB, publicKeyA));
}
}
运行工具类后,每次生成的密钥对是不同的,所以不要拿不同运行结果的私钥和公钥作为一对,这样加密解密是不成功的。
运行一次之后,就要保存起来,供后续使用。
下面是一对私钥和公钥的示例:
私钥:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpCu5k4rIgOW81w/eJeKtiXqX0vVq2kq24TeRiXsXsbqeA0Y4rDmhFPtYIhzX8m1HypQ/UB4Yu8+nQFx3c6EHeSpmbVn+1nL8TVFB2f6/VC+Qf7Y2A0gmedac03nKGdEJPVawndhyt5a1U5hsoBzzKtcpb+qx8lU46BRdIKmdQ2v3ETClPcm7NQfU5IeWBGpEVaWUNoEs/GgY/hXmke0W6jbuNy1Sxsb/UFO+9dOlKy4/0jvwwpQu/AAw77nu3kVw6+3P5t0/POCfxC2R9q/URolByo46z6L2AblkBfaIL3ny8ke9ys9jBvNIvLhLjbO/GDwpCruI1P+zCOQPmlaC1AgMBAAECggEAK65mce1eiBMvWJ5eDcj/yHiau8ZedYUrnM+L75t725+wawo7iYa8jQAywJtn6PGd2GyszWZwVxuyVJJUpiviMXXngYt1jtGFUpJcBHL0VcIv3cw934bm82qFnZTJ1VKfe+6wgLX1rT4Hb0PSyqIsJFmbg+8fuUW/pCCCpqRGdE7mtAZpBEkAHD2VJJ8+BQ/9JVQXzu8MjRpQ5zUKCP60hzLJAqeNeP5pKV0XmGma7GP3ZqtC9op3M7/NZfShF2/vQRm3PJxWVQAnTz46NTwzWXk4/tAJvZNaLAhRZ70rwbaoc0ogxFcy6A6OQVJXiPReM3qJyuze0t5AsilTh39LAQKBgQDfHREesEyurwfreVsL5ULSsqlSa1oCW7p58RPqRAewgwVvEyMnFZ2WzhBigNXiLTMkNzoB2l7pmxZ26KCqjyMyaVzu9FuS5ZWnMySr6mwRjZqyckRCZv4wn7SOURnfYzwtzkAOTtbE7vJONnXlLtZ79eeYpMtN1Tn/Fgj95Ar4QQKBgQDB9ZAxWuVJhkdw04dCg3WiN/tT7/InRDo5nE9ob5Jxb/VBlqjXZC3i6oBu3CD3F5DGZkPqsbz4EUYIyjIfZotMOUY7wsasfaod8tydxDTE6NV34HXndptAl/JpeSE1ozNs6HIjMVFhiLpOR3fQapAleyhBifSLUv3RP0HCjA9rdQKBgEvvV6FLPX4Cgj6JWgxtZdXSCsDLWqIM2CWigDWuG7Pek93e9Irb13u4/GiaErFc0tgTl8GDsePt7bJgsDX8a20/4OpO7k/Lpah3RpbgPRGoUStEqqiy5vZjlI8PWS/nVVb9qF12RbBW5s7pyCxNSaB86+rOw4bk+E0yEbNfhsBBAoGAAyDTx4gAxLPOuSogN1lpb0lZ21u2Wx3FlqJHwZZzFTNKEFm+tWKfPtarZZ5VRcbyhdCmbcWaF6InsAKa1ljQDFWsJVCZ5bRNJxiAqGa+tyJONxW+sRH/pQYOWdcjSvsr3CjPlnO4LUuIPbT3YLwnQQOAfbYc5JZdE5/ijqG1qfUCgYEAmcVfSSs8VLvXiDTwVLWpMyR+bA7CVbCnUvp1natj80ZYY6lavllUXzlZxOdUr1b68r5OZaH0XQh5Xyo2q/lAByOpP5Gpge7V3XYMdTGvnU1DqIF+Uc0748S9bf6nO/hnJlSI/ABgI/cfj0FYJxFIWmmxTOIEWyCWepPYOAg0GDM=
公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQruZOKyIDlvNcP3iXirYl6l9L1atpKtuE3kYl7F7G6ngNGOKw5oRT7WCIc1/JtR8qUP1AeGLvPp0Bcd3OhB3kqZm1Z/tZy/E1RQdn+v1QvkH+2NgNIJnnWnNN5yhnRCT1WsJ3YcreWtVOYbKAc8yrXKW/qsfJVOOgUXSCpnUNr9xEwpT3JuzUH1OSHlgRqRFWllDaBLPxoGP4V5pHtFuo27jctUsbG/1BTvvXTpSsuP9I78MKULvwAMO+57t5FcOvtz+bdPzzgn8Qtkfav1EaJQcqOOs+i9gG5ZAX2iC958vJHvcrPYwbzSLy4S42zvxg8KQq7iNT/swjkD5pWgtQIDAQAB