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 解密相關問題全部解決. 簡單記錄一下.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM