次のコード:
_//used Bouncy Castle provider for keyStore
keyStore.setKeyEntry(alias, (Key)keyPair.getPrivate(), pwd, certChain);
_
ここで、certChainは、エンド証明書と発行者証明書(つまり、2つの証明書)を保持します。
keyStoreが_PKCS12
_のインスタンスである場合、ファイルシステムに保存されたキーストアファイルにチェーンの一部として発行者証明書を保存しません。
キーストアのタイプが_PKCS12-3DES-3DES
_の場合、両方の証明書が保存されます。どうしてこれなの? PKCS12は、両方の証明書がチェーンの一部であると想定していませんか?
編集:これは [〜#〜] sscce [〜#〜] です。これは_"JKS"
_では正常に機能し、_"PKCS12"
_では失敗します。チェーン内の最初の証明書のみにgetCertificateChain(String)
を介してアクセスできます。保存したファイルを_openssl pkcs12
_で開くと、両方の証明書が表示されます。
_ public void testKeyStore() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Certificate[] outChain = { createCertificate("CN=CA", publicKey, privateKey), createCertificate("CN=Client", publicKey, privateKey) };
KeyStore outStore = KeyStore.getInstance("PKCS12");
outStore.load(null, "secret".toCharArray());
outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);
OutputStream outputStream = new FileOutputStream("c:/outstore.pkcs12");
outStore.store(outputStream, "secret".toCharArray());
outputStream.flush();
outputStream.close();
KeyStore inStore = KeyStore.getInstance("PKCS12");
inStore.load(new FileInputStream("c:/outstore.pkcs12"), "secret".toCharArray());
Key key = outStore.getKey("myKey", "secret".toCharArray());
assertEquals(privateKey, key);
Certificate[] inChain = outStore.getCertificateChain("mykey");
assertNotNull(inChain);
assertEquals(outChain.length, inChain.length);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
private static X509Certificate createCertificate(String dn, PublicKey publicKey, PrivateKey privateKey) throws Exception {
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
certGenerator.setSerialNumber(new BigInteger("1"));
certGenerator.setIssuerDN(new X509Name(dn));
certGenerator.setSubjectDN(new X509Name(dn));
certGenerator.setNotBefore(Calendar.getInstance().getTime());
certGenerator.setNotAfter(Calendar.getInstance().getTime());
certGenerator.setPublicKey(publicKey);
certGenerator.setSignatureAlgorithm("SHA1withRSA");
X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC");
return certificate;
}
_
あなたのコードには2つのエラーがあります:
first:証明書の発行者を設定していません(有効なチェーンを作成するには、CAがクライアント証明書を発行する必要があります)。
second:証明書チェーンを作成するときに間違った順序を使用しています(クライアントファート、CAを最後にする必要があります)
ここでSSCCEを作り直し、エラーなしで動作します。
@Test
public void testKeyStore() throws Exception{
try {
String storeName = "/home/grigory/outstore.pkcs12";
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Certificate trustCert = createCertificate("CN=CA", "CN=CA", publicKey, privateKey);
Certificate[] outChain = { createCertificate("CN=Client", "CN=CA", publicKey, privateKey), trustCert };
KeyStore outStore = KeyStore.getInstance("PKCS12");
outStore.load(null, "secret".toCharArray());
outStore.setKeyEntry("mykey", privateKey, "secret".toCharArray(), outChain);
OutputStream outputStream = new FileOutputStream(storeName);
outStore.store(outputStream, "secret".toCharArray());
outputStream.flush();
outputStream.close();
KeyStore inStore = KeyStore.getInstance("PKCS12");
inStore.load(new FileInputStream(storeName), "secret".toCharArray());
Key key = outStore.getKey("myKey", "secret".toCharArray());
Assert.assertEquals(privateKey, key);
Certificate[] inChain = outStore.getCertificateChain("mykey");
Assert.assertNotNull(inChain);
Assert.assertEquals(outChain.length, inChain.length);
} catch (Exception e) {
e.printStackTrace();
throw new AssertionError(e.getMessage());
}
}
private static X509Certificate createCertificate(String dn, String issuer, PublicKey publicKey, PrivateKey privateKey) throws Exception {
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random().nextLong())));
certGenerator.setIssuerDN(new X509Name(dn));
certGenerator.setSubjectDN(new X509Name(dn));
certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer!
certGenerator.setNotBefore(Calendar.getInstance().getTime());
certGenerator.setNotAfter(Calendar.getInstance().getTime());
certGenerator.setPublicKey(publicKey);
certGenerator.setSignatureAlgorithm("SHA1withRSA");
X509Certificate certificate = (X509Certificate)certGenerator.generate(privateKey, "BC");
return certificate;
}
使用するJDKに応じて、アプリケーションをパッケージ化する方法は異なります。 LinuxやOpenJDKを使用している人や、SunJDK(Oracle)を使用しているWindowsで開発している人がいるときに起こります。
最新のアルゴリズムには、最強のアルゴリズムを使用できるようにするための追加の構成がいくつかあります。 この記事 は、問題がJCEポリシーに関連している場合に役立ちます。