微信小程序數據解密(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM