文档章节

吐血记录微信小程序授权获取Unionid及linux下使用bouncycastle解密用户数据 遇到的坑

HeyS1
 HeyS1
发布于 2018/04/27 13:10
字数 707
阅读 555
收藏 8

背景

公司小程序上线了,发现系统无法拿到一些用户的UniondID。但是上线前的测试一切都是正常的。

坑1

经排查,发现一些用户通过下面的接口无法得到unionid

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

阅读https://developers.weixin.qq.com/miniprogram/dev/api/uinionID.html 得知,从未在关联公众号或小程序进行授权过的用户,是不会直接返回unionid的。要拿到这些用户的unionid需要以下3个数据

1.https://api.weixin.qq.com/sns/jscode2session返回的session_key

2. wx.getUserInfo且用户同意后返回的encryptedData和iv

使用以下代码可以解密出用户的信息



import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.NoSuchProviderException;
import java.security.Security;


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



public class AES {
    public static boolean initialized = false;

    public static void main(String[] args) throws InvalidAlgorithmParameterException, UnsupportedEncodingException {
        String encryptedData = "";
        String iv = "";
        String sessionKey = "";

        byte[] resultByte = AES.decrypt(Base64.decodeBase64(encryptedData),
                Base64.decodeBase64(sessionKey),
                Base64.decodeBase64(iv));
        System.out.println(new String(resultByte,"utf-8"));
    }

    /**
     * AES解密
     *
     * @param content 密文
     * @return
     * @throws InvalidAlgorithmParameterException
     * @throws NoSuchProviderException
     */
    public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

            Key sKeySpec = new SecretKeySpec(keyByte, "AES");


            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化

            byte[] result = cipher.doFinal(content);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void initialize() {
        if (initialized) return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

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


}  

 

坑2,真正吐血的地方

使用以上的方法在我本机上面进行测试是没问题的,但是将项目部署上Linux上之后又出了一个问题

解密的时候抛异常:

java.security.NoSuchAlgorithmException - Cannot find any provider supporting AES/CBC/PKCS7Padding

我回头看代码,要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现,解密代码中确实也设置了。且本机也是可以解密的,本机和linux上的jdk均是官网下载的1.8版本,为什么Linux上就不行呢

//使用BouncyCastleProvider组件填充
Security.addProvider(new BouncyCastleProvider());

maven中也引用了bouncycastle


        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.59</version>
        </dependency>

 

排除代码问题的话很明显是环境问题了,linux上使用Security.addProvider(new BouncyCastleProvider());  不起效果。。。

 

那没办法了,只能手动改jre。步骤如下

1.把bcprov-jdk15on-1.59.jar 复制到jre目录中的/lib/ext

2.编辑/lib/security/java.security 

....
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC

#在此加上这句代码
security.provider.x=org.bouncycastle.jce.provider.BouncyCastleProvider


.....

3.重启tomcat,解密成功了。。。

 

 

附一份检测是否支持bouncycastle的代码。方法:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.Security;
public class TestB {

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        System.out.println("Attemptingto get a Cipher and encrypt...");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        System.out.println("OK");
    }
}

 

如果想用纯Js解密也是可以的,这里有一篇文章:https://www.cnblogs.com/cai-rd/p/6816849.html

© 著作权归作者所有

HeyS1

HeyS1

粉丝 13
博文 49
码字总数 29804
作品 1
广州
程序员
私信 提问
加载中

评论(11)

HeyS1
HeyS1 博主

引用来自“斑老头”的评论

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

看了你代码,Cipher.getInstance 后面可以加一个参数,指定provider 用bouncycastle的话 后面加字符串"BC"
我的问题是项目打包了bouncycastle的jar,执行Cipher.getInstance("AES/CBC/PKCS7Padding");会报异常
只能在把bouncycastle的jar放入 /jre/lib/ext 才行。

你的意思是无需把jar包放jre,在项目执行Cipher.getInstance("AES/CBC/PKCS7Padding/BC"); 这样就行了吗

不需要改动jdk默认的provider
您的意思是这样吧:Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
我试了下,如果不把bcprov-jdk15on-1.59.jar放进去/jre/lib/ext 里面的话还是不行。

放在项目的lib就行,除非冲突
我用的是spring boot,打包的jar里面BOOT-INF/lib/ 也有bcprov-jdk15on-1.59.jar。然而还是不行 莫名奇妙的
阿诺-舒华-辛力加
阿诺-舒华-辛力加

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

看了你代码,Cipher.getInstance 后面可以加一个参数,指定provider 用bouncycastle的话 后面加字符串"BC"
我的问题是项目打包了bouncycastle的jar,执行Cipher.getInstance("AES/CBC/PKCS7Padding");会报异常
只能在把bouncycastle的jar放入 /jre/lib/ext 才行。

你的意思是无需把jar包放jre,在项目执行Cipher.getInstance("AES/CBC/PKCS7Padding/BC"); 这样就行了吗

不需要改动jdk默认的provider
您的意思是这样吧:Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
我试了下,如果不把bcprov-jdk15on-1.59.jar放进去/jre/lib/ext 里面的话还是不行。

放在项目的lib就行,除非冲突
HeyS1
HeyS1 博主

引用来自“斑老头”的评论

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

看了你代码,Cipher.getInstance 后面可以加一个参数,指定provider 用bouncycastle的话 后面加字符串"BC"
我的问题是项目打包了bouncycastle的jar,执行Cipher.getInstance("AES/CBC/PKCS7Padding");会报异常
只能在把bouncycastle的jar放入 /jre/lib/ext 才行。

你的意思是无需把jar包放jre,在项目执行Cipher.getInstance("AES/CBC/PKCS7Padding/BC"); 这样就行了吗

不需要改动jdk默认的provider
您的意思是这样吧:Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
我试了下,如果不把bcprov-jdk15on-1.59.jar放进去/jre/lib/ext 里面的话还是不行。
宿命
宿命
要学会用轮子解决问题
画面
画面

引用来自“j4love”的评论

windows 和 linux 上运行效果不一致的坑太多了。。。
所以我在Ubuntu 和mac下开发
HeyS1
HeyS1 博主

引用来自“j4love”的评论

windows 和 linux 上运行效果不一致的坑太多了。。。
😭 对
阿诺-舒华-辛力加
阿诺-舒华-辛力加

引用来自“HeyS1”的评论

引用来自“斑老头”的评论

看了你代码,Cipher.getInstance 后面可以加一个参数,指定provider 用bouncycastle的话 后面加字符串"BC"
我的问题是项目打包了bouncycastle的jar,执行Cipher.getInstance("AES/CBC/PKCS7Padding");会报异常
只能在把bouncycastle的jar放入 /jre/lib/ext 才行。

你的意思是无需把jar包放jre,在项目执行Cipher.getInstance("AES/CBC/PKCS7Padding/BC"); 这样就行了吗

不需要改动jdk默认的provider
阿诺-舒华-辛力加
阿诺-舒华-辛力加
BC独立一个参数
BryceLoski
BryceLoski
windows 和 linux 上运行效果不一致的坑太多了。。。
HeyS1
HeyS1 博主

引用来自“斑老头”的评论

看了你代码,Cipher.getInstance 后面可以加一个参数,指定provider 用bouncycastle的话 后面加字符串"BC"
我的问题是项目打包了bouncycastle的jar,执行Cipher.getInstance("AES/CBC/PKCS7Padding");会报异常
只能在把bouncycastle的jar放入 /jre/lib/ext 才行。

你的意思是无需把jar包放jre,在项目执行Cipher.getInstance("AES/CBC/PKCS7Padding/BC"); 这样就行了吗
Android RSA数据加密与Java服务端RSA私钥解密出错问题

出错描述:服务RSA解密抛出javax.crypto.BadPaddingException: Decryption error 2.出错原因:Android系统使用的虚拟机(dalvik)跟SUN标准JDK是有所区别的,其中他们默认的RSA实现就不同。即...

李云风
2017/06/03
0
0
javax.crypto.BadPaddingException: Blocktype mis...

错误:javax.crypto.BadPaddingException: Blocktype mismatch 1.最近做RSA加密用于增强android客户机与服务器(JavaEE)数据传输的安全性。发现在andorid上生成的(密钥对由服务器在windows下...

cwalet
2011/11/23
0
3
使用Hutools的对称加密时出现的一个问题

首先 这不是Hutools的一个bug 而是pdfbox-app这个组件的bug 在2.0.0版本的pdfbox-app jar包中 集成了一个叫 bouncycastle的加密工具包(貌似是个jdk级别的jar)的源代码,pdfbox直接将其源码都写...

娑婆丶
05/17
0
0
Java加密解密(二) Base64编码

Base64的由来 Base64最早用于解决电子邮件传输问题。由于“历史问题”,早期的电子邮件网关只允许传输ASCII(二进制为00000000-01111111)字符,如果有非ASCII字符经过这种网关时, 字符的二进...

pseudo
2015/06/12
0
0
openfire 二次开发打包

最近在研究openfire,在最后打包发布的时候遇到找不到org/bouncycastle这个包,但我的项目里确实是导入了这个jar文件的,膜拜大神解救...

Junker522
2014/07/16
380
0

没有更多内容

加载失败,请刷新页面

加载更多

北斗三号IGSO-2卫星发射成功!

6月25日,中国航天科技集团官方公众号宣布,北斗三号IGSO-2卫星发射成功! 航天科技集团表示,6月25日2点09分,我国在西昌卫星发射中心用长征三号乙运载火箭成功将北斗三号第2颗倾斜地球同步...

linuxCool
27分钟前
3
0
阿里java开发规约的Idea插件安装(英文)

Idea Plugin Prepare Project JDK: 1.7+ Gradle: 3.0+(Require JDK1.8+ for gradle) Build cd p3c-ideagradle clean buildPlugin Run plugin cd p3c-ideagradle runIde# run speci......

Airship
37分钟前
1
0
很多人转行做程序员选择web前端学习,前端简单在哪里?

不管你是工人阶层还是服务行业,是否想过转行IT,转行IT后肯定会选择一门编程语言进行深入学习,很多转行的人基础都不是太好,不是科班出身,甚至有的是专科乃至中专,前端的HTML和CSS相对其...

智云编程
50分钟前
2
0
一文读懂内网、公网和NAT

我们做弱电监控系统的时候,都避免不了要跟IP地址打交道,比如摄像头、NVR、服务器等这些设备安装好之后,就需要给它们配上IP,那这个IP地址你了解嘛?今天我们就一起来聊聊什么是内网、公网和...

老孟的Linux私房菜
55分钟前
5
0
聊聊dubbo的ExecuteLimitFilter

序 本文主要研究一下dubbo的ExecuteLimitFilter ExecuteLimitFilter dubbo-2.7.2/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java public clas......

go4it
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部