簡體   English   中英

java.security.NoSuchAlgorithmException:找不到任何支持 AES/ECB/PKCS7PADDING 的提供商

[英]java.security.NoSuchAlgorithmException:Cannot find any provider supporting AES/ECB/PKCS7PADDING

我試圖使用 AES 算法加密數據。 但是,發生了以下異常。

java.security.NoSuchAlgorithmException:
    Cannot find any provider supporting AES/ECB/PKCS7PADDING

有人知道這個問題的解決方案嗎? 我的 JDK 版本是 1.7。

您不想為分組密碼使用指定 PKCS#7 填充。 您想指定 PKCS#5 填充。 PKCS#5 被指定用於分組密碼,而 PKCS#7 不是(它用於不同的地方,比如在 S/MIME 中)。 我將指出 PKCS#5 和 PKCS#7 實際上指定了完全相同的填充類型(它們是相同的!),但在此上下文中使用時稱為 #5。 :)

因此,而不是"AES/ECB/PKCS7PADDING"想要"AES/ECB/PKCS5PADDING" 這是一個密碼實現,Java 平台的每個實現都需要支持。 有關更多詳細信息,請參閱Cipher文檔

如果你想使用 AES/ECB/PKCS7Padding 那么充氣城堡將支持 ht tp://www.bouncycastle.org/specifications.html

有關包括 PKCS#5 和 PKCS#7 加密標准文本在內的問題的非常全面的解釋,請查看此處


PKCS#5 padding 表示填充 1 到 8 個字節。 填充字節本身包含編碼為字節的填充字節量。 為 DES 指定了 PKCS#5 填充,但它適用於塊大小為 8 字節的任何塊密碼。

現在 DES 規范甚至基於密碼的加密的 PKCS#5 規范早於 Java。 AES 直到 2002 年才被標准化,早在 Java 甚至 Java 2 被引入之后。 因此,在 AES 出現之前,(三重)DES 和 PKCS#5 填充已集成到 Java 中。

當 Java——或者更准確地說,Sun JCE 提供者——獲得 AES 功能時,它需要一個 16 字節的塊大小的填充方法。 PKCS#7 指定了與 PKCS#5 padding 相同的填充方法,除了它是為 2 到 255 個字節的塊大小定義的(如果它編碼基於零的無符號整數,則為字節的最大值)。 但是,填充方法已經存在; 它被命名為"PKCS5Padding" 因此,沒有引入新名稱, "PKCS5Padding"簡單地重新使用了"PKCS5Padding"

到目前為止,Sun 提供者應該真正支持"PKCS7Padding"因為 PKCS#5 填充是完全不正確的。 這不僅僅是 Java 命名問題,對於任何試圖實現加密協議或將其他應用程序移植到 Java 的開發人員來說,都是一個問題。 但是現在,您應該使用"PKCS5Padding"而不是"PKCS7Padding"

解決方案: Step1:將 bcprov-ext-jdk16-1.46.jar ( https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk16/1.46 ) 添加到您的項目中

Step2:添加行“Security.addProvider(new BouncyCastleProvider());” 進入 init Cipher common

然后,運行項目,OK,解密成功。

如果環境為Android ,並且您嘗試從文件中讀取 PKCS8 格式的加密私鑰或密碼保護私鑰,請考慮以下解決方案。

我收到的異常如下:

W/System.err: org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: 1.2.840.113549.1.5.13 not available: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source:60)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
W/System.err:     at android.os.Looper.loop(Looper.java:223)
W/System.err:     at android.os.HandlerThread.run(HandlerThread.java:67)
W/System.err: Caused by: org.bouncycastle.operator.OperatorCreationException: 1.2.840.113549.1.5.13 not available: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source:322)
W/System.err:     at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source:6)
W/System.err:   ... 8 more
W/System.err: Caused by: java.security.NoSuchAlgorithmException: No provider found for 2.16.840.1.101.3.4.1.42
W/System.err:     at javax.crypto.Cipher.createCipher(Cipher.java:736)
W/System.err:     at javax.crypto.Cipher.getInstance(Cipher.java:619)
W/System.err:     at org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createCipher(Unknown Source:0)
W/System.err:     at org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder$1.get(Unknown Source:101)
W/System.err:   ... 9 more

唯一可行的解決方案是將 Provider 設置為 Bouncy Castle,如下所示:

InputDecryptorProvider decryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
    .setProvider(new BouncyCastleProvider())
    .build(mContext.getResources().getString(R.string.password).toCharArray());

完整的塊代碼如下所示:

privateKeyString = privateKeyString.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "").replaceAll(System.lineSeparator(), "")
                .replace("-----END ENCRYPTED PRIVATE KEY-----", "");
byte[] keyStringBytes = DatatypeConverter.parseBase64Binary(privateKeyString);
ASN1Sequence asn1Sequence = ASN1Sequence.getInstance(keyStringBytes);
PKCS8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo = new PKCS8EncryptedPrivateKeyInfo(
    EncryptedPrivateKeyInfo.getInstance(asn1Sequence));
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
InputDecryptorProvider decryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
    .setProvider(new BouncyCastleProvider())
    .build(mContext.getResources().getString(R.string.password).toCharArray());
PrivateKeyInfo privateKeyInfo = pkcs8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptorProvider);
mPrivateKey = converter.getPrivateKey(privateKeyInfo);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM