查看: 62|回复: 0

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

[复制链接]

0

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2011-9-26
发表于 2020-7-9 21:02:00 | 显示全部楼层 |阅读模式

近日小程序开发需求--获取用户小程序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 解密相关问题全部解决. 简单记录一下.

 



来源:https://www.cnblogs.com/JackpotHan/p/13276202.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部