JAVA解密微信小程式使用者資訊encryptedData方案

github_OceanYi發表於2020-04-04

首先我相信當各位大佬看到這個文章的時候,應該看過很多關於java解密微信小程式使用者資訊的方案了。

但是總會遇到一些問題,比如程式碼複製過來,匯入正確的包也會遇到的問題拉~,這裡我就釋出一個自己遇到的問題,希望能幫助後面的人,這個坑很大哦~

廢話不多說,貼程式碼

這個AES解密工具包,放在Util包下

import java.security.AlgorithmParameters;
import java.security.Key;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Decoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public final class AES {

	public static final String KEY_ALGORITHM = "AES";
	public static final String CIPHER_ALGORITHM = "AES/CBC/NoPadding";

	// 生成金鑰
	public static byte[] generateKey() throws Exception {
		KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
		keyGenerator.init(128);
		SecretKey key = keyGenerator.generateKey();
		return key.getEncoded();
	}

	// 生成iv
	public static AlgorithmParameters generateIV() throws Exception {
		// iv 為一個 16 位元組的陣列,這裡採用和 iOS 端一樣的構造方法,資料全為0
		byte[] iv = new byte[16];
		Arrays.fill(iv, (byte) 0x00);

		return generateIV(iv);
	}

	// 生成iv
	public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
		AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_ALGORITHM);
		params.init(new IvParameterSpec(iv));
		return params;
	}

	// 轉化成JAVA的金鑰格式
	public static Key convertToKey(byte[] keyBytes) throws Exception {
		SecretKey secretKey = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
		return secretKey;
	}

	// 加密
	public static byte[] encrypt(byte[] data, byte[] keyBytes, AlgorithmParameters iv) throws Exception {
		// 轉化為金鑰
		Key key = convertToKey(keyBytes);
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		// 設定為加密模式
		cipher.init(Cipher.ENCRYPT_MODE, key, iv);
		return cipher.doFinal(data);
	}

	// 解密
	public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception {
		Key key = convertToKey(keyBytes);
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		// 設定為解密模式
		cipher.init(Cipher.DECRYPT_MODE, key, iv);
		return cipher.doFinal(encryptedData);
	}
}

呼叫方式

Decoder decoder = Base64.getDecoder();
		try {
			byte[] result = AES.decrypt(decoder.decode(encryptedData), decoder.decode(session_key),
					AES.generateIV(decoder.decode(iv)));
			String s=StringUtils.toString(result,"UTF-8");
			System.out.println(s);
		} catch (Exception e) {
			e.printStackTrace();
			
		}

那麼當你走到這一步的時候,你很可能遇到的問題:


java.lang.IllegalArgumentException: Illegal base64 character 20

沒錯就是這個異常,問題的原因是因為 encryptedData 密文在進行http傳輸的時候按照W3C的規範給你把其中的+號變成了空格,

例如這個密文

TuuTLtXibxWa1L8uTBQciO4hah/LwFh95Ip8I/tNo1FbDlEbIk0USXr4d3mm91XaVZ7+CynILJcCih5bbSEcFJKQiua2yn48Fdu4WiXRKwU0RD49aldpZ9SGSU+AtzAsD3KbyUiStdfwaWhkeX37qnQeXucV0/irhZBkwFqg5EXHDvq+cOldXl6pVJt2oO3/4c0kBECfGavQ717QXKJLqnEaoDfh8Qfce678CeDwa6wYnR46Xu6fnBx5t0K53f5qKL9hZZtHlr28aFZ6kYVq06mEP+97E4HxDBZjU9ZuDZjKyIpcajA2GUKCgzqqwMQG7iYfl6br7Q2cjh6UFGs5p08Ofr/p9TPNPXJm0ErAfVghu5UuyVxGRerW2O9aEQjKdlUGztlGqMZVriky6TjpzVz/Uy7m4++B7Pd4cvWkYaZGDWb+MdwMP+KYXLGVwrQyhPuAcppQqZ9G92qeMZl4uMfFLwFO3B/+7ShE0Ulpies=

然後通過DEBUG檢視後臺接收到的密文

TuuTLtXibxWa1L8uTBQciO4hah/LwFh95Ip8I/tNo1FbDlEbIk0USXr4d3mm91XaVZ7 CynILJcCih5bbSEcFJKQiua2yn48Fdu4WiXRKwU0RD49aldpZ9SGSU AtzAsD3KbyUiStdfwaWhkeX37qnQeXucV0/irhZBkwFqg5EXHDvq cOldXl6pVJt2oO3/4c0kBECfGavQ717QXKJLqnEaoDfh8Qfce678CeDwa6wYnR46Xu6fnBx5t0K53f5qKL9hZZtHlr28aFZ6kYVq06mEP 97E4HxDBZjU9ZuDZjKyIpcajA2GUKCgzqqwMQG7iYfl6br7Q2cjh6UFGs5p08Ofr/p9TPNPXJm0ErAfVghu5UuyVxGRerW2O9aEQjKdlUGztlGqMZVriky6TjpzVz/Uy7m4  B7Pd4cvWkYaZGDWb MdwMP KYXLGVwrQyhPuAcppQqZ9G92qeMZl4uMfFLwFO3B/ 7ShE0Ulpies=

兩個仔細對比一下,然後你感到驚喜了嗎?特瞄的居然是把+號改成了空格。

所以各位在前臺傳輸資料的時候一定要注意,可以把+號改成 %2B 這樣後臺在接收密文的時候,按照規範來講%2B會自動變成+號了。

希望各位不要入坑了~~我也被坑了2天才反應過來。。有問題留言哦 ~ 

相關文章