我试图使用 AES 算法加密数据。但是,发生了以下异常。
java.security.NoSuchAlgorithmException:
Cannot find any provider supporting AES/ECB/PKCS7PADDING
有人知道这个问题的解决方案吗?我的JDK版本是1.7。
我试图使用 AES 算法加密数据。但是,发生了以下异常。
java.security.NoSuchAlgorithmException:
Cannot find any provider supporting AES/ECB/PKCS7PADDING
有人知道这个问题的解决方案吗?我的JDK版本是1.7。
有关包含 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"
.
如果你想使用 AES/ECB/PKCS7Padding 那么充气城堡将支持 ht tp://www.bouncycastle.org/specifications.html
如果环境是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);
解决方案: Step1:将 bcprov-ext-jdk16-1.46.jar ( https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk16/1.46 ) 添加到您的项目中
第二步:添加行“Security.addProvider(new BouncyCastleProvider());” 开始初始化密码通用
然后,运行项目,OK,解密成功。