• 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 解密相关问题全部解决. 简单记录一下.

  • 相关阅读:
    10003 Cutting Sticks(区间dp)
    Cocos2d-x init() 和 onEnter() 区别
    HDU1181【有向图的传递闭包】
    空间参考系统与WKT解析
    面试经典-分金条
    uvalive 3971
    lua学习:使用Lua处理游戏数据
    面试经典--两个房间 每间房间三盏灯
    浙江大学PAT上机题解析之2-11. 两个有序链表序列的合并
    顺序队列之C++实现
  • 原文地址:https://www.cnblogs.com/JackpotHan/p/13276202.html
Copyright © 2020-2023  润新知