我正在尝试使用 BouncyCastle 提供程序读取基于椭圆曲线密钥的 PKCS#12 文件。但它抛出以下异常
java.lang.RuntimeException: java.io.IOException: exception decrypting data - java.security.NoSuchAlgorithmException: 1.2.840.113549.1.5.12 SecretKeyFactory not available
PKCS#12 文件是通过以下使用 OpenSSL 3.2.0 2023 年 11 月 23 日的命令生成的:
openssl ecparam -name prime256v1 -genkey -noout -out ec-private.key
openssl req -new -key ec-private.key -out ec-certificate.csr
openssl x509 -req -in ec-certificate.csr -signkey ec-private.key -days 365 -out ec-certificate.crt
openssl pkcs12 -export -out ec-certificate.p12 -inkey ec-private.key -in ec-certificate.crt -name "My ECC Certificate"
我对应的代码如下。
try {
InputStream caInput = getResources().openRawResource(R.raw.ec_certificate);
Security.addProvider(new BouncyCastleProvider());
// Initialize KeyStore
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
//KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(caInput, password_.toCharArray());
Enumeration < String > aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
cert = (X509Certificate) keyStore.getCertificate(alias);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (NoSuchProviderException e) {
throw new RuntimeException(e);
}
如何使用 BouncyCastle 提供商解决问题? 我正在使用
group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: '1.76'
bouncycastle 依赖项。
在我的java版本中,我使用
group: 'org.bouncycastle', name: 'bcprov-jdk18on', version: '1.79'
bouncycastle 依赖项,并且未抛出运行时异常。它只会在我的 Android 应用程序中使用并从原始资源文件中读取时抛出。
我已经能够在 Android 模拟器上使用 OpenSSL 3.2.1 和 Bouncy Castle 1.79 重现该问题。我相信这个问题是由以下事实引起的:Android 附带了一个名为“BC”的提供程序,并且该提供程序隐藏了您想要在应用程序中使用的现代提供程序。我尝试了两种似乎有效的不同解决方法,但我没有进行广泛的测试。第一个解决方法是在添加您的版本之前删除现有的 Bouncy Castle 提供程序。所以
InputStream caInput = getResources().openRawResource(R.raw.ec_certificate);
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
// Initialize KeyStore
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
getInstance
方法,该方法将 Provider
实例作为第二个参数。所以改用
KeyStore keyStore = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());
Android 使用 Bouncy Castle 提供商的零碎历史由来已久,这导致尝试使用自己的 Bouncy Castle 最新版本副本的应用程序出现问题。我虽然那都是古老的历史,但显然仍然有一些那时的遗迹。