淘先锋技术网

首页 1 2 3 4 5 6 7

一. RSA加密算法的介绍

RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

1973年,在英国政府通讯总部工作的数学家克利福德·柯克斯(Clifford Cocks)在一个内部文件中提出了一个与之等效的算法,但该算法被列入机密,直到1997年才得到公开。

对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到当前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。

1983年9月12日麻省理工学院在美国为RSA算法申请了专利。这个专利2000年9月21日失效。[4]由于该算法在申请专利前就已经被发表了,在世界上大多数其它地区这个专利权不被承认。

二. RSA加密算法的在项目中使用背景

在项目的登录模块中, 需要输入用户名和密码,即使是post请求,传递的用户名和密码通过浏览器的开发者工具, 一样可以明文显示, 如下图所示. 这样明文传递是极其不安全的.
在这里插入图片描述

因此决定采用RSA加密算法, 对传递的数据进行加密.
具体的思路如下
1、后端传递公钥给前端
2、前端把密码用公钥进行加密传递到后端
3、后台接收前端传递加密的密码,用私钥进行解密

三. RSA公钥和私钥的生成

3.1 生成私钥
在Linux系统中, 可以直接通过命令,进行公钥和私钥的生成
输入如下的命令,进行私钥的生成
openssl genrsa -out rsa_private.pem 1024
如下图所示, 执行完上面的命令后,生成了rsa_private.pem文件, 用cat命令查看该文件,即可查看到私钥的内容
在这里插入图片描述
如下图所示为私钥的内容
在这里插入图片描述

私钥整体的内容如下

MIICXQIBAAKBgQC3y5OIKGTa7+FpNklLVn3XB55qc8MQjh1R/MlJ3Uab29Tuufk8
Y3TfS4RVC9E8wxyC2l3XEyE6Xo2Kv5xAOdPlFXWloUJjA80QKJp8imhnNtxYNSql
lWfQJEZhNIejE5INhsuEmwALJZp3oG/rxqpWrVsZzPzOuMhLvKWBnD2kxQIDAQAB
AoGBALeF76rlqs9y+AG20zkHBGDSmrxxGzZMsbpMUDIRYY//0n8N9HD4XpsZLOo/
Ao9JxA5lPY6k62j9QRhqe/slww4pvBIbfDS/IbmLrf09sr+PJYbtgQOXURDMw1fJ
PkKpmq2B5T4Cr8MGDgA+/F8PCldEFdI7LgjB5pTckTH7qAOBAkEA7DEHahlaWtty
kynsvHWo1gQy54lnAZSZ3/iR1v4xCbaRriV5yt5x6RYC8tx84jDteTligaKJNej7
2HxHKSBWywJBAMc1nL8NriusKt0D3h+hYpyJcbdA6VuJcn0O8z5nuXzJPeTX3Zc+
flyfeIIGe/35kvVdFz5VH6S8rCOa9ozM8K8CQQCcjiMMAKITd0IKqc9xW8v9j+rt
7fWI5qbX/jss9nAqsAkAFXcVMTzv8tchg2SDyUqe/5p7svCf+z5z0GyapgThAkAy
/XcUtCS7ywLhtaa6g+2g0dGIrZXNt13VwujiNVyWI1Czbcmrd/SSMsN+zLgaJzLF
mUFk1BcYbK7HIlgvbBnDAkB6GlmYZgrbRMJG+eXa4hYNY8zoAzhmxL40xbhS0ikM
8Rzp6Oq9DaVaiAEIiFlmnopR+8p4KJAQYqrzTfTYrOzO

3.2 生成公钥
生成公钥文件 需要在私钥的基础上生成.
执行如下的命令
openssl rsa -in rsa_private.pem -pubout -out rsa_public_key.pem
如下图所示, 执行完命令后, 生成了rsa_public_key.pem文件
在这里插入图片描述

通过cat命令, 查看公钥的内容如下.

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3y5OIKGTa7+FpNklLVn3XB55q
c8MQjh1R/MlJ3Uab29Tuufk8Y3TfS4RVC9E8wxyC2l3XEyE6Xo2Kv5xAOdPlFXWl
oUJjA80QKJp8imhnNtxYNSqllWfQJEZhNIejE5INhsuEmwALJZp3oG/rxqpWrVsZ
zPzOuMhLvKWBnD2kxQIDAQAB

四. 前端用公钥进行加密

在前端加入jsencrypt.js,该js是用于执行OpenSSL RSA加密,解密和密钥生成的Javascript库.
该js库的GitHub地址如下https://github.com/travist/jsencrypt

在前端页面中,用input的隐藏域, 存储公钥
<input id=“pubkey” type=“hidden” value="${publicKey}" /
在html的登录表单中, 把用户输入的密码的值, 进行加密, 然后,传递到隐藏域的input中, 此隐藏的input, 有name值设置为了password, 即最终传递的参数为隐藏域的input框中加密后的密码的值.

 <!-- 用户输入的密码 -->
<input type="password" id="password" class="form-control" placeholder="密码" required="">
<!-- 加密后的密码,用于登录 -->
<input type="hidden" name="password" id="pass" class="form-control">

进行密码加密的js如下

<script>
// 密码加密
function verify() {
    var encrypt = new JSEncrypt();
    
    encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + $('#pubkey').val() + '-----END PUBLIC KEY-----');
    var encrypted = encrypt.encrypt($('#password').val());

    $('#pass').val(encrypted);
}
</script>

五. 后端用私钥进行解密

后端使用的是SpringBoot项目,JDK采用1.8
在后端java中, 首先要引入了如下的依赖,用于RSA的加密,解密

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-ext-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

在application.yml中配置私钥和公钥

在代码中, 采用如下的RSAUtil 工具类,进行加密解密的操作.

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtil {

    // 签名算法
    public static final String SHA1_WITH_RSA = "SHA1withRSA";
    public static final String MD5_WITH_RSA = "MD5withRSA";

    private static final Provider pro = new BouncyCastleProvider();

    // 统一以16进制解析modulus和exponent字符串
    private static final int BIGINTEGER_RADIX = 16;
    // RSA算法
    private static final String ALGORITHM = "RSA";
    // Padding
    private static final String NONE_PADDING = "RSA/None/PKCS1Padding";
    // 随机数算法
    private static final String RANDOM_ALGORITHM = "SHA1PRNG";
    // 编码默认格式
    private static final String UTF8 = "UTF-8";
    // 种子,改变后,生成的密钥对会发生变化
    private static final String SEEDKEY = "seedKey";
    // 密钥默认长度
    private static final int KEYSIZE = 1024;

    // 公钥PEM头部
    private static final String PUBLIC_KEY_PEM_HEADER_PKCS1 = "RSA PUBLIC KEY";
    private static final String PUBLIC_KEY_PEM_HEADER_PKCS8 = "PUBLIC KEY";
    // 私钥PEM头部
    private static final String PRIVATE_KEY_PEM_HEADER_PKCS1 = "RSA PRIVATE KEY";
    private static final String PRIVATE_KEY_PEM_HEADER_PKCS8 = "PRIVATE KEY";
    
    /**
     * 生成公私钥对
     *
     * @return
     * @throws Exception
     */
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        return generateKeyPair(KEYSIZE);
    }

    /**
     * 生成公私钥对
     *
     * @param keySize 密钥长度
     * @return
     * @throws Exception
     */
    public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM, pro);
        kpg.initialize(keySize);
        KeyPair kp = kpg.generateKeyPair();
        return kp;
    }

    /**
     * 生成公私钥对,使用特定种子生成
     *
     * @param seedKey 种子,当种子相同时,生成的密钥相同
     * @return
     * @throws Exception
     */
    public static KeyPair generateKeyPair(String seedKey) throws NoSuchAlgorithmException {
        return generateKeyPair(seedKey, KEYSIZE);
    }

    /**
     * 生成公私钥对,使用特定种子生成
     *
     * @param seedKey 种子,当种子相同时,生成的密钥相同
     * @param keySize 密钥长度
     * @return
     * @throws Exception
     */
    public static KeyPair generateKeyPair(String seedKey, int keySize) throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM, pro);
        // windows和linux下SecureRandom的行为不一致
        // 如果使用new SecureRandom(seedKey.getBytes()),在windows会生成相同密钥,在linux会生成不同密钥
        // 因此使用如下方法,确保在相同seedKey下,windows和linux都能生成相同密钥
        byte seedKeyBytes[] = seedKey.getBytes();
        SecureRandom secureRandom = SecureRandom.getInstance(RANDOM_ALGORITHM);
        secureRandom.setSeed(seedKeyBytes);
        // SecureRandom secureRandom = new SecureRandom(seedKey.getBytes());
        kpg.initialize(keySize, secureRandom);
        KeyPair kp = kpg.generateKeyPair();
        return kp;
    }

    /**
     * bytes转公钥
     *
     * @param bytes
     * @return
     * @throws InvalidKeySpecException
     */
    private static PublicKey bytesToPublicKey(byte[] bytes) throws InvalidKeySpecException {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance(ALGORITHM, pro);
            return kf.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            // Can't happen
        }
        return null;
    }

    /**
     * bytes转私钥
     *
     * @param bytes
     * @return
     * @throws InvalidKeySpecException
     */
    private static PrivateKey bytesToPrivateKey(byte[] bytes) throws InvalidKeySpecException {
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance(ALGORITHM, pro);
            return kf.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            // Can't happen
        }
        return null;
    }

    /**
     * String转公钥
     *
     * @param key
     * @return
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicRSAKey(String key) throws InvalidKeySpecException {
        return bytesToPublicKey(Base64.decode(key));
    }

    /**
     * String转私钥
     *
     * @param key
     * @return
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateRSAKey(String key) throws InvalidKeySpecException {
        return bytesToPrivateKey(Base64.decode(key));
    }

    /**
     * 公私钥转String格式
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String toBase64(Key key) {
        byte[] bytes = key.getEncoded();
        return Base64.toBase64String(bytes);
    }

    /**
     * String转bytes
     *
     * @param text
     * @return
     * @throws Exception
     */
    public static byte[] toBytes(String text) throws UnsupportedEncodingException {
        return toBytes(text, UTF8);
    }

    /**
     * String转bytes
     *
     * @param text
     * @param charSet 编码
     * @return
     * @throws Exception
     */
    public static byte[] toBytes(String text, String charSet) throws UnsupportedEncodingException {
        return text.getBytes(charSet);
    }

    /**
     * 使用密钥加密bytes,返回bytes
     *
     * @param text
     * @param key  密钥(公钥/私钥)
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] text, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance(NONE_PADDING, pro);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(text);
    }

    /**
     * 使用密钥加密String,返回bytes
     *
     * @param text
     * @param key  密钥(公钥/私钥)
     * @return
     * @throws Exception
     */
    private static byte[] encryptToBytes(String text, Key key) throws UnsupportedEncodingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        return encrypt(toBytes(text), key);
    }


    /**
     * 使用密钥加密String,返回String
     *
     * @param text
     * @param key  密钥(公钥/私钥)
     * @return
     * @throws Exception
     */
    public static String encryptToString(String text, Key key) throws BadPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        byte[] en = encryptToBytes(text, key);
        return Base64.toBase64String(en);
    }

    /**
     * 使用密钥解密bytes,返回bytes
     *
     * @param text
     * @param key  密钥(公钥/私钥)
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] text, Key key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance(NONE_PADDING, pro);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(text);
    }

    /**
     * 使用密钥解密bytes,返回String
     *
     * @param text
     * @param key  密钥(公钥/私钥)
     * @return
     * @throws Exception
     */
    private static String decryptToString(byte[] text, Key key) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
        return new String(decrypt(text, key));
    }

    /**
     * 使用密钥解密String,返回String
     *
     * @param text
     * @param key  私钥
     * @return
     * @throws Exception
     */
    public static String decryptToString(String text, Key key) throws InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, NoSuchPaddingException {
        byte[] en = Base64.decode(text);
        return decryptToString(en, key);
    }

    /**
     * 将Pem从String格式转为bytes
     *
     * @param keyPem
     * @return
     * @throws InvalidKeySpecException
     */
    private static byte[] getBytesFromPem(String keyPem) throws InvalidKeySpecException {
        try {
            StringReader stringReader = new StringReader(keyPem);
            PemReader pemReader = new PemReader(stringReader);
            PemObject pemObject = pemReader.readPemObject();
            pemReader.close();
            return pemObject.getContent();
        } catch (IOException e) {
            throw new InvalidKeySpecException("Could not get key pem");
        }
    }

    /**
     * 从Pem中解析公钥
     *
     * @param keyPem
     * @return
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicRSAKeyFromPem(String keyPem) throws InvalidKeySpecException {
        return bytesToPublicKey(getBytesFromPem(keyPem));
    }

    /**
     * 从Pem中解析私钥
     *
     * @param keyPem
     * @return
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateRSAKeyFromPem(String keyPem) throws InvalidKeySpecException {
        return bytesToPrivateKey(getBytesFromPem(keyPem));
    }

    /**
     * 获取Pem格式的RSAKey
     *
     * @param type
     * @param keyBytes
     * @return
     * @throws InvalidKeySpecException
     */
    private static String generateKeyPem(String type, byte[] keyBytes) throws InvalidKeySpecException {
        try {
            StringWriter stringWriter = new StringWriter();
            PemWriter pemWriter = new PemWriter(stringWriter);
            pemWriter.writeObject(new PemObject(type, keyBytes));
            pemWriter.close();
            String keyPem = stringWriter.toString();
            stringWriter.close();
            return keyPem;
        } catch (IOException e) {
            throw new InvalidKeySpecException("Could not generate key pem");
        }
    }

    /**
     * 获取Pem格式的RSAKey
     *
     * @param type
     * @param key
     * @return
     * @throws InvalidKeySpecException
     */
    private static String generateKeyPem(String type, Key key) throws InvalidKeySpecException {
        return generateKeyPem(type, key.getEncoded());
    }

    /**
     * 获取Pem格式的公钥
     *
     * @param publicKey
     * @return
     * @throws InvalidKeySpecException
     */
    public static String generateKeyPemPKCS8(PublicKey publicKey) throws InvalidKeySpecException {
        return generateKeyPem(PUBLIC_KEY_PEM_HEADER_PKCS8, publicKey);
    }

    /**
     * 获取Pem格式的私钥
     *
     * @param privateKey
     * @return
     * @throws InvalidKeySpecException
     */
    public static String generateKeyPemPKCS8(PrivateKey privateKey) throws InvalidKeySpecException {
        return generateKeyPem(PRIVATE_KEY_PEM_HEADER_PKCS8, privateKey);
    }

    /**
     * PKCS#8转换为PKCS#1
     *
     * @param privateKey
     * @throws IOException
     */
    public static String generateKeyPemPKCS1(PrivateKey privateKey) throws IOException, InvalidKeySpecException {
        byte[] privBytes = privateKey.getEncoded();
        PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
        ASN1Encodable encodable = pkInfo.parsePrivateKey();
        ASN1Primitive primitive = encodable.toASN1Primitive();
        byte[] privateKeyPKCS1 = primitive.getEncoded();
        return generateKeyPem(PRIVATE_KEY_PEM_HEADER_PKCS1, privateKeyPKCS1);
    }

    /**
     * X509转换为PKCS#1
     *
     * @param publicKey
     * @throws IOException
     */
    public static String generateKeyPemPKCS1(PublicKey publicKey) throws IOException, InvalidKeySpecException {
        byte[] pubBytes = publicKey.getEncoded();

        SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
        ASN1Primitive primitive = spkInfo.parsePublicKey();
        byte[] publicKeyPKCS1 = primitive.getEncoded();
        return generateKeyPem(PUBLIC_KEY_PEM_HEADER_PKCS1, publicKeyPKCS1);
    }

    /**
     * 签名,使用SHA1摘要
     *
     * @param data
     * @param privateKey
     * @return
     * @throws SignatureException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     */
    public static String sign(String data, PrivateKey privateKey) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        return sign(data, privateKey, SHA1_WITH_RSA);
    }

    /**
     * 验签,使用SHA1摘要
     *
     * @param data
     * @param sign
     * @param publicKey
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    public static boolean verify(String data, String sign, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
        return verify(data, sign, publicKey, SHA1_WITH_RSA);
    }

    /**
     * 签名
     *
     * @param data
     * @param privateKey
     * @param algorithm  指定摘要算法
     * @return
     * @throws SignatureException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     */
    public static String sign(String data, PrivateKey privateKey, String algorithm) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        // 设置签名算法
        Signature signature = Signature.getInstance(algorithm);
        // 设置签名加密方式
        signature.initSign(privateKey);//设置私钥
        // 签名和加密一样 要以字节形式 utf-8字符集得到字节
        signature.update(toBytes(data));
        // 得到base64编码的签名后的字段
        return Base64.toBase64String(signature.sign());
    }

    /**
     * 验签
     *
     * @param data
     * @param sign
     * @param publicKey
     * @param algorithm 指定摘要算法
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    public static boolean verify(String data, String sign, PublicKey publicKey, String algorithm) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
        // 指定签名类型
        Signature signature = Signature.getInstance(algorithm);
        // 放入公钥
        signature.initVerify(publicKey);
        // 放入数据
        signature.update(toBytes(data));
        // 验签结果
        return signature.verify(Base64.decode(sign));
    }
}

在业务代码在中, 可以使用@Value注解,把配置文件中的公钥和私钥进行注入到代码中

   /**
     * rsa 加密的公钥
     */
    @Value("${rsa.public.key}")
    private  String RSA_PUBLIC_KEY;

    /**
     * rsa 加密的私钥
     */
    @Value("${rsa.private.key}")
    private  String RSA_PRIVATE_KEY;

编写一个RsaConfig 配置类,进行 PrivateKey 对象的生成.

@Configuration
public class RsaConfig {

    /**
     * rsa 加密的私钥
     */
    @Value("${rsa.private.key}")
    private  String RSA_PRIVATE_KEY;

    /**
     * 生成 PrivateKey 对象
     * @return
     * @throws InvalidKeySpecException
     */
    @Bean
    public PrivateKey getPrivateRSAKey() throws InvalidKeySpecException {
        PrivateKey privateRSAKey = RSAUtil.getPrivateRSAKey(RSA_PRIVATE_KEY);
        return privateRSAKey;
    }

}

如下的代码所示,调用RSAUtil.decryptToString方法,即可用对加密的密码进行解密

 @Autowired
 private PrivateKey privateRSAKey;

 @RequestMapping(value = "/login", method = RequestMethod.POST)
  public String loginVali(HttpServletRequest request) {
	//获取加密的密码
    String password = super.getPara("password").trim();	
   
    //解密密码
    try {
          password = RSAUtil.decryptToString(password, privateRSAKey);
          System.out.println("解密后的密码: " +password);
      } catch (Exception e) {
          e.printStackTrace();
      }
}

六. 效果演示

发送登录的请求, 可以看到密码已经加密

加密的内容如下

bFKaTE2K/mxc5rbz2dCOLSYw5drQDWvW5YRv9+cM6z6wSuvUTY2haipIFYd8EQZwpke7RnO8UeNxlce7bADrDGzIqJtKhSm6KGO69flCPy6bXJ2h3rJD5yCplKDCCy0Jdq+WZNZLlpchF2t2SJUKogWrvMeJCqesYil9za2CKXc=

在后台控制台中打印如下, 说明后台成功进行了解密!
在这里插入图片描述