Fork me on GitHub

java 小程序开发PKCS7Padding 解密相关问题

近日小程序开发需求--获取用户小程序unionid(UnionID获取途径),考虑到用户非必须关注公众号,只能通过wx.getUserInfo从解密数据中获取 UnionID ,api返回的数据encryptedData 的解密算法要求为: AES-128-CBC,数据采用PKCS#7填充。

但是,在解密时出现了异常(使用的java 11)

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

查询了一波,大致的问题是java不支持PKCS7Padding,只支持PKCS5Padding,Java的默认crypto类,AES算法使用PKCS5Padding 填充模式,而iOS使用PKCS7Padding填充模式。

PKCS7Padding VS PKCS5Padding 的区别也很简单 PKCS5Padding 的blocksize为8字节,而PKCS5Padding 的blocksize范围 1~255字节. 参考 PKCS5Padding 和 PKCS7Padding

于是自以然的觉得把PKCS7Padding换成PKCS5Padding问题不久解决了嘛? 然后结果却啪啪啪的打脸,这条道走不了,只能想办法让java兼容PKCS7Padding.

借助强大的Google了解到要实现java支持PKCS7Padding就必须要借助第三方组件来实现--bouncycastle,在MVN仓库查询后发现相关的依赖有两个

复制代码
<dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk16</artifactId>
      <version>1.46</version>
</dependency> 
//以及
<dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-ext-jdk16</artifactId>
      <version>1.45</version>
    </dependency>
复制代码

有点懵逼啊,那么我该选择哪一个呢?把两个jar包下载下来后反编译看了下,惊讶的发现bcprov-jdk16的代码是bcprov-ext-jdk16的子集,于是依然选择了下面的依赖.

so easy 轻轻松松解决问题,程序跑起来,然而,又出现了一个新的错误

javax.crypto.BadPaddingException: pad block corrupted

于是又google了一波,stackoverflow上一位大佬的回答引起了我的注意,参见-stackoverflow,以下是大佬的回答.

 

 

 意思很明显,需要定义一个provider,于是我定义了一个静态方法

static {
    Security.addProvider(new BouncyCastleProvider());
}

终于成功解密了.

后来查看源码,发现Cipher有一个getInstance(String transformation, String provider)方法,源码如下

复制代码
    public static final Cipher getInstance(String transformation, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
        if (transformation != null && !transformation.equals("")) {
            if (provider != null && provider.length() != 0) {
                Provider p = Security.getProvider(provider);
                if (p == null) {
                    throw new NoSuchProviderException("No such provider: " + provider);
                } else {
                    return getInstance(transformation, p);
                }
            } else {
                throw new IllegalArgumentException("Missing provider");
            }
        } else {
            throw new NoSuchAlgorithmException("Null or empty transformation");
        }
    }
复制代码

于是,又在网上搜索了Cipher provider相关知识,发现一个很有趣的provider-"BC",使用方法如下

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");

启动,测试,完美,一次点亮.

自此.java 小程序开发PKCS7Padding 解密相关问题全部解决. 简单记录一下.

 

作者:JackpotHan
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

posted @   JackpotHan  阅读(1351)  评论(2编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示