签名规则

  1. 排序

排序需要将自己的全部字段进行排序,也就是json的全部key按照abcd的顺序进行排序,以下是java的案例

排序值

{
  "price": 123.123,
  "productCode": "123",
  "productName": "123",
  "quantity": 123
}

排序后的字符串

price&123.123-productCode&123-productName&123-quantity&123

排序方法Java

    public static String getSortMsg(String json){
        Map map = JSON.parseObject(json, Map.class);
        TreeMap<String,Object> treeMap = new TreeMap<>(map);
        StringJoiner joiner = new StringJoiner("-");
        String tlp="{}&{}";
        for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
            joiner.add(StrUtil.format(tlp,entry.getKey(),entry.getValue()));
        }
        return joiner.toString();
    }

每一个键值对中间使用”-“隔开提现出键值对的关系使用&隔开

  1. 签名

签名前我们需要将这个字符串提取成二进制数组中间有汉字的部分使用UTF_8转义一下,并且使用SHA256withRSA算法进行签名,之后得到二进制数组,我们在将这个二进制数组使用Base64压缩一下提取最终的一个字符串密文

Lzem0PhvR8eosobpbEVV7wDyhwA5AHowlcqWKQorMxyIXJXX4mttEfg+gFp1JfnVswiMzTaHUUqJbz0E1GmZ7jhe6mLXihTcdvn2XPqLqOZX1QTaq6f3fGk0W6sXd6mTGpYUowX1XpDkyBfJkX62sakZb6/l1m/vCX5cxlXZ2WWoEZW7ViE3nnmej5Ov/NJ5Fe9CUOinK70wkVVjsnbqHuOcfv62udXFaJd1bxcnEB0H+l6SdmPsiMcXk1bdrkanUzP40Y1+JcF4gkkpWQmhDZ7FEInKYpnFzWt1BRTE4uqQoax/o29bijj9Pb/rqbbOmjoZG1LUKS+DuDJNnzlW6w==

签名方法Java

    // 使用私钥对数据进行签名
    public static byte[] signData(byte[] data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }

传递准备签名的数据,并将平台给开发者的私钥进行签名

  1. 验签

平台给返回数据的时候应该对互传的数据进行校验完整性所以我们需要使用私钥对平台返回的数据进行签名并使用公钥对双方签名后的结果校验一下完整度确保双方没有任何的损失

java验签方法

    public static <T> boolean checkData(String data,T t,String publicKey,String privateKey) throws Exception {
        //数据解压缩
        byte[] decode = Base64.decode(data);
        //加签
        String string = JSON.toJSONString(t);
        //排序
        String msg = RSAUtils.getSortMsg(string);
        //公钥
        PublicKey key = RSAUtils.getPublicKey(publicKey);
        PrivateKey privKey = RSAUtils.getPrivateKey(privateKey);
        //加密
        byte[] bytes = RSAUtils.signData(msg.getBytes(StandardCharsets.UTF_8), privKey);
        //验签
        return RSAUtils.verifySignature(msg.getBytes(StandardCharsets.UTF_8),decode,key);
    }

第一个参数是平台给的签名串

第二个参数是平台返回的结果

第三个是平台给开发者的公钥

第四个是平台给开发者的私钥

辅助材料

java方法

    /**
     * 获取公钥
     */
    public static PublicKey getPublicKey(String publicKeyString) throws Exception {
        byte[] publicKeyBytes = Base64.decode(publicKeyString);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
    }
    /**
     * 获取私钥
     */
    public static PrivateKey getPrivateKey(String privateKeyString) throws Exception {
        byte[] privateKeyBytes = Base64.decode(privateKeyString);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
    }

平台给的密文串可以直接使用方法获取最终的结果

pom包

        <!--工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
        <!--rsa包-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
        <!--json转换-->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.26</version>
        </dependency>

效果展示

image-20230624011020212
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容