Java WeChat applet steps encryptedData and open data decryption

premise:

Three parameters,
1.sessionKey (available when you take openId)
2.encryptedData (provided by the front end)
3.iv (provided by the front end)
One class and one method.

1. Class:

 
import java.nio.charset.Charset;
import java.util.Arrays;
 
 
/**
 * 微信小程序加解密
 * @author liuyazhuang
 *
 */
public class WxPKCS7Encoder {
    
    
    private static final Charset CHARSET = Charset.forName("utf-8");
    private static final int BLOCK_SIZE = 32;
 
    /**
     * 获得对明文进行补位填充的字节.
     *
     * @param count
     *            需要进行填充补位操作的明文字节个数
     * @return 补齐用的字节数组
     */
    public static byte[] encode(int count) {
    
    
        // 计算需要填充的位数
        int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
        if (amountToPad == 0) {
    
    
            amountToPad = BLOCK_SIZE;
        }
        // 获得补位所用的字符
        char padChr = chr(amountToPad);
        String tmp = new String();
        for (int index = 0; index < amountToPad; index++) {
    
    
            tmp += padChr;
        }
        return tmp.getBytes(CHARSET);
    }
 
    /**
     * 删除解密后明文的补位字符
     *
     * @param decrypted
     *            解密后的明文
     * @return 删除补位字符后的明文
     */
    public static byte[] decode(byte[] decrypted) {
    
    
        int pad = decrypted[decrypted.length - 1];
        if (pad < 1 || pad > 32) {
    
    
            pad = 0;
        }
        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
    }
 
    /**
     * 将数字转化成ASCII码对应的字符,用于对明文进行补码
     *
     * @param a
     *            需要转化的数字
     * @return 转化得到的字符
     */
    public static char chr(int a) {
    
    
        byte target = (byte) (a & 0xFF);
        return (char) target;
    }
}

2. Method:

import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.InvalidParameterSpecException;
import java.util.HashMap;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;


import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AesCbcUtil {
    
    

	  static {
    
    
	        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
	        Security.addProvider(new BouncyCastleProvider());
	    }
	 
	    /**
	     * AES解密
	     *
	     * @param data           //密文,被加密的数据
	     * @param key            //秘钥
	     * @param iv             //偏移量
	     * @param encodingFormat //解密后的结果需要进行的编码
		 * @param type //0 是其他 1是微信步数
	     * @return
	     * @throws Exception
	     */
	    public static String decrypt(String data, String key, String iv, String encodingFormat,Integer type) throws Exception {
    
    
//	        initialize();
	    	if(StringUtils.isEmpty(data)||StringUtils.isEmpty(key)||StringUtils.isEmpty(iv))
	    		throw new SkyParamNullException("小程序获取用户信息参数不能为空");
	        //被加密的数据
	        byte[] dataByte = Base64.decodeBase64(data);
	        //加密秘钥
	        byte[] keyByte = Base64.decodeBase64(key);
	        //偏移量
	        byte[] ivByte = Base64.decodeBase64(iv);
	 
	 
	        try {
    
    
	            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
	 
	            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
	 
	            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
	            parameters.init(new IvParameterSpec(ivByte));
	 
	            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
	 
	            byte[] resultByte = cipher.doFinal(dataByte);
	            if (null != resultByte && resultByte.length > 0) {
    
    
	            	if (type==1){
    
    
						return  new String(WxPKCS7Encoder.decode(resultByte));

					}else {
    
    
						return  new String(resultByte, encodingFormat);

					}


	            }
	            return null;
	        } catch (NoSuchAlgorithmException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错1{}",e.getMessage());
	        } catch (NoSuchPaddingException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错2{}",e.getMessage());
	        } catch (InvalidParameterSpecException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错3{}",e.getMessage());
	        } catch (InvalidKeyException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错4{}",e.getMessage());
	        } catch (InvalidAlgorithmParameterException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错5{}",e.getMessage());
	        } catch (IllegalBlockSizeException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错6{}",e.getMessage());
	        } catch (BadPaddingException e) {
    
    
	            e.printStackTrace();
	            log.error("小程序解析出错7{}",e.getMessage());
	        }
			catch (UnsupportedEncodingException e) {
    
    
				e.printStackTrace();
				log.error("小程序解析出错8{}",e.getMessage());
			}
	        return null;
	    }
}

achieve

@ApiOperation(value = "wx步数解密")
    @PostMapping(value = "/decode")
    public ResultModel<Object> questionList(@RequestBody WxSportParam param) throws Exception {
    
    
        HashMap<String, Object> map = wxXiaoChenXuUtil.getWxOpenId(//这个方法网上很多,没有就用binarywang的
        	param.getCode()//前端提供的code
        		,sysProperties.getWxAppId()//appID
        			,sysProperties.getWxAppSecret());//secret
        String sessionKey = map.get("session_key").toString();
        String result = AesCbcUtil.decrypt(param.getData(), sessionKey,param.getIv(), "UTF-8",1);

        return ResultModel.success(result);
    }

Data coming out:

{ “stepInfoList”: [
{
“timestamp”: 1445866601,
“step”: 100
},
{
“timestamp”: 1445876601,
“step”: 120
} ] }、

tips: If you are parsing user information, use the same method, pass 0 in the parameter type in decrypt. The difference between the two is that the byte decode method is different.

Please like and follow, if you don’t understand, you can comment or ask by private message

Guess you like

Origin blog.csdn.net/plqaxx/article/details/108799081