zoukankan      html  css  js  c++  java
  • 支付宝敏感信息解密

      支付宝官方解密文档:https://docs.alipay.com/mini/introduce/aes

    String response = "小程序前端提交的";
    
    //1. 获取验签和解密所需要的参数
    Map<String, String> openapiResult = JSON.parseObject(response,
                new TypeReference<Map<String, String>>() {
                }, Feature.OrderedField);
    String signType = StringUtil.defaultIfBlank(openapiResult.get("signType"), "RSA2");
    String charset = StringUtil.defaultIfBlank(openapiResult.get("charset"), "UTF-8");
    String encryptType = StringUtil.defaultIfBlank(openapiResult.get("encryptType"), "AES");
    String sign = openapiResult.get("sign");
    //如果密文的
    boolean isDataEncrypted = !content.startsWith("{");
    boolean signCheckPass = false;
    
    //2. 验签
    String signContent = content;
    String signVeriKey = "你的小程序对应的支付宝公钥(为扩展考虑建议用appId+signType做密钥存储隔离)";
    String encryptType = "你的小程序对应的加解密密钥(为扩展考虑建议用appId+encryptType做密钥存储隔离)"
    //如果是加密的报文则需要在密文的前后添加双引号
    if (isDataEncrypted) {
        signContent = """ + signContent + """;
    }
    try {
        signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
    } catch (AlipayApiException e) {
        //验签异常, 日志
    }
    if(!signCheckPass) {
        //验签不通过(异常或者报文被篡改),终止流程(不需要做解密)
        throw new Exception("验签失败");
    }
    
    //3. 解密
    String plainData = null;
    if (isDataEncrypted) {
        try {
            AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
        } catch (AlipayApiException e) {
            //加密异常, 日志
           throw new Exception("解密异常");
        }
    } else {
        plainData = content;
    }

      虽然是参考代码,但个人感觉太随意了。做了一些简单的修改,编译和逻辑都没有问题了。

    /**
     * 敏感信息解密
     */
    @PostMapping(value = "/decryptor", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public RestResponse decryptor(@RequestBody String encryptContent) {
        RestResponse restResponse = new RestResponse();
    
        try {
            Map<String, String> openapiResult = JSON.parseObject(encryptContent,
                    new TypeReference<Map<String, String>>() {
                    },
                    Feature.OrderedField);
            String signType = StringUtils.defaultIfBlank(openapiResult.get("sign_type"), "RSA2");
            String charset = StringUtils.defaultIfBlank(openapiResult.get("charset"), "UTF-8");
            String encryptType = StringUtils.defaultIfBlank(openapiResult.get("encrypt_type"), "AES");
            String sign = openapiResult.get("sign");
            String content = openapiResult.get("response");
    
            LOGGER.info(String.format("准备验签和解密,sign=[%s], signType=[%s], encryptType=[%s], encryptContent=[%s]", sign, signType, encryptType, encryptContent));
    
            //如果密文的
            boolean isDataEncrypted = !content.startsWith("{");
            boolean signCheckPass;
    
            //2. 验签
            String signContent = content;
            //支付宝应用公钥
            String signVeriKey = ALIPAY_APPLET_PUBLIC_SECRET;
    
            //如果是加密的报文则需要在密文的前后添加双引号
            if (isDataEncrypted) {
                signContent = """ + signContent + """;
            }
            try {
                signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
            } catch (AlipayApiException e) {
                //验签异常, 日志
                LOGGER.error("验签异常,encryptContent=" + encryptContent, e);
                restResponse.setRestStatus(RestStatus.FAIL_100021);
                return restResponse;
            }
            if (!signCheckPass) {
                //验签不通过(异常或者报文被篡改),终止流程(不需要做解密)
                LOGGER.error("验签失败,encryptContent=" + encryptContent);
                restResponse.setRestStatus(RestStatus.FAIL_100021);
                return restResponse;
            }
    
            //支付宝小程序AES秘钥
            String encryptKey = ALIPAY_APPLET_AES_SECRET;
    
            //3. 解密
            String plainData;
            if (isDataEncrypted) {
                try {
                    plainData = AlipayEncrypt.decryptContent(content, encryptType, encryptKey, charset);
                } catch (AlipayApiException e) {
                    //解密异常, 日志
                    LOGGER.error("解密异常,encryptContent=" + encryptContent, e);
                    restResponse.setRestStatus(RestStatus.FAIL_100021);
                    return restResponse;
                }
            } else {
                plainData = content;
            }
            restResponse.setData(plainData);
            restResponse.setRestStatus(RestStatus.SUCCESS);
        } catch (Exception e) {
            LOGGER.error("验签解密异常,encryptContent=" + encryptContent, e);
            restResponse.setRestStatus(RestStatus.FAIL_100021);
        }
        return restResponse;
    }

      解密报文示例。

    {"response":"+A9tOP5n2uUJaQRJOxLj6+rR0yooZWC/SQhcHDJ1BbLKkEA+hUr2ah3KOzL/+RwuyO4mH5ZSeFRpOrNPyTac/w==","sign":"V9OSmt5iTWr2tqpW/p6jjTcvpdiva8WxjnC7nvqyHg5eT181/61wcKysoTgLuNfFd2XbKvULHxi9mZDIh3OAR1PDIs0aOEhzimORbf9wBofoWfGKlq2iwWKeSSnxyS0W4maF0VrS0kNySsx5ta7eBGtSlGozOOR6R7oeygNdd43jOo33pZmUA0fo6DSHZH5lblrwqL4t0UcLSFLx1kqVNi28BsRQA5OxqkUp78PsxPGdps0CI9gQcAHfCKbKYk6F1bimw+R3k7ympm2esdEfl59Yym7lpz7gtOkGuNDjY3Y/urrYwGt7Kq/EX5BcIYA4DCS4nPkyb3wPRkH1VKBE+g=="}
    或者

    { "response": "hvDOnibG0DPcOFPNubK3DEfLQGL4=", "sign": "OIwk7zfZMp5GX78Ow==", "sign_type": "RSA2", "encrypt_type": "AES", "charset": "UTF-8" }
  • 相关阅读:
    Mac Python相关配置操作汇总
    暑假算法练习Day2
    暑假算法练习Day1
    《Min_25筛》
    《Yuchang and Zixiang’s stones》
    《Codeforces Round #732 (Div. 1)》
    《P7842 「PMOI-4」可怜的团主》
    《Codeforces Round #739 (Div. 3)》
    《斜率dp》
    《凸包》
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/10184418.html
Copyright © 2011-2022 走看看