java - KeyStore 不为带有 BouncyCaSTLe 的 Android 中的 PKCS12 文件应用/强制执行私钥密码

标签 java android bouncycastle keystore pkcs#12

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

当我创建我的 PKCS12 文件时,我使用以下代码(privateKey 是一个 RSAPrivateKeysignedCert 是一个 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 的 key 密码。 PKCS#12 是一个关于个人凭证交换的标准,其结果之一是大多数实现假设 keystore 和 key 只需要一个密码。

可以使用与密封 keystore 不同的密码在 PKCS#12 文件中加密 key ,但是如果您这样做,您将不太可能找到另一个可以读取该文件的应用程序。或者换句话说,尝试这并不是一个疯狂的想法,只是 KeyStore API 和 PKCS#12 相似但又不同,所以您会发现存在一些特性——在某些方面,PKCS#12 的功能更全面,因为它允许附件以比 KeyStore API 更通用的方式存储在文件中的对象的属性。

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

您会发现其他格式(如 JKS)允许 key 和 keystore 使用不同的密码。正如我之前提到的,这里的区别在于 JKS 没有被定义为“个人”存储机制,这与 PKCS#12 不同。

问候,

大卫

关于java - KeyStore 不为带有 BouncyCaSTLe 的 Android 中的 PKCS12 文件应用/强制执行私钥密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15264498/

相关文章:

java - 使用 spring : Unresolved forward references Jackson Exception 反序列化 JSON

java - Jsch 无法与某些 sftp 服务器一起使用

java - 无法 gpg 解密 BouncyCaSTLePGP 加密消息

java - 在没有实体的文件中 hibernate native 查询

java - 在两个不同但相同的表中插入记录,Hibernate?

java - 如何在Android项目中命名getter/setter

android - bitmap.compress(Bitmap.CompressFormat.PNG, 0, fOut) 使图像尺寸大于原始尺寸

android - 如何在 RecyclerView 上滑动删除?

java - 如何制作一个弹性城堡 ECPublicKey

java - Java 中的哈希表内存使用情况