31

我试图使用 AES 算法加密数据。但是,发生了以下异常。

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

有人知道这个问题的解决方案吗?我的JDK版本是1.7。

4

5 回答 5

47

您不想为分组密码使用指定 PKCS#7 填充。您要指定 PKCS#5 填充。PKCS#5 被指定用于分组密码,而 PKCS#7 不是(它用于不同的地方,如在 S/MIME 中)。我会指出 PKCS#5 和 PKCS#7 实际上指定了完全相同的填充类型(它们是相同的!),但在这种情况下使用时它被称为 #5。:)

所以,而不是"AES/ECB/PKCS7PADDING",你想要"AES/ECB/PKCS5PADDING"。这是一个密码实现,Java 平台的每个实现都需要支持。有关更多详细信息,请参阅该类的文档。Cipher

于 2012-04-17T15:21:23.943 回答
3

有关包含 PKCS#5 和 PKCS#7 加密标准文本的问题的非常全面的解释,请查看此处


PKCS#5 填充表示填充 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"不如简单地重新使用。

到目前为止,Sun 提供商应该真正支持"PKCS7Padding"PKCS#5 填充是不正确的。这不仅仅是 Java 命名问题,对于任何尝试实现加密协议或将其他应用程序移植到 Java 的开发人员来说都是一个问题。但是,现在,您应该使用"PKCS5Padding"而不是"PKCS7Padding".

于 2015-01-24T22:39:08.220 回答
3

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

于 2013-10-15T09:43:41.003 回答
0

如果环境是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);
于 2022-02-24T10:29:03.563 回答
0

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

第二步:添加行“Security.addProvider(new BouncyCastleProvider());” 开始初始化密码通用

然后,运行项目,OK,解密成功。

于 2020-03-20T02:49:54.807 回答