Security Series-How many people can tell the public key and private key of RSA clearly? How to use public and private keys for RSA signature verification and encryption and decryption?

When docking with the development platforms of many Internet companies, the security of their own platforms in the future will require the caller's signature to confirm that the caller's identity is legal. At the same time, the security of future information network transmission may also require encryption and decryption. For example, when docking with Alipay and WeChat open platforms, you need to configure the public key and download the public key of the platform. The subsequent caller needs to sign the requested message. After Alipay and WeChat receive the request, they need to verify the signature. Only the identity verification can be executed. Related business processes.

In the actual development process, many people are confused about what is a public key and what is a private key, how to perform signature verification, encryption and decryption, and what is the relationship between signature verification and encryption and decryption. In this issue, we will talk about this issue in detail. For the RSA algorithm, please refer to my article "Security Series-RSA's Past and Present", encryption and decryption can refer to my article "Security Series-Handwritten JAVA Encryption and Decryption".

One, public key and private key

In the previous article "Security Series-Handwritten JAVA Encryption and Decryption", symmetric encryption and asymmetric encryption were introduced. Among them, asymmetric encryption uses the RAS algorithm. The so-called asymmetric means that the secret key used for encryption is different from the secret key used for decryption. In other words, RSA has a pair of secret keys, one of which is a public key, the other is a private key, one is used for encryption, and the other is used for decryption.

The two applications of the RAS algorithm are signature verification, encryption and decryption.

Before public key exchange

In the process of network communication, before the communication, both the caller and the callee need to generate a pair of public and private keys; then the caller and the callee exchange public keys; so that the caller and the callee both have their own private keys and The public key of the other party, which is used for signature verification and encryption and decryption for communication security.

After public key exchange

The private key can only be owned by oneself and cannot be exposed to anyone. As long as the private key is not exposed, the communication is secure. The private key can be equivalent to the identity.

The public key can be obtained by anyone. After obtaining the public key of the other party, the signature of the other party can be verified by the public key; at the same time, the public key of the other party is used for encryption, and it can only be decrypted by the private key of the other party.

Because the public key is public, it also facilitates the exchange of public keys between the communicating parties, so there is no need to consider whether it is leaked during the exchange.

2. The relationship between signature verification and encryption and decryption

First of all, it is emphasized that there is no relationship between signature verification and encryption and decryption .

Signature verification and encryption and decryption are necessary measures for system security, but to prevent different security risks.

Signature verification

Signature verification: to verify whether the user's identity is legal. For example, WeChat payment, any legitimate merchant can call the WeChat payment interface. So what is a legal merchant? Meet many requirements of WeChat, such as merchants registering on WeChat merchant platform to obtain merchant id, signing related payment products to obtain appid, configuring merchant's public key for opened payment products and downloading WeChat public key. Such merchants are only for WeChat. legal. Then the merchant uses its own merchant private key to sign the relevant request parameters and then calls the WeChat payment interface; after receiving the request, WeChat verifies the request through the merchant public key configured on the platform by the merchant , and the verification indicates this request. When initiated by a legitimate platform merchant, specific payment services can be made after the verification is passed.

Signature verification

Why is the private key of the caller used for signature? The signature is usually that the callee (platform) requires the caller to sign in consideration of its own security, so as to verify whether the caller is legal. The security of the callee is considered. Because the legitimate merchant has already configured its public key to the WeChat backend, when a caller passes the signed parameters to the WeChat platform, and the WeChat platform can use the public key configured by the merchant to verify the signature, indicating that the request is made A person is a legitimate merchant holding this private key, because only the merchant holding this private key can make this signature. The private key is confidential and not everyone has it. If the public key is used for the signature, everyone can obtain the public key from the Internet. An illegal caller can also obtain the public key and sign a request to WeChat. Even if the WeChat platform passes the verification, it is not known whether the caller is legal. .

encrypt and decode

Encryption and decryption: To prevent data from being hijacked during network transmission. If the merchant calls the WeChat payment interface, there are many sensitive fields in the request message such as bank card number, password, etc. (these fields are not actually needed). When the message is transmitted on the network, it is maliciously monitored, which will cause the merchant to The bank card number and password are leaked, so the merchant needs to use the WeChat public key to encrypt the entire message when calling ; after WeChat receives the request, it can use the WeChat private key to decrypt, which can prevent sensitive information from leaking. Of course, https has been encrypted during transmission.

encrypt and decode

Why use the other party's public key for encryption? Encryption is usually done by the caller (merchant) considering its own security to ensure that the caller's sensitive information is not leaked, and that only the true callee can decrypt it. How to guarantee it? That is, even if the information is hijacked during network transmission, it cannot be decrypted. If you want to decrypt, you must hold the secret key. If you want to hold the secret key only, it must be the private key, because the private key is not public. It can be decrypted, indicating that this information happened to him. Therefore, to whom the information is sent can only be decrypted with whose private key, which requires the sender to encrypt it with his public key. To send information to the WeChat platform, it must be encrypted with the public key of the WeChat platform.

Here, signature verification and encryption and decryption use different public and private keys. When signing, from the perspective of the callee (WeChat platform), who is required by WeChat to call the WeChat platform, who uses their own private key to sign; when decrypting, from the perspective of the caller (merchant), the merchant sends the information To whom, who can use their private key to decrypt. Because the private key is only held by you, the private key can be equated with legitimate users. The public key is open to the entire network and anyone can obtain it.

to sum up:

Signature: When A calls B, B must verify whether A is legal (whether it can call the interface), and A must sign with its own private key;

Decryption: When A calls B, A must verify whether B is legal (whether it can be decrypted), and B must use its own private key to decrypt;

Three, test

This simulates the process of A sending a message to B. Before the test, A generates a pair of public and private keys, B generates a pair of public and private keys, and then A and B exchange public keys, A has privateKey_A and publicKey_B, and B has privateKey_B and publicKey_A. Only one-way (A request B) signature verification and encryption and decryption are simulated here. Those who are interested can simulate the two-way (A request B, and B response A) signature verification and encryption and decryption by themselves.

For the generation of public and private keys, please refer to the previous article "Security Series-Handwritten JAVA Encryption and Decryption". Follow the official account and enter the keyword " java-summary " to get the source code.


/**
 * Description:
 *
 * @author 诸葛小猿
 * @date 2020-08-21
 */
@Slf4j
public class SignAndEncryptTest {
    
    

    public static final String  SIGN_ALGORITHMS = "SHA1WithRSA";
    public static final String CHATSET = "utf-8";

    public static String publicKey_A = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsnen01CdQc2zh/HihCNNYI6u7AFXf/NrZ/9auPvFsJcK1cWj5EFBU3lrts2OTvrmYVurhABg2g/Ya7glzUt6DwUojHOWtpwFxSH1v7FUJMvxDsbd4GXKRdWqMkqkcCMQYDpGpshbL3IAWYIw6pgnBcKksbzkDrZCZMAyHa1bB3zh5uEm9mcrRlBUGirbPNVt++3ztIfdc4Vp5hbw++daNMFr/VGDohMVg3Dlk4ZktDgHc5nakXkE8hSr6UDTw45JpfZZ0dP9XTi/CSVQdoYD+dsJIZ8uletlbrErRfZEJNx/k0w88P4kfGteNBGhlzzVo45tMkHT33O8QB6JxI4xVQIDAQAB";
    public static String privateKey_A = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyd6fTUJ1BzbOH8eKEI01gjq7sAVd/82tn/1q4+8WwlwrVxaPkQUFTeWu2zY5O+uZhW6uEAGDaD9hruCXNS3oPBSiMc5a2nAXFIfW/sVQky/EOxt3gZcpF1aoySqRwIxBgOkamyFsvcgBZgjDqmCcFwqSxvOQOtkJkwDIdrVsHfOHm4Sb2ZytGUFQaKts81W377fO0h91zhWnmFvD751o0wWv9UYOiExWDcOWThmS0OAdzmdqReQTyFKvpQNPDjkml9lnR0/1dOL8JJVB2hgP52wkhny6V62VusStF9kQk3H+TTDzw/iR8a140EaGXPNWjjm0yQdPfc7xAHonEjjFVAgMBAAECggEAec/qIPXZIF0CuTuEXKSr38gD5NpVmuPO38EPb0uJ96pgnuCzqMxRhmRN/Qv4ojfmn3UucH7BnJVMJtoeEy39NdtTfeo3aJS963vufNTQlf0NoARk1RElKt1XudPwwQlt2ABu0M/YTV4GlxGhyb3ohKoCN76x+si0MIhurIryovyabZCtlhGD2fg3V1t8RBlCEuz68FtB9fSh4zk7u6RhAL5LCOGNbVAiY4hx/NhrDiBfvQBhJZmPG+3gWjjZFgZEH5B0tGByuG2M+dj2qT5LFepkhGyI/upJwOhJrjiRrvR7LmSYCz0lI8/2fVCF8jN/TJav/1xVR82d/165Movm0QKBgQDZv/H1bhPoCoeh8z3ww8Um5FjFb1MMjmh4oB1d2+0QlYTbSVx6mOxBoh0yk+jKztotJyWs61nnHekOhdHFx9Ij1L8oMxybBK+heTuzl2WIs9/2CRBV4XfKMwNiYxJYkaXxUgeHx/2IVXTuFMKMrWhf7kxk2iFrK+Gv63oY0dmvhwKBgQDR0TWXRXC2qEqH/NV/6d24UHl4i/+UP1aKE9jA8xArJYBlKtTWCgM7g3/wxr0IRB6RocVupop/kZJ9RUFjprfaykDOj+A0oC+IDwUmGIjGbR4P921qjWEVQGIFSJvnIwHwGfEAPxvw0uW2tqz9C2GUZ9OB17lecfIdeJQX2Hb3QwKBgA9bWCclAkZlJ7emPgIS7H6XsCMMfODv0jJfqHKMJiX7RYlpnRoQWukuE70TbWGQQRbaIfAWERsZouwhR/AY7ZsVT/33zNap9/D9adZ6oPCJLwxdC0fjRN1/x4dS0WJpszhXvqw20Iyi6kI4OJhPSoMpfT3HnH/AcoRDqTLC6gVVAoGBAI3f9GfseZHZbERV75wF7HoEWI7tw41f4smNMAUQln9GZXKDKtXsgVEN00ZhbFMZlL4O8GyoyoAGVFLGsLeMdUfJeVbzrLyJEHrlBStEbcAW6rwLJ/5jySDQnzdJaLo7TsUnFXKAOgl24gPRtFmLB5mNN1TWJS86x2esMB+LrK33AoGADEDHIUtulc4zclLH9MJj7JcZPkgVz5llJ1jQj3fOu4iPc9TNvV2gV2kWU446gyMmRrQ2We1awnrjaeSzeFnf0OhL+yTzNUmRLMYWZhja/KMhr7b9vVRCCrysZJod+MWodEH+HIJlu9RGIxv7fNNy1S4yRU92OQU43XQ1S93eaEE=";

    public static String publicKey_B = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8GjRufWGPI7Xe6caZ5h5PbnRIQVzD4P1gDjKZaibcxcApGEaqFkT3Am2U6iKv6paELuwxy+dUL1Jvbs09QljuHgDB9SV0VxSM5LscpCmWJ5P1V6Y/QiholCQHCFR6ok6oE2HWGRw/bPQWr/gHfa2zNPu+CB64cbOxLHIQYIRji47tyywAL5ABhF1msZY2vW8xaFKHGq74sxNpf8s0NUnRnVRANjHtuDa/zvrHim45gqBWg+3gPVSQyPU3ydMoj0AiORJQmqprHaZDB7BufpTEZA6I2WElsKJcsGMdwfSd1s0B1iCzrkMmT30n/XXxyw8qQGsvJvQ2V90QiAV9bV+wIDAQAB";
    public static String privateKey_B = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/waNG59YY8jtd7pxpnmHk9udEhBXMPg/WAOMplqJtzFwCkYRqoWRPcCbZTqIq/qloQu7DHL51QvUm9uzT1CWO4eAMH1JXRXFIzkuxykKZYnk/VXpj9CKGiUJAcIVHqiTqgTYdYZHD9s9Bav+Ad9rbM0+74IHrhxs7EschBghGOLju3LLAAvkAGEXWaxlja9bzFoUocarvizE2l/yzQ1SdGdVEA2Me24Nr/O+seKbjmCoFaD7eA9VJDI9TfJ0yiPQCI5ElCaqmsdpkMHsG5+lMRkDojZYSWwolywYx3B9J3WzQHWILOuQyZPfSf9dfHLDypAay8m9DZX3RCIBX1tX7AgMBAAECggEBAIkRYyMGCTYfwGvuagPdYOCH1NxXBjXOjwdL7xUFRenyUDrNxbdq0gcuhbaDzMuq6XFLltwFKecsC4zkqHjqhkZSExLXOMaFLur5+4WErIJzr3OkKC5Wjm9YofDp/XsyldzCq+nomodXXuLGFwi/o8NYNEB5xKSVGNPrIkfqxfNazdR63738zq0ZPQmMjxEb/AK5uc+fdF9qosDrNI0SqQng00mhfpilvwHZbOYPfKNfh26lpqTEAGk0gaFGfr/QnhUDAnxfaoLhr9zELr4utrkwpaCzX958MrRB5naeScocYSl1h4Bi6htjjpdLWDKkk/vQ8Keno6GtF9Iha8MdvnECgYEA9p5UzaP3qYek4pe96milqmPiYkQeqSAUWSp1TpC5ppIoyPGMYl7Ia8SOsIYBw+9WL9iIR6jqZOpd/E68j8YsW5PyJuFYQTVjXZrVD76D435mskl4gsKz1izEWz5jzU/oE4mGfuaobfaOuw5ixun7dd8FrXknIVHbne0zyEZ+FY0CgYEAxw0Jq3aJbrJHX8ahPsZAodbWKYH8Ojkt2GkXKdrB9HJ6EGKockjPj7R/+ForXw2XWoGdoL4QPalhKuJX+3bsSQIgt7mDRiDEPK7XkbKd5mS/HTXWXsTIkGaDhYlq6yOkbmRsR3QgCfnhLYaaYkZ6kIKDsGgUJF8oIqxKrlDWo6cCgYBUyulzbu3nLwklE3Er2GElbYRXrv4vviTg53U/1wjN2bEGLe7Ln7UfQIyi6uBOgsrKVpO8t7onimFYL6YrdMKplfuLHK2gdf+9HlAlQqbMIBilMheqNdFpUSkOCix8Wf38QauplBrS/BPlArQ5mhdoVo74LxCiJyfwa68DLCGLvQKBgEGg4tdNtfJxhWbmrrNr2lOB6gq1eNwZjiwUOjbqkZhvRh+w56kGqKjQ8oCH+lTUvlpw8e/VurUZ65egGTIn+6/2q6Ln34h3tTvsydaX9cfI39pZrdyBNT+nDSYyMLZmggiDw8+rUgT4Bm5kOvK8Gh0bax/2sO1tEmacN+NRc/NxAoGALzEnmKI9B46NVNOWi0VLtTdiloSI6bxgli0Rm8T+6wD6y9JNnWsibYydGx9pDn6w2qihuP1QcKruHUiZ7V8aahhD4o4e/a+IgRzNYcQh4CngUzL+XymlqQVbDSaiEiVi/qSNv+i9mgeF/mSYbYcZjhFPjzdOy3hvtO3GtjDSMQw=";

    // 封装发送的消息
    public static Map<String,String> communicationParams = null;

    public static void main(String[] args) {
    
    

        // A给B发消息
        ASendMsgToB();

        // B接收来自A的消息
        BReceiveFromA();
    }


    /**
     * A给B发消息,首先A-B交换公钥,A拥有 privateKey_A 和 publicKey_B
     *
     * A使用publicKey_B加密消息,再使用privateKey_A对密文签名,然后将密文和签名发给B
     */
    public static void ASendMsgToB(){
    
    

        // 消息明文
        String msg = "你好";

        // 加密
        String encryptMsg = encryptByPublicKey(msg,publicKey_B);

        // 签名
        String sign = signByPrivateKey(encryptMsg,privateKey_A);

        // 发送消息
        communicationParams = new HashMap<String,String>();
        communicationParams.put("encryptMsg",encryptMsg);
        communicationParams.put("sign",sign);
        log.info("A发送给B的消息:{}", JSON.toJSONString(communicationParams));

        log.info("-------------------------------------------------");
    }

    /**
     * B接收A的消息,首先A-B交换公钥,B拥有 privateKey_B 和 publicKey_A
     *
     * B收到消息后,先使用publicKey_A验签,再使用privateKey_B解密
     */
    public static void BReceiveFromA(){
    
    
        // 接收消息
        Map<String,String> receiveMsg = communicationParams;
        log.info("B接收到A的消息:{}", JSON.toJSONString(receiveMsg));
        String sign = receiveMsg.get("sign");
        String encryptMsg = receiveMsg.get("encryptMsg");

        // 验签
        Boolean tf = verifySignPublicKey(encryptMsg,publicKey_A,sign);
        if(tf){
    
    
            log.info("验签通过,说明这个信息是B认可的用户发来的");
        }

        // 解密
        String msg = decryptByPrivateKey(encryptMsg,privateKey_B);
        log.info("解密成功,说明这个信息就是发给B的");


        log.info("B收到的消息:{}", msg);
    }


    /**
     * RSA签名
     * @param content 待签名数据
     * @param privateKey 商户私钥
     * @return 签名值
     */
    public static String signByPrivateKey(String content, String privateKey)
    {
    
    
        try{
    
    
            PKCS8EncodedKeySpec priPKCS8    = new PKCS8EncodedKeySpec( Base64.decode(privateKey) );
            KeyFactory keyf                 = KeyFactory.getInstance("RSA");
            PrivateKey priKey               = keyf.generatePrivate(priPKCS8);

            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update( content.getBytes(CHATSET) );

            byte[] signed = signature.sign();

            return Base64.encode(signed);

        }catch (Exception e){
    
    
            log.error(e.getMessage(), e);
        }

        return null;
    }

    /**
     * RSA验签名检查
     * @param content 待签名数据
     * @param sign 签名值
     * @param publicKey 公钥
     * @return 布尔值
     */
    public static boolean verifySignPublicKey(String content, String publicKey, String sign)
    {
    
    
        try{
    
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            Signature signature = Signature.getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update( content.getBytes(CHATSET) );

            boolean bverify = signature.verify( Base64.decode(sign) );
            return bverify;

        }catch (Exception e){
    
    
            log.error(e.getMessage(), e);
        }

        return false;
    }

    /**
     * RSA公钥加密
     * @param str 加密字符串
     * @param publicKey 公钥
     * @return 密文
     */
    public static String encryptByPublicKey( String str, String publicKey ) {
    
    

        try{
    
    

            //base64编码的公钥
            byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));

            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            String outStr = org.apache.commons.codec.binary.Base64.encodeBase64String(cipher.doFinal(str.getBytes(CHATSET)));
            return outStr;

        }catch (Exception e) {
    
    
            log.error(e.getMessage(), e);
        }

        return null;
    }

    /**
     * RSA私钥解密
     * @param str 加密字符串
     * @param privateKey 私钥
     * @return 明文
     */
    public static String decryptByPrivateKey(String str, String privateKey){
    
    

        try{
    
    

            //64位解码加密后的字符串
            byte[] inputByte = org.apache.commons.codec.binary.Base64.decodeBase64(str.getBytes(CHATSET));
            //base64编码的私钥
            byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));

            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            String outStr = new String(cipher.doFinal(inputByte));
            return outStr;

        }catch (Exception e) {
    
    
            log.error(e.getMessage(), e);
        }

        return null;
    }

}

operation result:

00:09:01.375 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - A发送给B的消息:{
    
    "sign":"X13XFI2khSarCOTDjENC/ZTtKfUKAPXuO3b7vossIvC6Aj9WMnKd9w/w64/EqTg+42SGvJXjVpvdglRMmWVrbFSWfmrEfjejaNcq35+aor6j4tMMq0ZVxRO4BxTe+qKDx/e0037dHACvAY2ecojVcbAQaECEc3TrZJguQnte/Nv0DZYPSv/9evPnuKL3DuTl/wy+JaTEhVrvsu/4jXpQ6HRbrhrC4dnzs6AZEqtBXvgfRSkq62jbAvUguDhhZ6yexA2/5S+oOqO8mgRVnooQxkAI5QZd9z0voDIrCDp4emKuznj7vMUjmOXgdD0C3l7LuBqQ469JmAD0U2fRLWMIiQ==","encryptMsg":"lFrlwDA4RjXaxrFPkd8DrbiWQ15o7nNzvLwdWUmTgkDyV5DGMXXsbcEP8aBWqmCje49ymAdzQl3MdO+U2t51QtTvzJOS55EBOZgonN8XJHKNiW7XikWbgf54vUx/mNdHH7fqpBM8AM1qcyH2N3OISFK4NP6eCKgMXRRb3hxw4oko3cGTa98Hnl8jlR9yR2Goy1euT7lpL04VqWcJtP0aEW5gurPkTEDRmOn1UC6x8qZX+K3dxrQfOQhJVRoIOb2hbu/HhzBsknJw1QZTS5IN/n0GlRiJQUwJllQUT4XRF6zmc2y4ewnLwlMY99WqwCaB4XFaBNQO9/5fa7A/XZTr7g=="}
00:09:01.378 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - -------------------------------------------------
00:09:01.378 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - B接收到A的消息:{
    
    "sign":"X13XFI2khSarCOTDjENC/ZTtKfUKAPXuO3b7vossIvC6Aj9WMnKd9w/w64/EqTg+42SGvJXjVpvdglRMmWVrbFSWfmrEfjejaNcq35+aor6j4tMMq0ZVxRO4BxTe+qKDx/e0037dHACvAY2ecojVcbAQaECEc3TrZJguQnte/Nv0DZYPSv/9evPnuKL3DuTl/wy+JaTEhVrvsu/4jXpQ6HRbrhrC4dnzs6AZEqtBXvgfRSkq62jbAvUguDhhZ6yexA2/5S+oOqO8mgRVnooQxkAI5QZd9z0voDIrCDp4emKuznj7vMUjmOXgdD0C3l7LuBqQ469JmAD0U2fRLWMIiQ==","encryptMsg":"lFrlwDA4RjXaxrFPkd8DrbiWQ15o7nNzvLwdWUmTgkDyV5DGMXXsbcEP8aBWqmCje49ymAdzQl3MdO+U2t51QtTvzJOS55EBOZgonN8XJHKNiW7XikWbgf54vUx/mNdHH7fqpBM8AM1qcyH2N3OISFK4NP6eCKgMXRRb3hxw4oko3cGTa98Hnl8jlR9yR2Goy1euT7lpL04VqWcJtP0aEW5gurPkTEDRmOn1UC6x8qZX+K3dxrQfOQhJVRoIOb2hbu/HhzBsknJw1QZTS5IN/n0GlRiJQUwJllQUT4XRF6zmc2y4ewnLwlMY99WqwCaB4XFaBNQO9/5fa7A/XZTr7g=="}
00:09:01.379 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - 验签通过,说明这个信息是B认可的用户发来的
00:09:01.386 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - 解密成功,说明这个信息就是发给B的
00:09:01.386 [main] INFO com.wuxiaolong.EncrypteDecrypt.SignAndEncryptTest - B收到的消息:你好

Follow the official account and enter the keyword " java-summary " to get the source code.

Finished, call it a day!

[ Dissemination of knowledge, sharing value ], thank you friends for your attention and support, I am [ Zhuge Xiaoyuan ], an Internet migrant worker struggling in hesitation! ! !

Guess you like

Origin blog.csdn.net/wuxiaolongah/article/details/108138772