4

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

当我创建我的 PKCS12 文件时,我使用以下代码(privateKeyis anRSAPrivateKeysignedCertis an 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();

提前致谢!

4

1 回答 1

5

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

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

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

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

问候,

大卫

于 2013-03-07T12:28:52.873 回答