微信小程序解密encryptedData报错pad block corrupted

news2024/11/18 16:21:18

在这里插入图片描述前要: 今天调试一下微信授权登录的时候老是第一次报错解密失败pad block corrupted,第二次授权的时候正常,因为第一次已经获取到手机号码!

后端代码:

public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
    try {
      // 加密秘钥
      byte[] keyByte = Base64.decodeBase64(sessionKey);
      // 偏移量
      byte[] ivByte = Base64.decodeBase64(iv);

      // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
      int base = 16;
      if (keyByte.length % base != 0) {
        int groups = keyByte.length / base + 1;
        byte[] temp = new byte[groups * base];
        Arrays.fill(temp, (byte) 0);
        System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
        keyByte = temp;
      }
      // 初始化
      Security.addProvider(new BouncyCastleProvider());
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
      SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
      AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
      parameters.init(new IvParameterSpec(ivByte));
      cipher.init(Cipher.DECRYPT_MODE, spec, parameters); // 初始化
      // 被加密的数据
      byte[] dataByte = Base64.decodeBase64(encryptedData);
      byte[] resultByte = cipher.doFinal(dataByte);
      if (null != resultByte && resultByte.length > 0) {
        String result = new String(resultByte, StandardCharsets.UTF_8);
        log.info("解析微信加密数据==>{}", result);
        return JSONObject.parseObject(result);
      }
    } catch (BadPaddingException e) {
      log.error("解析微信加密数据失败", e);
      throw Exceptions.fail(WECHAT_SESSION_EXPIRED);
    }
    return null;
  }

报错提示:

javax.crypto.BadPaddingException: pad block corrupted
	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.doFinal(Unknown Source)
	at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
	at javax.crypto.Cipher.doFinal(Cipher.java:2088)
	at com.saic.ebiz.service.util.AESUtils.getUserInfo(AESUtils.java:62)
	at com.saic.ebiz.service.util.AESUtils.main(AESUtils.java:96)
Exception in thread "main" java.lang.NullPointerException
	at com.saic.ebiz.service.util.AESUtils.main(AESUtils.java:96)

查找了官方文档原来不是后端代码问题,而是前端代码问题~是微信的bug。不知道有没有解决,但我们自己可以去解决:就是执行顺序问题

原因: uni.login获取session_key,而sessionKey又是解密encryptedData的密钥,所以一旦我们的uni.login在uni.getUserInfo(getPhoneNumber)之后获取,我们存储的sessionKey绝对不是当前获取encryptedData的密钥。

  • 这是因为调用了uni.login后通过code获得的session_key是新的session_key.
  • 所以,在调用uni.login之前获的加密数据不是用新得session_key加密的数据。
  • 在调用uni.login之后获得的加密数据,才是新得的session_key加密的数据。

本来的执行顺序:

  1. 先触发getPhoneNumber获取了手机号的加密数据。
  2. 然后才调用的uni.login获取code。
  3. 再通过code取到用户的session_key 。
  4. 最后再用session_key,手机号的加密数据和向量解密获取手机号。

正确的做法应该是:

  1. 首先调用的uni.login获取code
  2. 再通过code取到用户session_key 。
  3. 再触发getPhoneNumber获取了手机号的加密数据
  4. 最后再用session_key,手机号的加密数据和向量解密获取手机号。

前端保证uni.login获取到的code在getUserInfo(getPhoneNumbe)操作之前。也可以是后端,因为项目是graphql,所以我是前端保证就行。社区还提供另外一种方案Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS7Padding”, “BC”);中BC去掉,不知道行不行!可以试一下!!!

setTab(index) {
	let that = this;
	that.tabIndex = index;
	if (index == 1) {
		uni.login({
			provider: 'weixin',
			success: function(loginRes) {
				that.loginResCode = loginRes.code;
			}
		})
	}
},
getPhoneNumber: function(e) {
	console.log('aaaaaaaa', e)
	if (e.detail.errMsg != "getPhoneNumber:ok") {
		return console.log('用户拒绝请求')
	}
	let self = this;
	let fromData = {
		rawData: e.detail.encryptedData,
		iv: e.detail.iv,
		code: self.loginResCode
	}
	self.$api.wxLogin(fromData).then(res => {
		if (res.data.code == 200) {
			self.$store.commit('changeUserInfo', res.data.data);
			self.$store.commit('changeLoginStatus', true);
			self.$store.commit('changeToken', res.header.accesstoken || res.header.accessToken);
			// uni.navigateBack();
			var pages = getCurrentPages(); // 当前页面
			var beforePage = pages[pages.length - 2]; // 前一个页面
			if (beforePage) {
				uni.navigateBack()
			} else {
				uni.switchTab({
					url: '/pages/home/home'
				})
			}
		} else {
			uni.showModal({
				title: '提示',
				content: res.data.msg,
				showCancel: false,
				success: function(res) {
					if (res.confirm) {
						console.log('用户点击确定');
					} else if (res.cancel) {
						console.log('用户点击取消');
					}
				}
			});
		}
	})
},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149332.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信自动回复软件

软件介绍 软件名称: 微信超级管家 适用平台: windows 是否免费: 完全免费 病毒检测: 火绒安全检测通过 流氓检测: 无广告、无弹窗、无其他流氓行为 软件大小: 183M 这个软件依赖的是本地微信客户端&#x…

C++ 初始化列表详解

目录 1.什么是初始化列表 2.什么时候需要使用初始化列表? 3.初始化列表的效率 4.初始化列表的初始化顺序 1.什么是初始化列表 class A { public:A(int value):m_dada(value){}private:int m_dada; }; 如上图,红色圈起来的部分,就是构造函…

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《5》

在上一篇文章的介绍中,我们知道语义分割可以对图像中的每个像素进行类别预测。这节主要讲关于全卷积网络(Fully Convolutional Network,FCN),实现从图像像素到像素类别的变换。 那这里的卷积神经网络跟以往的有什么不一样的地方吗? 这里的网络是通过转置…

Java中享元模式是什么/享元模式有什么用,编程如何实现,哪里用到了享元模式

继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用! 5.8 享元模式 5.8.1 概述 运用共享技术来有效地支持大量细粒度对象的复用,通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象…

图文并茂strapi 4.5.5自定义搭建指南以及数据库字段名接口返回mapping分析

strapi是什么? 基于Nodejs的开源免费CMS框架 为什么选择它? 基于nodejs,100%JavaScript,上手迅速可轻松创建功能强大且可自定义的API可以使用任何喜欢的数据库 先决条件 首先你的电脑需要具备以下环境,再执行命令…

技术破局:程序员2023为何跳出舒适圈?

1前言今天的冬日暖阳高照,给我羽绒服下的肉身火一般的燥热,给了我一个错觉,以为到了阳春三月。刚刚送完老妈还有老婆孩子回老家,我坐到电脑机器前,准备捋一下思绪,回首2022的生活和工作。 2 2022 回顾今年用…

Linux下C/C++实现cpustat(测量CPU利用率)

在Linux中,cpustat定期转储正在运行的进程的当前CPU利用率统计信息。cpustat已被优化为具有最小的CPU开销,与top相比,通常使用约35%的CPU。cpustat还包括一些简单的统计分析选项,可以帮助描述CPU的加载方式。 cpustat介绍 cpust…

大数据概论

大数据概论大数据概论概念特点(4V)Volume(大量)Velocity(高速)Variety(多样)Value(低价值密度)应用场景发展前景部门间业务流程分析部门组织结构大数据概论 概念 大数据(BigData),指无法在一定时间范围内\textcolor{Red}{无法在一定时间范围内}无法在一定时间范围…

iOS—Effective Objective—C2.0(2)

文章目录对象,消息,运行期理解“属性”概念合成与存取dynamic关键字属性特性原子性读/写权限内存管理语义方法名为什么几乎所有的属性都可以使用nonatomic:要点在对象的内部尽量直接访问实例变量惰性初始化:要点理解“对象同等性”…

2022年度总结——平凡之路

文章目录一、缘起二、回首2022三、展望2023四、结束语我是平凡的人,总要接受普通平凡的自己。一、缘起 我注册CSDN的时间是2021-07-25,这是一个值得纪念的时间。不过那时候的我并没有写博客,只是在CSDN游览一些文章,查看资料&…

一文读懂Java垃圾回收机制及算法原理万字详解

Java垃圾回收机制及算法 文章目录Java垃圾回收机制及算法垃圾回收概述垃圾回收-对象是否已死判断对象是否存活 - 引用计数算法判断对象是否存活-可达性分析算法可达性分析算法JVM之判断对象是否存活再谈引用垃圾收集算法分代收集理论标记-清除算法什么是标记-清除算法?标记-复…

读书:《卡片笔记写作法》

2023年罗胖跨年演讲时提到了一个故事,说Flomo的创始人有3个原则:一不在软件内弹广告,二不做永久会员,三不融资。我就马上试用了一下这款Flomo软件,然后就发现了《卡片笔记写作法》这本书。 这本书的卡片写作法来自于一…

【Qt】QtCreator新建Application项目的6类应用程序的示例

【Qt】QtCreator新建Application项目的6类应用程序的示例1、背景2、Application分类1、背景 操作系统:windows10专业版。 Qt版本:qt-opensource-windows-x86-msvc2013_64-5.7.1.exe 注意:安装了该exe可执行文件,就自动安装了qtcr…

(考研湖科大教书匠计算机网络)第一章概述-第一节:因特网概述

文章目录一:网络、互联网和因特网基本概念二:因特网发展的三个阶段三:ISP和基于ISP的三层结构的因特网(1)ISP(2)基于ISP的三层结构的因特网四:因特网的标准化工作五:因特…

KMP算法--子串查找问题

目录 一.前言 二.KMP算法简介 三.关键概念1:字符串的前后缀 四. 关键概念2:字符串相等前后缀与最长相等前后缀长度 五.关键概念3:Next数组 六.Next数组在算法中的应用: 七.模式串Next数组的构建 先膜拜一下三位神仙&#x…

面试前端数组去重,我会问这3个小问题

关于数组去重,已经是一个老生常谈的问题了,网络上已经有N篇关于数组去重的讲解了,所以,凡是能看见这篇博客的,我们都是有缘人,希望2023年你可以乘风破浪,职击沧海。而一般面试的时候&#xff0c…

MySQL调优-高性能业务表结构设计

目录 前言记录: 数据库表设计 范式设计 什么是范式? 数据库设计的第一范式 数据库设计的第二范式 数据库设计的第三范式 范式说明 反范式设计 什么叫反范式化设计? 反范式设计-商品信息 范式化和反范式总结 实际工作中的反范式实…

C++ stack和queue

1. stack的介绍和使用1.1 stack的介绍1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器&…

基于深度学习的自然语言处理

1、什么是自然语言处理? 自然语言处理(Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门融语言学、计算机科学、…

【信号与系统】预习笔记(每日更新ing)

2023.1.8已打卡 信号与系统(一)信号与系统概述1.0 常见三角公式1.1 信号与系统1.2 信号的表述、分类1.3 信号的运算(二)连续系统的时域分析(三)离散系统的时域分析(四)傅里叶变换与频…