微信小程序数据解密(Java)

pom 依赖

非必须,hutool 是为了使用 AES 工具类,bcprov 是为了使用 PKCS7Padding,都可以自己实现,这里为了方便。

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool-all.version}</version>
</dependency>
<dependency><!--AES/CBC/PKCS7Padding-->
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15to18</artifactId>
    <version>${bcprov-jdk15to18.version}</version>
</dependency>

 

工具类

import cn.hutool.json.JSONUtil;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;

public class WeChatUtil {
    static {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 初始化密钥
    }

    /**
     * 解密数据
     */
    public static String decrypt(String appId, String sessionKey, String encryptedData, String iv) throws
            InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException,
            NoSuchAlgorithmException, InvalidParameterSpecException, BadPaddingException, InvalidKeyException {
        // AES aes = new AES("CBC", "PKCS7Padding", Base64.decode(sessionKey), Base64.decode(iv));
        // byte[] resultByte = aes.decrypt(Base64.decode(encryptedData));
        byte[] resultByte = wxDecrypt(encryptedData, sessionKey, iv);
        String result = new String(resultByte, StandardCharsets.UTF_8);
        // 是否与当前 appid 相同
        if (!appId.equals(JSONUtil.parseObj(result).getJSONObject("watermark").getStr("appid"))) {
            result = "";
        }
        return result;
    }

    public static final String KEY_NAME = "AES"; // 算法名
    // 加解密算法/模式/填充方式,ECB 模式只用密钥即可对数据进行加密解密,CBC 模式需要添加一个 iv
    public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    /**
     * 接口如果涉及敏感数据(如 wx.getUserInfo 当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。
     * 开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。 解密算法如下:
     * * 对称解密使用的算法为 AES-128-CBC,数据采用 PKCS#7 填充。
     * * 对称解密的目标密文为 Base64_Decode(encryptedData)。
     * * 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
     * * 对称解密算法初始向量 为 Base64_Decode(iv),其中 iv 由数据接口返回。
     *
     * @param encrypted  目标密文
     * @param sessionKey 会话ID
     * @param iv         加密算法的初始向量
     */
    public static byte[] wxDecrypt(String encrypted, String sessionKey, String iv) throws NoSuchAlgorithmException,
            InvalidParameterSpecException, NoSuchPaddingException, BadPaddingException, InvalidKeyException,
            IllegalBlockSizeException, InvalidAlgorithmParameterException {
        KeyGenerator.getInstance(KEY_NAME).init(128);

        // 生成 iv
        // iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为 0
        // Arrays.fill(iv, (byte) 0x00);
        AlgorithmParameters ivj = AlgorithmParameters.getInstance(KEY_NAME);
        ivj.init(new IvParameterSpec(java.util.Base64.getDecoder().decode(iv)));

        // 生成解密
        Key key = new SecretKeySpec(java.util.Base64.getDecoder().decode(sessionKey), KEY_NAME);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key, ivj); // 设置为解密模式
        return cipher.doFinal(java.util.Base64.getDecoder().decode(encrypted));
    }
}

测试

public static void main(String[] args) {
    String appId = "wx4f4bc4dec97d474b";
    String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJl" +
            "AC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW" +
            "1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs" +
            "8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2" +
            "SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COw" +
            "fneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==";
    String sessionKey = "tiihtNczf5v6AKRyjwEUhQ==";
    String iv = "r7BXXKkLb8qrSNn05n0qiA==";
    System.out.println(WeChatUtil.decrypt(appId, sessionKey, encryptedData, iv));
}

 


https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html#加密数据解密算法

http://tool.chacuo.net/cryptaes

https://www.hutool.cn/docs/#/crypto/对称加密-SymmetricCrypto

posted @ 2021-06-21 17:24  江湖小小白  阅读(1089)  评论(0编辑  收藏  举报