RSA加密算法介绍及Java工具类

一、RSA加密算法介绍

当今重要的三类加密算法:非对称加密对称加密以及哈希算法(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、公钥用于加密、私钥用于解密,这才能起到加密作用
因为公钥是公开的,很多人可以持有公钥。若用私钥加密,那所有持有公钥的人都可以进行解密,这是不安全的!
若用公钥加密,那只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证的数据的安全性

虽然公钥和私钥都可以加解密,但是用法一般如下:
公钥加密、私钥解密、私钥签名、公钥验签。

三、Java工具类

下面介绍两种工具类:

1、公钥在客户端,私钥在服务端。公钥用于加密,私钥用于解密。

pom引包

     <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
     </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
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值