IT门户, 中国互联网人工智能物联网行业资讯平台--公众IT
新闻来源:互联网资料整理       发布时间:2023/4/5 12:34:16       共计:4629 浏览

前言:

随着百度小程序的风头正劲,越来越多的站长投入到百度小程序的开发中来,但是开发过程中难免会碰到诸多问题无法自己解决,08-06小编发现百度用户:【shanetianxia】提出了一个关于“解密用户数据的Java示例代码解密错误”的问题,在问题中开发者shanetianxia对该问题做了如下阐述:

问题类型:

  • 问题类型:bug

问题描述:

https://smartprogram.baidu.com/docs/develop/function/login_userdata/ 用java示例解密报错

预期:解密用户数据成功

实际结果:异常出错

js_code: afb2c034b62e2779e09915b20107b0e7NW

encrypted_data:DCHcuoVPkVHbWG2fzXj709SyygYRSMmbpyMnt1Mls86UqrqEeH00gd+yqi73hzdLXsrddtnk6sbdt+Kqt7/9/ckL/deP2uXS5a7x8hkVqxsnf5I02qi936jW6PeXXDKFaJoGu02voDVjALYT39jiQ56Br6QnZe5LHnfigpZaFyXuLa1EkGyQPb7U7uLCDr1jfPz3c/looyMB1ISExwNwzJOduICBX17zOEAYTrq33Ez23Mf1wsZzmbZ2v+3XBiaEf8p24uCEfEQeoTkF0kSsxOA4VYi+1mStii66v9hq/So=

iv:10fecb9e997d9a2191e3dw==

根据code 拿到了正确的 sessionkey和openid {“openid”:”z45QjEcuEsznnXXB1X9IW81mTt”,”session_key”:”10fecb9e997d9a2191e3d1c320b207e2″}

在下面代码:byte[] encrypted = Base64.decodeBase64(text); 解析错误,请帮忙看看,谢谢

提示java.lang.Exception: javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes

/*
 * Copyright (C) 2018 Baidu, Inc. All Rights Reserved.
 */
package com.baidu.utils.secruity;

import java.nio.charset.Charset;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class Demo {
	private static Charset CHARSET = Charset.forName("utf-8");

	/**
	 * 对密文进行解密
	 *
	 * @param text 需要解密的密文
	 *
	 * @return 解密得到的明文
	 *
	 * @throws Exception 异常错误信息
	 */
	public String decrypt(String text, String sessionKey,String ivStr) throws Exception {
		byte[] aesKey = Base64.decodeBase64(sessionKey + "=");
		byte[] original;
		try {
			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
			SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
			byte[] ivBytes = Base64.decodeBase64(ivStr);
			IvParameterSpec iv = new IvParameterSpec(ivBytes);
			cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
			byte[] encrypted = Base64.decodeBase64(text);
			original = cipher.doFinal(encrypted);
		} catch (Exception e) {
			throw new Exception(e);
		}
		String xmlContent;
		String fromClientId;
		try {
			// 去除补位字符
			byte[] bytes = PKCS7Encoder.decode(original);
			// 分离16位随机字符串,网络字节序和ClientId
			byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
			int xmlLength = recoverNetworkBytesOrder(networkOrder);
			if (xmlLength > 65535) {
			    /*
                 * 注意:开发者解密加密数据出现乱码或者偶发OOM,一般是sessionKey过期导致
                 * 
                 * 开发者可以根据实际情况,改变判断值大小
			     */
                throw new RuntimeException("aesKey invalid");
            }
			xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
			fromClientId = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
		} catch (Exception e) {
			throw new Exception(e);
		}
		return xmlContent;
	}

	public static String getType(Object test) {
		return test.getClass().getName().toString();

	}

	/**
	 * 还原4个字节的网络字节序
	 *
	 * @param orderBytes 字节码
	 *
	 * @return sourceNumber
	 */
	private int recoverNetworkBytesOrder(byte[] orderBytes) {
		int sourceNumber = 0;
		int length = 4;
		int number = 8;
		for (int i = 0; i < length; i++) {
			sourceNumber <<= number;
			sourceNumber |= orderBytes[i] & 0xff;
		}
		return sourceNumber;
	}

	/**
	 * 加密解密demo
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		String dy = "toMIrTrp2WovaM4RUoqsrBX4kR7p5JThrzY8bW4ZTBKm4YPRr0CfxY8ZZFwk0RJIPEVCVNebRuN3h6zOIHrHrjdvz5hcKkRfX3VO4OfoHJ3LiZv5uVRl6056iLBgNm+x2HY6T07A40aKeYJQDT3kmgdaAi3UB7NUlrEFUpAuZ2Tsm5B+bF3lnbmUzhskTCFE";

		String sessionKey = "a28bea08d86e426f8d51e024194eae6f";
		String iv = "a28bea08d86e426f8d51ew==";
		
		Demo demo = new Demo();
		String dd = demo.decrypt(dy, sessionKey, iv);
		System.out.println(dd);
	}
}
class PKCS7Encoder {

	static Charset CHARSET = Charset.forName("utf-8");
	static int BLOCK_SIZE = 32;

	/**
	 * 获得对明文进行补位填充的字节.
	 *
	 * @param count 需要进行填充补位操作的明文字节个数
	 *
	 * @return 补齐用的字节数组
	 */
	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 删除补位字符后的明文
	 */
	static byte[] decode(byte[] decrypted) {
		int pad = (int) decrypted[decrypted.length - 1];
		if (pad < 1 || pad > 32) {
			pad = 0;
		}
		return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
	}

	/**
	 * 将数字转化成ASCII码对应的字符,用于对明文进行补码
	 *
	 * @param a 需要转化的数字
	 *
	 * @return 转化得到的字符
	 */
	static char chr(int a) {
		byte target = (byte) (a & 0xFF);
		return (char) target;
	}

}

注:以上是百度小程序开发者:”shanetianxia”对于本问题的一些阐述,这里做一个引用,我们将实时关注百度小程序助手对该问题提出的解决方案。

解决方案:

【08-09】百度官方对用户shanetianxia提出的解密用户数据的Java示例代码解密错误给予如下回复

您好,解密用户数据的Java示例代码解密错误的问题,请您这边检查下解密时候输入的数据是否正确,是否有多加空格之类的错误,如果检查没有输入错误请再次反馈谢谢~

结语:

百度智能小程序开源联盟对于整个行业而言是一次机遇,让所有人都有机会享受到小程序所到来的红利。另一方面,对于百度自身而言,智能小程序开源联盟或许是其又一次业绩腾飞的潜在动力

如果您也在使用百度小程序,请关注我们,如果您有关于百度小程序的使用问题请联系我们,或者去百度小程序平台找官方人员给予解决,相信百度在小程序上的发力会是一个里程碑!

版权说明:
本网站凡注明“公众IT 原创”的皆为本站原创文章,如需转载请注明出处!
本网转载皆注明出处,遵循行业规范,如发现作品内容版权或其它问题的,请与我们联系处理!
您可以扫描右侧微信二维码联系我们。
网站首页 关于我们 联系我们 合作联系 会员说明 新闻投稿 隐私协议 网站地图