1. 程式人生 > >微信小程式開放資料解密 AES-128-CBC 解密(Java版本)

微信小程式開放資料解密 AES-128-CBC 解密(Java版本)

最近朋友在弄微信小程式開發,需要跟微信服務端互動,微信敏感資料都有加密返回,需要在服務端接收進行解密後再返回給客戶端小程式,今天就通過Java進行資料的解密,以下展示是Java程式碼
如果你使用的C#,請訪問這個地址(C#版本) https://blog.csdn.net/jasonsong2008/article/details/83586119
我們先來看一下微信官方的說明文件,以下直接文件來自微信小程式官方:

加密資料解密演算法

介面如果涉及敏感資料(如wx.getUserInfo當中的 openId 和 unionId),介面的明文內容將不包含這些敏感資料。開發者如需要獲取敏感資料,需要對介面返回的加密資料(encryptedData)

 進行對稱解密。 解密演算法如下:

  1. 對稱解密使用的演算法為 AES-128-CBC,資料採用PKCS#7填充。
  2. 對稱解密的目標密文為 Base64_Decode(encryptedData)。
  3. 對稱解密祕鑰 aeskey = Base64_Decode(session_key), aeskey 是16位元組。
  4. 對稱解密演算法初始向量 為Base64_Decode(iv),其中iv由資料介面返回。


通過微信文件的說明編寫了如下解密方法供大家使用


import org.apache.shiro.codec.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * AES解密(JAVA版本)
 * Add by 成長的小豬(Jason.Song) on 2018/10/26
 * http://blog.csdn.net/jasonsong2008
 */
public class AesHelper {

    /**
     * 微信小程式 開放資料解密
     * AES解密(Base64)
     * Add by 成長的小豬(Jason.Song) on 2018/10/26
     * @param encryptedData 已加密的資料
     * @param sessionKey    解密金鑰
     * @param iv            IV偏移量
     * @return
     * @throws Exception
     */
    public static String decryptForWeChatApplet(String encryptedData, String sessionKey, String iv) throws Exception {
        byte[] decryptBytes = Base64.decode(encryptedData);
        byte[] keyBytes = Base64.decode(sessionKey);
        byte[] ivBytes = Base64.decode(iv);

        return new String(decryptByAesBytes(decryptBytes, keyBytes, ivBytes));
    }

    /**
     * AES解密
     * Add by 成長的小豬(Jason.Song) on 2018/10/26
     * @param decryptedBytes    待解密的位元組陣列
     * @param keyBytes          解密金鑰位元組陣列
     * @param ivBytes           IV初始化向量位元組陣列
     * @return
     * @throws Exception
     */
    public static byte[] decryptByAesBytes(byte[] decryptedBytes, byte[] keyBytes, byte[] ivBytes) throws Exception {
        SecretKeySpec  key = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        byte[] outputBytes = cipher.doFinal(decryptedBytes);;
        return outputBytes;
    }

}


下面是通過以上解密方法進行測試,大家根據自己的情況進行相應呼叫即可


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

/**
 * 文章來源於成長的小豬
 * http://blog.csdn.net/jasonsong2008
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/applicationContext.xml"})
public class AesHelperTest {

    @Test
    public void decryptForWeChatApplet() {
        //微信小程式返回的加密資料
        String encryptedData =
                "tsyLVebikY1aLQ0aNpg10NHxCTV2Ar+FJHUZdwIchBXFbJU7hXyf5gbDibaLU+lT6bzzut/nVymRFp/U8MrF0c8yOCFbnK5aevyearR7vopeel2y929weVA/s16shDPnRMkIn9xiMfVY3LDmuptnBpy1loZfSW2CPfXFuKXQf2z+Kiruynve1cq2mnzAadNaw3/g/tjHRPzxBnTkMsu8sQ==";
        //會話金鑰
        String sessionKey = "vBwBswWRVmD0WQvRbdbMZg==";
        //解密演算法初始向量
        String iv = "8IzE0WUF0j5hXy4oIKuLHA==";


        try {
            String result = AesHelper.decryptForWeChatApplet(encryptedData, sessionKey, iv);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}