java 小程序开发PKCS7Padding 解密相关问题
<p>近日小程序开发需求--获取用户小程序unionid(UnionID获取途径),考虑到用户非必须关注公众号,只能通过<em>wx.getUserInfo从解密数据中获取 UnionID</em> ,api返回的数据<em>encryptedData</em> 的解密算法要求为: AES-128-CBC,数据采用PKCS#7填充。</p><p>但是,在解密时出现了异常(使用的java 11)</p>
<div class="cnblogs_code">
<pre>java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/CBC/PKCS7Padding</pre>
</div>
<p>查询了一波,大致的问题是java不支持PKCS7Padding,只支持PKCS5Padding,Java的默认crypto类,AES算法使用PKCS5Padding 填充模式,而iOS使用PKCS7Padding填充模式。</p>
<p>PKCS7Padding VS PKCS5Padding 的区别也很简单 PKCS5Padding 的blocksize为8字节,而PKCS5Padding 的blocksize范围 1~255字节. 参考 PKCS5Padding 和 PKCS7Padding</p>
<p>于是自以然的觉得把PKCS7Padding换成PKCS5Padding问题不久解决了嘛? 然后结果却啪啪啪的打脸,这条道走不了,只能想办法让java兼容PKCS7Padding.</p>
<p>借助强大的Google了解到要实现java支持PKCS7Padding就必须要借助第三方组件来实现--bouncycastle,在MVN仓库查询后发现相关的依赖有两个</p>
<div class="cnblogs_code">
<pre><dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">以及</span>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk16</artifactId>
<version>1.45</version>
</dependency></pre>
</div>
<p>有点懵逼啊,那么我该选择哪一个呢?把两个jar包下载下来后反编译看了下,惊讶的发现bcprov-jdk16的代码是bcprov-ext-jdk16的子集,于是依然选择了下面的依赖.</p>
<p>so easy 轻轻松松解决问题,程序跑起来,然而,又出现了一个新的错误</p>
<div class="cnblogs_code">
<pre>javax.crypto.BadPaddingException: pad block corrupted</pre>
</div>
<p>于是又google了一波,stackoverflow上一位大佬的回答引起了我的注意,参见-stackoverflow,以下是大佬的回答.</p>
<p> </p>
<p><img src="https://img2020.cnblogs.com/blog/1477997/202007/1477997-20200709204928162-1536937088.png" alt="" width="552" height="193" loading="lazy"></p>
<p> </p>
<p> 意思很明显,需要定义一个provider,于是我定义了一个静态方法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> {
Security.addProvider(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BouncyCastleProvider());
}</span></pre>
</div>
<p>终于成功解密了.</p>
<p>后来查看源码,发现Cipher有一个getInstance(String transformation, String provider)方法,源码如下</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Cipher getInstance(String transformation, String provider) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (transformation != <span style="color: rgba(0, 0, 255, 1)">null</span> && !transformation.equals(""<span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (provider != <span style="color: rgba(0, 0, 255, 1)">null</span> && provider.length() != 0<span style="color: rgba(0, 0, 0, 1)">) {
Provider p </span>=<span style="color: rgba(0, 0, 0, 1)"> Security.getProvider(provider);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (p == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> NoSuchProviderException("No such provider: " +<span style="color: rgba(0, 0, 0, 1)"> provider);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> getInstance(transformation, p);
}
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> IllegalArgumentException("Missing provider"<span style="color: rgba(0, 0, 0, 1)">);
}
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> NoSuchAlgorithmException("Null or empty transformation"<span style="color: rgba(0, 0, 0, 1)">);
}
}</span></pre>
</div>
<p>于是,又在网上搜索了Cipher provider相关知识,发现一个很有趣的provider-"BC",使用方法如下</p>
<div class="cnblogs_code">
<pre>Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");</pre>
</div>
<p>启动,测试,完美,一次点亮.</p>
<p>自此.java 小程序开发PKCS7Padding 解密相关问题全部解决. 简单记录一下.</p>
<p> </p><br><br>
来源:https://www.cnblogs.com/JackpotHan/p/13276202.html
頁:
[1]