Java – KeyStore没有在Android中使用BouncyCastle为PKCS12文件应用/强制执行私钥密码

我发现当我创建一个受密码保护的PKCS12文件,该文件还包含受密码保护的私钥及其关联的公钥/证书时,无论提供给getKey()的密码如何,我都能解密私钥(内部加密)只要为KeyStore的初始加载()提供了正确的密码.这是一个已知问题还是有其他人看过这个?它看起来真的是私钥密码未被使用或一起被忽略.我使用Android和BouncyCastle作为提供者.我也很好奇这个问题是否适用于JKS而不仅仅是BouncyCastle?为清楚起见,删除了以下代码中的错误检查.

当我创建我的PKCS12文件时,我使用以下代码(privateKey是RSAPrivateKey,signedCert是X509Certificate):

KeyStore store;
store = KeyStore.getInstance( "PKCS12", "BC" );
store.load( null, null );

X509Certificate[] chain = new X509Certificate[1];
chain[0] = signedCert;

store.setKeyEntry( pkcs12Alias, privateKey, p12PkeyPass.toCharArray(), chain );

FileOutputStream fos;
File outputDir = appContext.getFilesDir();
File pkcs12File = new File( outputDir, p12Filename );
fos = new FileOutputStream( pkcs12File );

store.store( fos, p12Pass.toCharArray() );
fos.flush();
fos.close();

当我去加载PKCS12内容时,无论我为私钥密码添加什么,提取的私钥都被正确加载并且都是相同的(pkey1 == pkey2 == pkey3使用.equals()进行测试).

FileInputStream fis;
KeyStore store;
File pkcs12File = new File( activity.getFilesDir(), p12Filename );
fis = new FileInputStream( pkcs12File );
store = KeyStore.getInstance( "PKCS12", "BC" );
store.load( fis, p12Pass.toCharArray() );

X509Certificate signedCert = (X509Certificate) store.getCertificate( pkcs12Alias );

// try to get the private key with different passwords - result is the same
RSAPrivateKey pkey1 = (RSAPrivateKey) store.getKey( pkcs12Alias, p12PkeyPass.toCharArray() );
RSAPrivateKey pkey2 = (RSAPrivateKey) store.getKey( pkcs12Alias, "".toCharArray() );
RSAPrivateKey pkey3 = (RSAPrivateKey) store.getKey( pkcs12Alias, "something completely different".toCharArray() );

fis.close();

提前致谢!

解决方法:

像许多其他提供商一样,Bouncy Castle忽略了PKCS#12的密钥密码. PKCS#12是关于个人凭证交换的标准,其结果之一是大多数实现假设密钥库和密钥都只需要一个密码.

可以使用与用于密封密钥库的密码不同的密码在PKCS#12文件中加密密钥,但是如果执行此操作,则不太可能找到可以读取该文件的其他应用程序.或者换一种方式,尝试这不是一个疯狂的想法,只是KeyStore API和PKCS#12相似但不同,所以你会发现存在特性 – 在某些方面PKCS#12功能更全面,因为它允许附件以比KeyStore API更常规的方式存储在文件中的对象的属性.

我们(如在Bouncy Castle中)最近试图在PKCS#12的单独API中提供更通用的方法来处理这个问题,该API目前是1.49的beta版.如果你真的想要它,它将允许你使用不同的加密密码,但如果你希望你生产的文件被其他任何东西理解,我会建议不要使用它. PKCS#12 API确实允许您更好地使用属性,但是这是否是您真正需要做的事情(通常您没有)我会留给您决定.

您会发现其他格式(如JKS)允许密钥和密钥库使用不同的密码.正如我之前提到的,不同之处在于,与PKCS#12不同,JKS并未被定义为“个人”存储机制.

问候,

大卫

上一篇:uni-app 云打包证书生成笔记


下一篇:Java – javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份验证