前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

公钥私钥区别

公钥一般用来加密、验签,私钥用来解密、签名。公钥和私钥唯一对应,用某个公钥签名过得内容只能用对应的私钥才能解签验证;同样用某个私钥加密的内容只能用对应的公钥才能解密。

公钥是公开出去的,但是私钥只能自己私密持有。

项目测试

1、项目准备:生成2组公私钥

    @Test
    public void createRSA() {
        SecureRandom random = new SecureRandom();
        //这个数字不可以随便输入
        RSAUtils.getInstance().generatorKeyPair(4096, random);
    }
客户端A的公钥(aPublicKey)
客户端A的私钥(aPrivaetKey)

客户端B的公钥(dealPublicKey)
客户端B的私钥(dealPrivaetKey)


客户端A持有 A的私钥,B的公钥
客户端B持有 B的私钥,A的公钥

2、流程解释

A向B发送信息的整个签名和加密的过程如下:

1、A先用自己的私钥(aPublicKey)对信息(一般是信息的摘要)进行签名。
2、A接着使用B的公钥(dealPublicKey)对信息内容和签名信息进行加密。

B接收到A的信息后,获取信息内容的步骤如下:

1、用自己的私钥(dealPrivaetKey)解密,A用B的公钥(dealPublicKey)加密的内容;
2、得到解密后的明文后用A的公钥(PUB_A)解签A用A自己的私钥(aPrivaetKey)的签名。

总结:从而整个过程就保证了开始说的端到端的唯一确认。A的签名只有A的公钥才能解签,这样B就能确认这个信息是A发来的;A的加密只有B的私钥才能解密,这样A就能确认这份信息只能被B读取。

2.1、加解、签名内容确定

签名:一般情况下我们只对业务数据进行签名,也可以对整个报文进行签名,但是一些公共的参数确实没有必要进行签名,签名的计算比较浪费时间。

加密:我们对整个报文进行加密

解密:对整个加密报文进行解密

验签:我们将解密后的报文获取业务数据,然后将签名和业务数据传入验签方法进行验证

2.1.1、整个报文(数据原文)

<MESSAGE>
    <BASIC_INFO>
        <TRANS_CODE>8661ff6aa57247c1899cf54c700a9ed6</TRANS_CODE>
        <TRANS_TYPE>T0001</TRANS_TYPE>
        <TRANS_TIME>1572335106478</TRANS_TIME>
    </BASIC_INFO>
    <BUSINESS_DATA>
        <COMPANY_NAME>企业名称</COMPANY_NAME>
        <ORG_CODE>123456789</ORG_CODE>
    </BUSINESS_DATA>
</MESSAGE>

2.1.1、要签名的报文(签名原文)

<BUSINESS_DATA>
    <COMPANY_NAME>企业名称</COMPANY_NAME>
    <ORG_CODE>123456789</ORG_CODE>
</BUSINESS_DATA>

2.1.3、签名后要发送的报文(加密原文)

<MESSAGE>
    <BASIC_INFO>
        <TRANS_CODE>8661ff6aa57247c1899cf54c700a9ed6</TRANS_CODE>
        <TRANS_TYPE>T0001</TRANS_TYPE>
        <TRANS_TIME>1572335106478</TRANS_TIME>
        <SIGNED_MSG>MrdpqWs62gyHWN0RKmAO/iK3W+H/A8iyAi3LGedEAYr1UAAx6ca42y35bV5LgfeijEJHC1DCSuvWitEu1WKeztxH9bldHvIQHvJ4PAn06QmggXClyvfYQZ+lACcGZQX5XUCPh3Tk6BGfoiT+DlZvnP9VEwxbXztJ2rSm2AZvzOP7paLoLUo2GUX8sY0B9h9Lt+/ISDZEYJHaiG7sU3faGu6bTO0UZiQCI3A3m/LbwMznU6tq3oTAPOTUHzMOWfH4bl3xnApw2RiCxO/SGZA+OMX7qfE+87XdtDm1fhmKy4xwe8zJj2WpD44HS3wbb0xm4Ke9TJf3libNwFpW56Aw2Im55yGhJDADLJcB8BkxdkW3JgKnVMeIcfMK7PTS9AVmOIOoyDFggG7ZTqOeoIpnbk+EiOEXn0a03/50gBgOazb6lnXbZtchfkelc+Dg+6E/QGSiV7yCrbywrLqKOfxKNioqUYr3gFG0kA3R+PB4JLZFawS+8JbI7rgir3w1OYwEOOpSYiSWV/hv/5YOdwt722Aup1WyoKRUQdw+lfTs38iP+yIVGJRhTBZ8nTFjCtgVm/5XLLW/SucCmDDQLSiMq5WDfvbX25YLNKgwZ+CH8N6l9zrqDiv79Tvcr9SUVUXifdDTwXRuShII9Y3SqYKjCMf6hR+hVg61CqVE49QzAxU=</SIGNED_MSG>
    </BASIC_INFO>
    <BUSINESS_DATA>
        <COMPANY_NAME>企业名称</COMPANY_NAME>
        <ORG_CODE>123456789</ORG_CODE>
    </BUSINESS_DATA>
</MESSAGE>

3、代码测试

3.1、报文实体 MessageDTO

package com.healerjean.proj.a_test.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;


/**
 * @author HealerJean
 * @ClassName MessageDTO
 * @date 2019/10/29  14:22.
 * @Description
 */
@Data
@JacksonXmlRootElement(localName = "MESSAGE")
public class MessageDTO {

    @JacksonXmlProperty(localName = "BASIC_INFO")
    private BasicInfo basicInfo;

    @JacksonXmlProperty(localName = "BUSINESS_DATA")
    private BussinssData bussinssData;

}

3.2、报文公共参数

@ApiModel(description = "交易基础消息体")
@Data
public class BasicInfo {

    @ApiModelProperty(value = "交易编号")
    private String transCode;

    @ApiModelProperty(value = "交易类型")
    private String transType;

    @ApiModelProperty(value = "交易时间")
    private Date transTime;

    @ApiModelProperty(value = "签名:一般我们只对业务数据data进行签名就可以了,没必要全部签名,有些浪费时间")
    private String signedMsg;

    /** 返回代码 */
    private String retCode;
    /** 错误信息 */
    private String retMsg;

}

3.3、报文业务数据

/**
 * @author HealerJean
 * @ClassName BussinssData
 * @date 2019-10-28  23:07.
 * @Description
 */
@Data
public class BussinssData {

    @ApiModelProperty(value = "企业Id")
    private Long companyId;

    @ApiModelProperty(value = "企业名称")
    private String companyName;

    @ApiModelProperty(value = "企业编号")
    private String orgCode;

}

    @Test
    public void clientA() {

        String aPrivaetKey = "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";
        String dealPublicKey = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAloJZU18QoWuI+j4LhLNBKJyiDU++dQodqOG6+l+05gYgUdjYNQwHalSW4Sx+koidwbp7Wj9WtnyuH/C1Rp0gsSiVi8nba70ztXsn+LoD2A6PD2vqS/Weyuwhqwi5xm5P4r2gAi2gT6H9tolesxamIBqdRmiv5KwGROJnsnwWKticARY+Q10nqKE3u6ZGGWjfPENLfb0aVUb4DkZOzslo7roVIF6/A+iBfAM/vV/9hfFd3BnU1ZS6DPBJ5yLgvlX/mLhTh8+if2apl2WV3UI6XPjzzSi8q4f0IWLw170AOx4dq7z7orH2uezfOeZqsCMf0SNp5675g1yuO4Vf2Tn34S0+88HVTzQrhHw1QgBgYXVkSumyTC7DmQ9nwQXBD1d0dltwZKmEq0h+zYgeKJ9eVSBjrwIx79JZ7MamOeePkh9k/tWKYOS+tk4gQ/htaBl2XpWtKeM+ye8B+GQYHayOSQ4QS8RKXaajDjEFAwXHSSu4bI38sJW61GMBjL2LfIR9z9nQyMOR0WJEKBr5ta8z+GIRwRGP+GQXaWyExSGP2g6DaoHy3C4dxFCvJ0X1eJhWi2kg4VettpMs60pjTfpwlQrzFAy7YAkoK4guCpaVRCwhJZYIlUkWiaE4vu47ZPd5707faWu2LWZOVuLLJWVmdLAhsJFbmSAy3G9OicbZbbcCAwEAAQ==";


        RSAUtils rsaUtils = RSAUtils.getInstance();
        BussinssData bussinssData = new BussinssData();
        bussinssData.setCompanyName("企业名称");
        bussinssData.setOrgCode("123456789");
        BasicInfo basicInfo = new BasicInfo();
        basicInfo.setTransCode(UUID.randomUUID().toString().replace("-", ""));
        basicInfo.setTransType("T0001");
        basicInfo.setTransTime(new Date());

        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setBasicInfo(basicInfo);
        messageDTO.setBussinssData(bussinssData);

        String xmlOrigin = XmlUtils.toXml(messageDTO);
        log.info("数据原文:【 {} 】", xmlOrigin);

        String signedXmlOrigin = XmlUtils.toXml(bussinssData);
        log.info("签名原文:【 {} 】", signedXmlOrigin);

        // 1、 私钥生成签名(只对业务数据进行签名)
        String sign = rsaUtils.signByPriKey(signedXmlOrigin, aPrivaetKey, RSAUtils.SHA1withRSA);
        log.info("签名:【 {} 】", sign);

        basicInfo.setSignedMsg(sign);
        String encryptOriginXml = XmlUtils.toXml(messageDTO);
        log.info("加密原文:【 {} 】", encryptOriginXml);

        // 2、公钥加密
        String encryptContent = rsaUtils.encryptByPubKey(encryptOriginXml, dealPublicKey);
        log.info("加密报文:【 {} 】", encryptContent);

        //模拟调用别人接口
        String resEncryptContent = clientB(encryptContent);
        log.info("响应加密报文:【 {} 】", resEncryptContent);

        // 1、解密
        String decryptXml = rsaUtils.decryptByPriKey(resEncryptContent, aPrivaetKey);
        log.info("响应解密报文:【 {} 】", decryptXml);

        // 验证签名
        messageDTO = XmlUtils.toObject(decryptXml, MessageDTO.class);
        sign = messageDTO.getBasicInfo().getSignedMsg();
        log.info("响应签名:【 {} 】", sign);

        bussinssData = messageDTO.getBussinssData();
        signedXmlOrigin = XmlUtils.toXml(bussinssData);
        log.info("响应签名原文:【 {} 】", signedXmlOrigin);
        boolean check = rsaUtils.verifySignByPubKey(signedXmlOrigin, sign, dealPublicKey, RSAUtils.SHA1withRSA);
        if (!check) {
            throw new RuntimeException("响应签名验证失败");
        }
        log.info("----------success----------------");


    }


    public String clientB(String encryptContent) {
        String aPublicKey = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0N6hPKO+05+ImOazyelOCe5d6UzahFNWD3BW3qBJDOaWgiMvT6G3uQuTEpprKZWP48/vZJ1uMYLXJhxGa5iMoFSB8JS+Mlc5WAnJEPwpop3Env9D5AyG5gLjtEa0KfKRph6R/PLttlN1n6UVnM/s0PpZY2MYO4RDd/xEAkgfStIs5lvfu3SehYDlfiNO/L5zL0u4FvM9mvNXEiEWK9PH3Bm9D72vebHhWGzJGfMed6OK96h47KcAiRY6hktNKEXwM5DzXF3jSRwnFl5ipmy/xkL4ffqlz0EsPvYUCumzOWmzED4vJEfW3brBVrZgVAi/KoC6OeVyA0MvD8AqoklpBLtZlk88QZPvqYy/g00U9DsCDzeTZ/CNdelFDtbYZOB3x93dnKn+N664t58cp/6X25CE0MCoJvWHS+tNFVVeZ7c3YB1Lp5NHmKFPuH0CfNcR3Wb462qm1nHMd6/LSMwDORb8ex0SR34QUpREhhhm1/xM/x1P9ZLWxs+3B1rSn5EGp96br3sJEOgsiK75o8Eq3ST7HuoQcMCp0nYVIxu8RkkJtCENBDQSsdQz5sGGBNbHWypXfVTz+U7Y6ybeCLhc3XKGMx6AWU5D0vRbAOoegnvKjChYKQfDgY4i39imMlvVQBeyibu361qbUpO9XVcPGEwWBiWiiMFVIrLa1kBqmgUCAwEAAQ==";
        String dealPrivaetKey = "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCWgllTXxCha4j6PguEs0EonKINT751Ch2o4br6X7TmBiBR2Ng1DAdqVJbhLH6SiJ3BuntaP1a2fK4f8LVGnSCxKJWLydtrvTO1eyf4ugPYDo8Pa+pL9Z7K7CGrCLnGbk/ivaACLaBPof22iV6zFqYgGp1GaK/krAZE4meyfBYq2JwBFj5DXSeooTe7pkYZaN88Q0t9vRpVRvgORk7OyWjuuhUgXr8D6IF8Az+9X/2F8V3cGdTVlLoM8EnnIuC+Vf+YuFOHz6J/ZqmXZZXdQjpc+PPNKLyrh/QhYvDXvQA7Hh2rvPuisfa57N855mqwIx/RI2nnrvmDXK47hV/ZOffhLT7zwdVPNCuEfDVCAGBhdWRK6bJMLsOZD2fBBcEPV3R2W3BkqYSrSH7NiB4on15VIGOvAjHv0lnsxqY554+SH2T+1Ypg5L62TiBD+G1oGXZela0p4z7J7wH4ZBgdrI5JDhBLxEpdpqMOMQUDBcdJK7hsjfywlbrUYwGMvYt8hH3P2dDIw5HRYkQoGvm1rzP4YhHBEY/4ZBdpbITFIY/aDoNqgfLcLh3EUK8nRfV4mFaLaSDhV622kyzrSmNN+nCVCvMUDLtgCSgriC4KlpVELCEllgiVSRaJoTi+7jtk93nvTt9pa7YtZk5W4sslZWZ0sCGwkVuZIDLcb06JxtlttwIDAQABAoICAQCO58EMqgzOV549jD+/hbvuZZpwbTD3S92RhpLUO581cMerLutKots/mIWR039yfojbcsbAj7czmfpylUhpfbOWwmQL0GOoToMUY5U2UthngptPFzXlXZeiMMZe8PADeqYbMdUFfHDka3jMom3qOS0O+nYubiPkSXnCWf3/uFYL5JNrbMU9jOuk7z5Ny7hvU+XyACtjffPM2I+abiNRsGcTlFeO3qcbfN3E9AjHNKcxUFXAMD6ndIma02Q4NCOUVW9UgF+/aeRudvm7qFa9OK7VrANA3tcVPwcL1De9f9UCTLv7XnrGpZcQPdpNzXurNg51stxRgQ+kLJG6Lg8t4B58jyGzdjrzIkBkzO4zWbrMUSB/npdVGAW3wujwm6CSZq7zWMsgh3o2JcUOB7kdJ2nRhJu5OMYiEUBs8LeQI7NFb1vRgHIbefWXV6wMLT/gGvQnl3E97IppGtnWs1ujJXzEGI5fx7kAWO+foGjUuJXeSC9HCMnSzrxdO4WQWBhBrJrM/CLjHN3n1tW8tZA/lvQZqsxb/4ZcWZ//4Bwwo/jEMQ6wKXZ5YWdzZhRfVxjH4RuCzbOUIzSzRaEKTO0Km291KMzsdQucjdblaPPXFbYND0JwTq/4TI3iXipMehO6IDmiNdb2vOMOedbWM0gvy10Au3MmWodDodwJlCWLkDWgcQKCAQEA9Z/JsRxQEQ8Vrh9DC6FH/HVTwWXqPVJbIcJ2+PzU/GMNDS/1tWB6DdpwksJZ9HZVC6AHilubWXJ/8wfbD7auMHr9reUlS8peDxwAnbe/NuIg8kxeNOZXnNCwqfJszBqx8BhObLVyIoh8brzghEUrK5knM0pK3QyJ8IEzDk8z+rESLr3hB19p0hhgCq2NSFGHu8DOsfG9g5MAdkhvk+7+FfFUxcgyTPz7wyN+1/JC+BH8XYXk5SRgzaKA0iBYghjPgufM9wZh2GOyXNm5lcHdIVxNXAvs3tjM/9KMlTMgsYr3kgmsqEARzlLyp5D23aIaf12KsIUwl5sMoq1OO4GyPQKCAQEAnN35mBKekUuM+M9n+KEoSIIF0Ls3TLijRViF+Ps7hNpTBFINcLg1aLTBF0MFTtzwHezcbh9d+m2j/9eq0OOCFRqHtzXf2JHMyqZIXj0+mYNBe3woFUszaYo2Bgy/42wWiBN0Gw+f+4rnqOvFIL5keUQP1JWAhJehfhVNvR87IZbbYD+P4pGEpXeOQZAw5YQNozjq4u2sK13Wv6JI/xzD3yaH38zAzaYXYTjLn5YPYebKwnsgsFeglpC6JG/Jjg51AJGJxgBbAWJfg8anTy9uKYTwYSbD3JgaGeWGAERa/9Kz130xVMttYqAzG/m39zaEM3+XrIAWQ8IhiUdGui4jAwKCAQEAhDelTG9fMi+ajgZKAuKoa1+E3GBN/QBuCfgyLsl6pPl0txqP+ziZuwdQ/c8cuRlRolZceL/jGf0mnt4lr4m4rmQmVgs5Tlj61MtQEZYtmg+TiJpPQ86Sbtlvn6vdoOjly8ZpwN7TN3+c68dEXC8Xk/p3PYbKUb9EKXCC2TsNUe8rSHnxvhRAVFXGrTjLCpjIpeqd2O+2AjOJViKb3VgS8iDcbzLa0NKFe3+J8hh4sCyOWpGOq0Iv0cGd8n5y5mUQnvjEPlzzIpZYFt8kpVacAC89fUT2FudBQpxGDLJe8PNLXRNUG6WRcCz6bfT8zkVKWjEyTN8FTzapUJBVwnaISQKCAQBvzREYHqUfHv6hUolivdGNJAZrBxPZvXq4cOhDVSPNgyFJ4gUsQk3mi3VXU/ATjgog+fD9F6QOWVhafuaCrLPIwLjbji01GG0iPbM0X2gfV1ozXYDf9FH3NYdddnbI6v+ACoVkyBUY3Z5QWYGM3cWUXDsAI3GOjteNmjdmxDyLqw49oe+15kro97XO6qq+2ggyPd3C0Ow1mFL3D/4AvQqpH7gVfMQpjef55dXSrsvV1fzK8aCRrlKJHStdzsKTWaBwQEo2cYhrCybSL6KNIFvegZ4lT9Cmh02LCXgg9pb4375HpjWjnr0eXtkuZiOEsTk1zwlV65ByyIjIY6F4DmvrAoIBAD4MjfYkqbuTa23zpJ/cipFmQEHgLkFoY41VY7gyghHdAWGPDYtbsUwI1xWp9cI2vpXXyTXCobjDbAr2/OWuxtcps6Aajr5mCTLPlRwzCVhQ/0zag8SEb5+5UAxXR/Nx5/e0xwbats9iCNQ1xsaGWUVtou0QkchIpxItfukqHw86de1XeFBU2gAfSbPa+Pv3OjLXIAH/ddBo1COx8UE/ITN2/zrZjil321knifFcP6jfRsOdhEN+1kdAtHs76ZnVddOz+6RlpCl+y2qcEXNjcb/6oCb11Xyoqatg2vaKzSJIca/Kzx9/4265/BJctMSmQzHKDR2rLhAJp5QbsGPAKA0=";

        log.info("----------------------------------------------------------------------");
        log.info("接收加密报文:【 {} 】", encryptContent);

        //1、私钥解密
        RSAUtils rsaUtils = RSAUtils.getInstance();
        String decryptXml = rsaUtils.decryptByPriKey(encryptContent, dealPrivaetKey);
        log.info("解密报文:【 {} 】", decryptXml);

        // 验证签名
        MessageDTO messageDTO = XmlUtils.toObject(decryptXml, MessageDTO.class);
        String sign = messageDTO.getBasicInfo().getSignedMsg();
        log.info("签名:【 {} 】", sign);
        BussinssData bussinssData = messageDTO.getBussinssData();
        String signedXmlOrigin = XmlUtils.toXml(bussinssData);
        log.info("签名原文:【 {} 】", signedXmlOrigin);
        boolean check = rsaUtils.verifySignByPubKey(signedXmlOrigin, sign, aPublicKey, RSAUtils.SHA1withRSA);
        if (!check) {
            throw new RuntimeException("验签失败");
        }

        //业务处理
        BasicInfo basicInfo = messageDTO.getBasicInfo();
        basicInfo.setRetCode("200");
        basicInfo.setRetMsg("Success");
        bussinssData.setCompanyId(1L);
        signedXmlOrigin = XmlUtils.toXml(bussinssData);

        // 1、 私钥生成签名(只对业务数据进行签名)
        sign = rsaUtils.signByPriKey(signedXmlOrigin, dealPrivaetKey, RSAUtils.SHA1withRSA);
        log.info("返回签名:【 {} 】", sign);
        basicInfo.setSignedMsg(sign);
        String encryptOriginXml = XmlUtils.toXml(messageDTO);
        log.info("返回加密原文:【 {} 】", encryptOriginXml);

        // 2、公钥加密
        encryptContent = rsaUtils.encryptByPubKey(encryptOriginXml, aPublicKey);
        log.info("返回加密报文:【 {} 】", encryptContent);

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

3、测试日志

2019-10-29 15:49:34 INFO  -[                                ]- 数据原文:【 <MESSAGE><BASIC_INFO><TRANS_CODE>3cbd6fce24654e079411b010b9097d7b</TRANS_CODE><TRANS_TYPE>T0001</TRANS_TYPE><TRANS_TIME>1572335373899</TRANS_TIME></BASIC_INFO><BUSINESS_DATA><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BUSINESS_DATA></MESSAGE> 】 com.healerjean.proj.a_test.XmlRsa.clientA[57]
2019-10-29 15:49:34 INFO  -[                                ]- 签名原文:【 <BussinssData><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BussinssData> 】 com.healerjean.proj.a_test.XmlRsa.clientA[60]
2019-10-29 15:49:34 INFO  -[                                ]- 签名:【 MrdpqWs62gyHWN0RKmAO/iK3W+H/A8iyAi3LGedEAYr1UAAx6ca42y35bV5LgfeijEJHC1DCSuvWitEu1WKeztxH9bldHvIQHvJ4PAn06QmggXClyvfYQZ+lACcGZQX5XUCPh3Tk6BGfoiT+DlZvnP9VEwxbXztJ2rSm2AZvzOP7paLoLUo2GUX8sY0B9h9Lt+/ISDZEYJHaiG7sU3faGu6bTO0UZiQCI3A3m/LbwMznU6tq3oTAPOTUHzMOWfH4bl3xnApw2RiCxO/SGZA+OMX7qfE+87XdtDm1fhmKy4xwe8zJj2WpD44HS3wbb0xm4Ke9TJf3libNwFpW56Aw2Im55yGhJDADLJcB8BkxdkW3JgKnVMeIcfMK7PTS9AVmOIOoyDFggG7ZTqOeoIpnbk+EiOEXn0a03/50gBgOazb6lnXbZtchfkelc+Dg+6E/QGSiV7yCrbywrLqKOfxKNioqUYr3gFG0kA3R+PB4JLZFawS+8JbI7rgir3w1OYwEOOpSYiSWV/hv/5YOdwt722Aup1WyoKRUQdw+lfTs38iP+yIVGJRhTBZ8nTFjCtgVm/5XLLW/SucCmDDQLSiMq5WDfvbX25YLNKgwZ+CH8N6l9zrqDiv79Tvcr9SUVUXifdDTwXRuShII9Y3SqYKjCMf6hR+hVg61CqVE49QzAxU= 】 com.healerjean.proj.a_test.XmlRsa.clientA[64]
2019-10-29 15:49:34 INFO  -[                                ]- 加密原文:【 <MESSAGE><BASIC_INFO><TRANS_CODE>3cbd6fce24654e079411b010b9097d7b</TRANS_CODE><TRANS_TYPE>T0001</TRANS_TYPE><TRANS_TIME>1572335373899</TRANS_TIME><SIGNED_MSG>MrdpqWs62gyHWN0RKmAO/iK3W+H/A8iyAi3LGedEAYr1UAAx6ca42y35bV5LgfeijEJHC1DCSuvWitEu1WKeztxH9bldHvIQHvJ4PAn06QmggXClyvfYQZ+lACcGZQX5XUCPh3Tk6BGfoiT+DlZvnP9VEwxbXztJ2rSm2AZvzOP7paLoLUo2GUX8sY0B9h9Lt+/ISDZEYJHaiG7sU3faGu6bTO0UZiQCI3A3m/LbwMznU6tq3oTAPOTUHzMOWfH4bl3xnApw2RiCxO/SGZA+OMX7qfE+87XdtDm1fhmKy4xwe8zJj2WpD44HS3wbb0xm4Ke9TJf3libNwFpW56Aw2Im55yGhJDADLJcB8BkxdkW3JgKnVMeIcfMK7PTS9AVmOIOoyDFggG7ZTqOeoIpnbk+EiOEXn0a03/50gBgOazb6lnXbZtchfkelc+Dg+6E/QGSiV7yCrbywrLqKOfxKNioqUYr3gFG0kA3R+PB4JLZFawS+8JbI7rgir3w1OYwEOOpSYiSWV/hv/5YOdwt722Aup1WyoKRUQdw+lfTs38iP+yIVGJRhTBZ8nTFjCtgVm/5XLLW/SucCmDDQLSiMq5WDfvbX25YLNKgwZ+CH8N6l9zrqDiv79Tvcr9SUVUXifdDTwXRuShII9Y3SqYKjCMf6hR+hVg61CqVE49QzAxU=</SIGNED_MSG></BASIC_INFO><BUSINESS_DATA><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BUSINESS_DATA></MESSAGE> 】 com.healerjean.proj.a_test.XmlRsa.clientA[68]
2019-10-29 15:49:34 INFO  -[                                ]- 加密报文:【 b2uXZL643Z+U2tZl5iamx/dK0E8gvBnJ6BfaDS5Jz4L+UWIpQrrYPI9YzQnKnATJrJyDx1N8ksJq2j6U/WOurFsCTkzsBXi3x7bYbdK3KmulS8HsvxHq6bcFAqzFlxoTRCnBu75d9gJyj/Xu3RRvqclLs4jYlGAhfn0tDctCJFNFt/ZNc1FknPPPet457wadPZILh9kIToGmZtn3YfuAGpLgT4MlCRRm3dPvXYDoCvuE2rzeEdtWOfjc+18J/x3i7ZH08D0HmKhBvdmGq6YzoiFMiTUWg/IOCVZqNyD2BcNTPHhb/57qE7PEEbw1/KEdlJGAY0u3xQTwmnmp1GI8zHKvR0YmfmM+c6c+GV5VJ2tKtip+Mtk4/u5Ypp3ejZrUW7gbnwyIpH6IcBnA3Mg1qsPH9P/PeWSvGQJ7Zwrec8AbSPpT/xaIKWA0zkiAlAWoXCa2wtsxNH9AXH3fFJbmHM0KvZ2b8YHgEoVztmMkDVbj1YrKOj0I3CGYovN3l8ZT9qe7mHeRcNNWhWbRg0RwEWXH8EJV4deGzYydgNRESI7VVsDE+BqSiPOrE+aaDGLKvKVlKkl4U4+o153qP7KlE+lvvTDyGc2lg78BuOhdJLveRrmVg+D+syb+WUB5QfVg3Ovycz0wXP1LzX7KASYYIdGi9D9tQH1ZE8x3AyeHSTFH9dHmn0STbwPDkMuW9p4NCIK9/jfGD+Anw+ISV671J/k1Sk9ptaN+BiiA+9flYmhzAWVodFWcSnbxZRTNMu1gLUV2TXrb/h0Ut6nkhcHhJXEyeahzGQcJh5ks19JWuxTOI6jnQQFjHJSWQhpRmtRuNsl53zcXHcCHCAQjuF167On9vNpi7axJ8wqiOa+m2Q2ATPk1Pi73SsEI+rmrRnhizZ01HAUWTXp6XEHBi6pnSdwK610hhY0HPF5dV08BoQ2qqBkm/WSx/fSQDDyPa5/WXVEMhGahOlJScMPOQkyAQmvJV39axdipqTWrCUxoo2skAF8khKYiwcVPiuEXosimWpMXhXR4Lc0B/JEYaVV5eDtVxYDiqE7Kzhskw/zK6RQ3KAmhR/oyHKaSktH0i/h9Ru9H5QZR1trxrG2y8on4LJHYRUX/UE6B4JW2u8FqTZ5qwQAmPpEgNi/yNYYoorN7h1mrOjazuV/9P/8gIAGgo3R/eDfd7yi9v/Bik8kY6FtmYDY0xAxDpaY+aJT0+TWDp8wvpAEjDwBYLSMChn0i2ReRuw7ADLsrsWlhOFMi+wEWG7MAuUturwIqkzT/Ks5IG3VNGODzeJVycc4gBAJI64MDBbaKbye0zbgvorxRC9BcybVVAPMMR/XhPRlOEsqWMfHa9unzX8AEpLstgjOFhQ== 】 com.healerjean.proj.a_test.XmlRsa.clientA[72]
2019-10-29 15:49:34 INFO  -[                                ]- ---------------------------------------------------------------------- com.healerjean.proj.a_test.XmlRsa.clientB[104]
2019-10-29 15:49:34 INFO  -[                                ]- 接收加密报文:【 b2uXZL643Z+U2tZl5iamx/dK0E8gvBnJ6BfaDS5Jz4L+UWIpQrrYPI9YzQnKnATJrJyDx1N8ksJq2j6U/WOurFsCTkzsBXi3x7bYbdK3KmulS8HsvxHq6bcFAqzFlxoTRCnBu75d9gJyj/Xu3RRvqclLs4jYlGAhfn0tDctCJFNFt/ZNc1FknPPPet457wadPZILh9kIToGmZtn3YfuAGpLgT4MlCRRm3dPvXYDoCvuE2rzeEdtWOfjc+18J/x3i7ZH08D0HmKhBvdmGq6YzoiFMiTUWg/IOCVZqNyD2BcNTPHhb/57qE7PEEbw1/KEdlJGAY0u3xQTwmnmp1GI8zHKvR0YmfmM+c6c+GV5VJ2tKtip+Mtk4/u5Ypp3ejZrUW7gbnwyIpH6IcBnA3Mg1qsPH9P/PeWSvGQJ7Zwrec8AbSPpT/xaIKWA0zkiAlAWoXCa2wtsxNH9AXH3fFJbmHM0KvZ2b8YHgEoVztmMkDVbj1YrKOj0I3CGYovN3l8ZT9qe7mHeRcNNWhWbRg0RwEWXH8EJV4deGzYydgNRESI7VVsDE+BqSiPOrE+aaDGLKvKVlKkl4U4+o153qP7KlE+lvvTDyGc2lg78BuOhdJLveRrmVg+D+syb+WUB5QfVg3Ovycz0wXP1LzX7KASYYIdGi9D9tQH1ZE8x3AyeHSTFH9dHmn0STbwPDkMuW9p4NCIK9/jfGD+Anw+ISV671J/k1Sk9ptaN+BiiA+9flYmhzAWVodFWcSnbxZRTNMu1gLUV2TXrb/h0Ut6nkhcHhJXEyeahzGQcJh5ks19JWuxTOI6jnQQFjHJSWQhpRmtRuNsl53zcXHcCHCAQjuF167On9vNpi7axJ8wqiOa+m2Q2ATPk1Pi73SsEI+rmrRnhizZ01HAUWTXp6XEHBi6pnSdwK610hhY0HPF5dV08BoQ2qqBkm/WSx/fSQDDyPa5/WXVEMhGahOlJScMPOQkyAQmvJV39axdipqTWrCUxoo2skAF8khKYiwcVPiuEXosimWpMXhXR4Lc0B/JEYaVV5eDtVxYDiqE7Kzhskw/zK6RQ3KAmhR/oyHKaSktH0i/h9Ru9H5QZR1trxrG2y8on4LJHYRUX/UE6B4JW2u8FqTZ5qwQAmPpEgNi/yNYYoorN7h1mrOjazuV/9P/8gIAGgo3R/eDfd7yi9v/Bik8kY6FtmYDY0xAxDpaY+aJT0+TWDp8wvpAEjDwBYLSMChn0i2ReRuw7ADLsrsWlhOFMi+wEWG7MAuUturwIqkzT/Ks5IG3VNGODzeJVycc4gBAJI64MDBbaKbye0zbgvorxRC9BcybVVAPMMR/XhPRlOEsqWMfHa9unzX8AEpLstgjOFhQ== 】 com.healerjean.proj.a_test.XmlRsa.clientB[105]
2019-10-29 15:49:34 INFO  -[                                ]- 解密报文:【 <MESSAGE><BASIC_INFO><TRANS_CODE>3cbd6fce24654e079411b010b9097d7b</TRANS_CODE><TRANS_TYPE>T0001</TRANS_TYPE><TRANS_TIME>1572335373899</TRANS_TIME><SIGNED_MSG>MrdpqWs62gyHWN0RKmAO/iK3W+H/A8iyAi3LGedEAYr1UAAx6ca42y35bV5LgfeijEJHC1DCSuvWitEu1WKeztxH9bldHvIQHvJ4PAn06QmggXClyvfYQZ+lACcGZQX5XUCPh3Tk6BGfoiT+DlZvnP9VEwxbXztJ2rSm2AZvzOP7paLoLUo2GUX8sY0B9h9Lt+/ISDZEYJHaiG7sU3faGu6bTO0UZiQCI3A3m/LbwMznU6tq3oTAPOTUHzMOWfH4bl3xnApw2RiCxO/SGZA+OMX7qfE+87XdtDm1fhmKy4xwe8zJj2WpD44HS3wbb0xm4Ke9TJf3libNwFpW56Aw2Im55yGhJDADLJcB8BkxdkW3JgKnVMeIcfMK7PTS9AVmOIOoyDFggG7ZTqOeoIpnbk+EiOEXn0a03/50gBgOazb6lnXbZtchfkelc+Dg+6E/QGSiV7yCrbywrLqKOfxKNioqUYr3gFG0kA3R+PB4JLZFawS+8JbI7rgir3w1OYwEOOpSYiSWV/hv/5YOdwt722Aup1WyoKRUQdw+lfTs38iP+yIVGJRhTBZ8nTFjCtgVm/5XLLW/SucCmDDQLSiMq5WDfvbX25YLNKgwZ+CH8N6l9zrqDiv79Tvcr9SUVUXifdDTwXRuShII9Y3SqYKjCMf6hR+hVg61CqVE49QzAxU=</SIGNED_MSG></BASIC_INFO><BUSINESS_DATA><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BUSINESS_DATA></MESSAGE> 】 com.healerjean.proj.a_test.XmlRsa.clientB[110]
2019-10-29 15:49:34 INFO  -[                                ]- 签名:【 MrdpqWs62gyHWN0RKmAO/iK3W+H/A8iyAi3LGedEAYr1UAAx6ca42y35bV5LgfeijEJHC1DCSuvWitEu1WKeztxH9bldHvIQHvJ4PAn06QmggXClyvfYQZ+lACcGZQX5XUCPh3Tk6BGfoiT+DlZvnP9VEwxbXztJ2rSm2AZvzOP7paLoLUo2GUX8sY0B9h9Lt+/ISDZEYJHaiG7sU3faGu6bTO0UZiQCI3A3m/LbwMznU6tq3oTAPOTUHzMOWfH4bl3xnApw2RiCxO/SGZA+OMX7qfE+87XdtDm1fhmKy4xwe8zJj2WpD44HS3wbb0xm4Ke9TJf3libNwFpW56Aw2Im55yGhJDADLJcB8BkxdkW3JgKnVMeIcfMK7PTS9AVmOIOoyDFggG7ZTqOeoIpnbk+EiOEXn0a03/50gBgOazb6lnXbZtchfkelc+Dg+6E/QGSiV7yCrbywrLqKOfxKNioqUYr3gFG0kA3R+PB4JLZFawS+8JbI7rgir3w1OYwEOOpSYiSWV/hv/5YOdwt722Aup1WyoKRUQdw+lfTs38iP+yIVGJRhTBZ8nTFjCtgVm/5XLLW/SucCmDDQLSiMq5WDfvbX25YLNKgwZ+CH8N6l9zrqDiv79Tvcr9SUVUXifdDTwXRuShII9Y3SqYKjCMf6hR+hVg61CqVE49QzAxU= 】 com.healerjean.proj.a_test.XmlRsa.clientB[115]
2019-10-29 15:49:34 INFO  -[                                ]- 签名原文:【 <BussinssData><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BussinssData> 】 com.healerjean.proj.a_test.XmlRsa.clientB[118]
2019-10-29 15:49:34 INFO  -[                                ]- 【公钥验证数字签名】验签结果:【true】 com.healerjean.proj.util.rsa.RSAUtils.verifySignByPubKey[359]
2019-10-29 15:49:34 INFO  -[                                ]- 返回签名:【 TYZEkWVSdkH4ujqr4YnSe3WxJzt6kNwHWFq3XeQ26gnRn1BH1TBvVEuq3AevbMK8yfK3GYcVTtat32mi2I3XqWHkbzHJWQES8UT1mTLCBq3x6a1hB3iu6iYon8sl1RVFuj9aeRXhLOqoYGfcW5Oeihi4ty3ysKDk9zVFwJFl3Vx8JlH0ZBbhS6MBBzzaNn6ejviK0CesUFZWDi7vRed4KPyGPtnGESRqa5/rL5FTy/O0ySgp4bHcG2mVUvR5yJfJfXp2XypUGfrNKfd0z/8in0Gnh0AGT16RPc2Dw4g/ElYIKIX4adeEImMcDm13YdFjVbka4Jb/xNsWLISMvMfTEdnqUPJI37/w0IZoJSmyJTkVzNsZ4MVdI8TYLsG94WnRazJ9iNdu2t9gI4tuE3UxHWTTZ6B2nX3H+3KcImKRllYFLEpZW+HNBQ3kISicUeYPHuwGfdCqo6mqDPcIhKDhGKGULdps69aSbOlyQPO+GWFRxo/sTuP1LG7etqi3++AMoIRfMRbss7KUiOLjftsUvO5PnXHQoDdWEY06G736kbwkSITn2N9+Fznwa/9kysCzlAi4zZqpA9DQvxXA9pkMfTw9Rj2EAm8sY04ed8/+oZ5OZvjs6kHZOiL3/FSTSk0B9FzMb97TfyhHPfWsiVd8BTcv+nYUo4PYrDTPV3JNWB8= 】 com.healerjean.proj.a_test.XmlRsa.clientB[133]
2019-10-29 15:49:34 INFO  -[                                ]- 返回加密原文:【 <MESSAGE><BASIC_INFO><TRANS_CODE>3cbd6fce24654e079411b010b9097d7b</TRANS_CODE><TRANS_TYPE>T0001</TRANS_TYPE><TRANS_TIME>1572335373899</TRANS_TIME><SIGNED_MSG>TYZEkWVSdkH4ujqr4YnSe3WxJzt6kNwHWFq3XeQ26gnRn1BH1TBvVEuq3AevbMK8yfK3GYcVTtat32mi2I3XqWHkbzHJWQES8UT1mTLCBq3x6a1hB3iu6iYon8sl1RVFuj9aeRXhLOqoYGfcW5Oeihi4ty3ysKDk9zVFwJFl3Vx8JlH0ZBbhS6MBBzzaNn6ejviK0CesUFZWDi7vRed4KPyGPtnGESRqa5/rL5FTy/O0ySgp4bHcG2mVUvR5yJfJfXp2XypUGfrNKfd0z/8in0Gnh0AGT16RPc2Dw4g/ElYIKIX4adeEImMcDm13YdFjVbka4Jb/xNsWLISMvMfTEdnqUPJI37/w0IZoJSmyJTkVzNsZ4MVdI8TYLsG94WnRazJ9iNdu2t9gI4tuE3UxHWTTZ6B2nX3H+3KcImKRllYFLEpZW+HNBQ3kISicUeYPHuwGfdCqo6mqDPcIhKDhGKGULdps69aSbOlyQPO+GWFRxo/sTuP1LG7etqi3++AMoIRfMRbss7KUiOLjftsUvO5PnXHQoDdWEY06G736kbwkSITn2N9+Fznwa/9kysCzlAi4zZqpA9DQvxXA9pkMfTw9Rj2EAm8sY04ed8/+oZ5OZvjs6kHZOiL3/FSTSk0B9FzMb97TfyhHPfWsiVd8BTcv+nYUo4PYrDTPV3JNWB8=</SIGNED_MSG><RET_CODE>200</RET_CODE><RET_MSG>Success</RET_MSG></BASIC_INFO><BUSINESS_DATA><COMPANY_ID>1</COMPANY_ID><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BUSINESS_DATA></MESSAGE> 】 com.healerjean.proj.a_test.XmlRsa.clientB[136]
2019-10-29 15:49:35 INFO  -[                                ]- 返回加密报文:【 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 】 com.healerjean.proj.a_test.XmlRsa.clientB[140]
2019-10-29 15:49:35 INFO  -[                                ]- ---------------------------------------------------------------------- com.healerjean.proj.a_test.XmlRsa.clientB[142]
2019-10-29 15:49:35 INFO  -[                                ]- 响应加密报文:【 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 】 com.healerjean.proj.a_test.XmlRsa.clientA[76]
2019-10-29 15:49:35 INFO  -[                                ]- 响应解密报文:【 <MESSAGE><BASIC_INFO><TRANS_CODE>3cbd6fce24654e079411b010b9097d7b</TRANS_CODE><TRANS_TYPE>T0001</TRANS_TYPE><TRANS_TIME>1572335373899</TRANS_TIME><SIGNED_MSG>TYZEkWVSdkH4ujqr4YnSe3WxJzt6kNwHWFq3XeQ26gnRn1BH1TBvVEuq3AevbMK8yfK3GYcVTtat32mi2I3XqWHkbzHJWQES8UT1mTLCBq3x6a1hB3iu6iYon8sl1RVFuj9aeRXhLOqoYGfcW5Oeihi4ty3ysKDk9zVFwJFl3Vx8JlH0ZBbhS6MBBzzaNn6ejviK0CesUFZWDi7vRed4KPyGPtnGESRqa5/rL5FTy/O0ySgp4bHcG2mVUvR5yJfJfXp2XypUGfrNKfd0z/8in0Gnh0AGT16RPc2Dw4g/ElYIKIX4adeEImMcDm13YdFjVbka4Jb/xNsWLISMvMfTEdnqUPJI37/w0IZoJSmyJTkVzNsZ4MVdI8TYLsG94WnRazJ9iNdu2t9gI4tuE3UxHWTTZ6B2nX3H+3KcImKRllYFLEpZW+HNBQ3kISicUeYPHuwGfdCqo6mqDPcIhKDhGKGULdps69aSbOlyQPO+GWFRxo/sTuP1LG7etqi3++AMoIRfMRbss7KUiOLjftsUvO5PnXHQoDdWEY06G736kbwkSITn2N9+Fznwa/9kysCzlAi4zZqpA9DQvxXA9pkMfTw9Rj2EAm8sY04ed8/+oZ5OZvjs6kHZOiL3/FSTSk0B9FzMb97TfyhHPfWsiVd8BTcv+nYUo4PYrDTPV3JNWB8=</SIGNED_MSG><RET_CODE>200</RET_CODE><RET_MSG>Success</RET_MSG></BASIC_INFO><BUSINESS_DATA><COMPANY_ID>1</COMPANY_ID><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BUSINESS_DATA></MESSAGE> 】 com.healerjean.proj.a_test.XmlRsa.clientA[80]
2019-10-29 15:49:35 INFO  -[                                ]- 响应签名:【 TYZEkWVSdkH4ujqr4YnSe3WxJzt6kNwHWFq3XeQ26gnRn1BH1TBvVEuq3AevbMK8yfK3GYcVTtat32mi2I3XqWHkbzHJWQES8UT1mTLCBq3x6a1hB3iu6iYon8sl1RVFuj9aeRXhLOqoYGfcW5Oeihi4ty3ysKDk9zVFwJFl3Vx8JlH0ZBbhS6MBBzzaNn6ejviK0CesUFZWDi7vRed4KPyGPtnGESRqa5/rL5FTy/O0ySgp4bHcG2mVUvR5yJfJfXp2XypUGfrNKfd0z/8in0Gnh0AGT16RPc2Dw4g/ElYIKIX4adeEImMcDm13YdFjVbka4Jb/xNsWLISMvMfTEdnqUPJI37/w0IZoJSmyJTkVzNsZ4MVdI8TYLsG94WnRazJ9iNdu2t9gI4tuE3UxHWTTZ6B2nX3H+3KcImKRllYFLEpZW+HNBQ3kISicUeYPHuwGfdCqo6mqDPcIhKDhGKGULdps69aSbOlyQPO+GWFRxo/sTuP1LG7etqi3++AMoIRfMRbss7KUiOLjftsUvO5PnXHQoDdWEY06G736kbwkSITn2N9+Fznwa/9kysCzlAi4zZqpA9DQvxXA9pkMfTw9Rj2EAm8sY04ed8/+oZ5OZvjs6kHZOiL3/FSTSk0B9FzMb97TfyhHPfWsiVd8BTcv+nYUo4PYrDTPV3JNWB8= 】 com.healerjean.proj.a_test.XmlRsa.clientA[85]
2019-10-29 15:49:35 INFO  -[                                ]- 响应签名原文:【 <BussinssData><COMPANY_ID>1</COMPANY_ID><COMPANY_NAME>企业名称</COMPANY_NAME><ORG_CODE>123456789</ORG_CODE></BussinssData> 】 com.healerjean.proj.a_test.XmlRsa.clientA[89]
2019-10-29 15:49:35 INFO  -[                                ]- 【公钥验证数字签名】验签结果:【true】 com.healerjean.proj.util.rsa.RSAUtils.verifySignByPubKey[359]
2019-10-29 15:49:35 INFO  -[                                ]- ----------success---------------- com.healerjean.proj.a_test.XmlRsa.clientA[94]

工具类

1、RSAUtils

@Slf4j
public class RSAUtils {

    private static volatile RSAUtils rsaUtils;
    public static final String MD5withRSA = "MD5withRSA";
    public static final String SHA1withRSA = "SHA1withRSA";
    public static final String RSA = "RSA";

    private RSAUtils() {
    }

    public static RSAUtils getInstance() {
        if (null == rsaUtils) {
            synchronized (RSAUtils.class) {
                if (rsaUtils == null) {
                    rsaUtils = new RSAUtils();
                }
            }
        }
        return rsaUtils;
    }


    public static void main(String[] args) {
        SecureRandom random = new SecureRandom();
        //生成一对密钥对
        KeyPair keyPair = getInstance().generatorKeyPair(4096, random);
        System.out.println(keyPair);
    }


    /**
     * 生成密钥对
     *
     * @param keysize
     * @param random
     * @return
     */
    public KeyPair generatorKeyPair(int keysize, SecureRandom random) {
        String prefixStr = "【生成密钥对】";
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
            keyPairGenerator.initialize(keysize, random);
            java.security.KeyPair keyPair = keyPairGenerator.generateKeyPair();
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

            String publicKeyStr = Base64.encodeBase64String(rsaPublicKey.getEncoded());
            String privateKeyStr = Base64.encodeBase64String(rsaPrivateKey.getEncoded());

            log.info("{}Public Key:【{}】", prefixStr, publicKeyStr);
            log.info("{}Private Key:【{}】", prefixStr, privateKeyStr);
            KeyPair generatorKeyPair = new KeyPair();
            generatorKeyPair.setPublicKeyStr(publicKeyStr);
            generatorKeyPair.setPrivateKeyStr(privateKeyStr);
            return generatorKeyPair;
        } catch (NoSuchAlgorithmException e) {
            log.error("{}异常,", prefixStr, e);
        }
        return null;
    }

    /**
     * 还原公钥,X509EncodedKeySpec 用于构建公钥的规范
     *
     * @param publicKeyStr 公钥
     * @return
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    private PublicKey restorePublicKey(String publicKeyStr) throws InvalidKeySpecException, NoSuchAlgorithmException {
        byte[] publicKeyByte = Base64.decodeBase64(publicKeyStr);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        return publicKey;
    }

    /**
     * 还原私钥 PKCS8EncodedKeySpec
     *
     * @param privateKeyStr 私钥
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private PrivateKey restorePrivateKey(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        return privateKey;
    }

    /**
     * 通过公钥获取秘钥属性
     *
     * @param publicKey
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private KeyPair getKeySizeByPubKey(PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyPair keyPair = new KeyPair();
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        RSAPublicKeySpec keySpec = keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
        BigInteger modulus = keySpec.getModulus();
        //RSA秘钥大小
        int keySize = modulus.toString(2).length();
        //RSA最大加密明文大小
        int maxEncryptSize = keySize / 8 - 11;
        //RSA最大解密密文大小
        int maxDecryptSize = keySize / 8;
        keyPair.setKeySize(keySize);
        keyPair.setMaxEncryptSize(maxEncryptSize);
        keyPair.setMaxDecryptSize(maxDecryptSize);
        return keyPair;
    }

    /**
     * 通过私钥获取秘钥属性
     *
     * @param privateKey
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private KeyPair getKeySizeByPriKey(PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyPair keyPair = new KeyPair();
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        RSAPrivateKeySpec keySpec = keyFactory.getKeySpec(privateKey, RSAPrivateKeySpec.class);
        BigInteger modulus = keySpec.getModulus();
        //RSA秘钥大小
        int keySize = modulus.toString(2).length();
        //RSA最大加密明文大小
        int maxEncryptSize = keySize / 8 - 11;
        //RSA最大解密密文大小
        int maxDecryptSize = keySize / 8;
        keyPair.setKeySize(keySize);
        keyPair.setMaxEncryptSize(maxEncryptSize);
        keyPair.setMaxDecryptSize(maxDecryptSize);
        return keyPair;
    }

    /**
     * 公钥加密
     *
     * @param original     原文
     * @param publicKeyStr 公钥
     * @return 密文
     */
    public String encryptByPubKey(String original, String publicKeyStr) {
        String prefixStr = "【公钥加密】";
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            if (StringUtils.isEmpty(publicKeyStr)) {
                log.info("{}失败,publicKeyStr为空", prefixStr);
                return null;
            }
            byte[] originalByte = original.getBytes("UTF-8");
            if (null == originalByte) {
                log.info("{}失败,originalByte为空", prefixStr);
                return null;
            }
            PublicKey publicKey = restorePublicKey(publicKeyStr);
            KeyPair keyPair = getKeySizeByPubKey(publicKey);
            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            //RSA最大加密明文大小
            int maxEncryptSize = keyPair.getMaxEncryptSize();
            int inputLen = originalByte.length;
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offset > 0) {
                if (inputLen - offset > maxEncryptSize) {
                    cache = cipher.doFinal(originalByte, offset, maxEncryptSize);
                } else {
                    cache = cipher.doFinal(originalByte, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * maxEncryptSize;
            }
            byte[] encryptedData = out.toByteArray();
            String ciphertext = Base64.encodeBase64String(encryptedData);
            log.debug("{}密文:【{}】", prefixStr, ciphertext);
            return ciphertext;
        } catch (Exception e) {
            log.error("{}异常,", prefixStr, e);
        } finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error("{}关闭字节数组流异常,", prefixStr, e);
                }
            }
        }
        return null;
    }
    /**
     * 私钥解密
     *
     * @param ciphertext    密文
     * @param privateKeyStr 私钥
     * @return 明文
     */
    public String decryptByPriKey(String ciphertext, String privateKeyStr) {
        String prefixStr = "【私钥解密】";
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            if (StringUtils.isEmpty(privateKeyStr)) {
                log.info("{}失败,privateKeyStr为空", prefixStr);
                return null;
            }
            byte[] ciphertextByte = Base64.decodeBase64(ciphertext);
            if (null == ciphertextByte) {
                log.info("{}失败,ciphertextByte为空", prefixStr);
                return null;
            }
            PrivateKey privateKey = restorePrivateKey(privateKeyStr);
            KeyPair keyPair = getKeySizeByPriKey(privateKey);
            int maxDecryptSize = keyPair.getMaxDecryptSize();
            Cipher cipher = Cipher.getInstance(RSA);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            int inputLen = ciphertextByte.length;
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offset > 0) {
                if (inputLen - offset > maxDecryptSize) {
                    cache = cipher.doFinal(ciphertextByte, offset, maxDecryptSize);
                } else {
                    cache = cipher.doFinal(ciphertextByte, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * maxDecryptSize;
            }
            byte[] decryptedData = out.toByteArray();
            String original = new String(decryptedData, "UTF-8");
            log.debug("{}明文:【{}】", prefixStr, original);
            return original;
        } catch (Exception e) {
            log.error("{}异常,", prefixStr, e);
        } finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error("{}关闭字节数组流异常,", prefixStr, e);
                }
            }
        }
        return null;
    }



    /**
     * 私钥数字签名
     *
     * @param original      原文
     * @param privateKeyStr 私钥
     * @param algorithm     算法
     * @return 数字签名
     */
    public String signByPriKey(String original, String privateKeyStr, String algorithm) {
        String prefixStr = "【私钥数字签名】";
        try {
            byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
            if (null == privateKeyByte) {
                log.info("{}失败,privateKeyByte为空", prefixStr);
                return null;
            }
            byte[] originalByte = original.getBytes("UTF-8");
            if (null == originalByte) {
                log.info("{}失败,originalByte为空", prefixStr);
                return null;
            }
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

            Signature signature = Signature.getInstance(algorithm);
            signature.initSign(privateKey);
            signature.update(originalByte);
            byte[] signByte = signature.sign();
            String signs = Base64.encodeBase64String(signByte);
            log.debug("{}数字签名:【{}】", prefixStr, original);
            return signs;
        } catch (Exception e) {
            log.error("{}异常,", prefixStr, e);
        }
        return null;
    }

    /**
     * 公钥数字签名进行验证
     *
     * @param original     原文内容
     * @param sign         数字签名
     * @param publicKeyStr 公钥
     * @param algorithm    算法
     * @return 验签结果
     */
    public boolean verifySignByPubKey(String original, String sign, String publicKeyStr, String algorithm) {
        String prefixStr = "【公钥验证数字签名】";
        try {
            byte[] publicKeyByte = Base64.decodeBase64(publicKeyStr);
            if (null == publicKeyByte) {
                log.info("{}失败,publicKeyByte为空", prefixStr);
                return false;
            }
            byte[] originalByte = original.getBytes("UTF-8");
            if (null == originalByte) {
                log.info("{}失败,originalByte为空", prefixStr);
                return false;
            }
            byte[] signByte = Base64.decodeBase64(sign);
            if (null == signByte) {
                log.info("{}失败,signsByte为空", prefixStr);
                return false;
            }
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

            Signature signature = Signature.getInstance(algorithm);
            signature.initVerify(publicKey);
            signature.update(originalByte);
            boolean verify = signature.verify(signByte);
            log.info("{}验签结果:【{}】", prefixStr, verify);
            return verify;
        } catch (Exception e) {
            log.error("{}异常,", prefixStr, e);
        }
        return false;
    }
}

@Data
class KeyPair {
    /**
     * 公钥
     */
    String publicKeyStr;
    /**
     * 私钥
     */
     String privateKeyStr;
    /**
     * 秘钥keySize
     */
     int keySize;
    /**
     * 最大加密明文大小
     */
     int maxEncryptSize;
    /**
     * 最大解密密文大小
     */
    private int maxDecryptSize;
}

2、base64

final class Base64 {
    private static final char[] base64EncodeChars = new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
        'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};

    private static final byte[] base64DecodeChars = new byte[] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1,
        -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};

    public static final String encode(byte[] data) {
        StringBuilder sb = new StringBuilder();
        int r = data.length % 3;
        int len = data.length - r;
        int i = 0;
        int c;
        while (i < len) {
            c = (0x000000ff & data[i++]) << 16 | (0x000000ff & data[i++]) << 8 | (0x000000ff & data[i++]);
            sb.append(base64EncodeChars[c >> 18]);
            sb.append(base64EncodeChars[c >> 12 & 0x3f]);
            sb.append(base64EncodeChars[c >> 6 & 0x3f]);
            sb.append(base64EncodeChars[c & 0x3f]);
        }
        if (r == 1) {
            c = 0x000000ff & data[i++];
            sb.append(base64EncodeChars[c >> 2]);
            sb.append(base64EncodeChars[(c & 0x03) << 4]);
            sb.append("==");
        } else if (r == 2) {
            c = (0x000000ff & data[i++]) << 8 | (0x000000ff & data[i++]);
            sb.append(base64EncodeChars[c >> 10]);
            sb.append(base64EncodeChars[c >> 4 & 0x3f]);
            sb.append(base64EncodeChars[(c & 0x0f) << 2]);
            sb.append("=");
        }
        return sb.toString();
    }

    public static final byte[] decode(String str) {
        byte[] data = str.getBytes();
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;
        int b1, b2, b3, b4;

        while (i < len) {

            /* b1 */
            do {
                b1 = base64DecodeChars[data[i++]];
            } while (i < len && b1 == -1);
            if (b1 == -1) {
                break;
            }

            /* b2 */
            do {
                b2 = base64DecodeChars[data[i++]];
            } while (i < len && b2 == -1);
            if (b2 == -1) {
                break;
            }
            buf.write((int)((b1 << 2) | ((b2 & 0x30) >>> 4)));

            /* b3 */
            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }
                b3 = base64DecodeChars[b3];
            } while (i < len && b3 == -1);
            if (b3 == -1) {
                break;
            }
            buf.write((int)(((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

            /* b4 */
            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }
                b4 = base64DecodeChars[b4];
            } while (i < len && b4 == -1);
            if (b4 == -1) {
                break;
            }
            buf.write((int)(((b3 & 0x03) << 6) | b4));
        }
        return buf.toByteArray();
    }
}

3、XmlUtils

@Slf4j
public class XmlUtils {

    public static final XmlMapper xmlMapper;


    static {
        xmlMapper = new XmlMapper();
        SimpleModule module = new SimpleModule();
        xmlMapper.registerModule(module);
        xmlMapper.setDefaultUseWrapper(false);
        //字段为null,自动忽略,不再序列化
        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //XML标签名:使用骆驼命名的属性名,
        xmlMapper.setPropertyNamingStrategy(new UpperCaseSnackNamingStrategy());
        //设置转换模式
        xmlMapper.enable(MapperFeature.USE_STD_BEAN_NAMING);
    }


    public static String toXml(Object object) {
        try {
            return xmlMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("Xml转换失败", e);
            throw new RuntimeException("Xml转换失败", e);
        }
    }


    public static <T> T toObject(String xml, Class<T> c) {
        try {
            return xmlMapper.readValue(xml, c);
        } catch (IOException e) {
            log.error("Xml转换失败", e);
            throw new RuntimeException("Xml转换失败", e);
        }
    }


}

ContactAuthor