web-dev-qa-db-ja.com

PKCS12 Java CAからのキーストアとjava

私は最近、JavaでApple製品(iPhone構成ユーティリティ)のモックアップを担当しました。私が少し立ち往生しているセクションの1つは、ExchangeActiveSyncに関する部分です。そこでは、キーチェーンから証明書を選択してEASアカウントの資格情報として使用できます。調査の結果、実際にPKCS12キーストアを作成し、選択した証明書の秘密鍵を挿入して、にエンコードしていることがわかりました。 XML。これまでのところ大したことではありません。KeychainAccessで.p12ファイルを作成すると、問題なくアップロードされます。しかし、それをJavaに持ち込もうとすると、問題が発生します。

以前に.p12ファイルで使用した証明書の1つを.cerファイルとしてエクスポートするとします(これは、環境で取得することを期待しているものです)。これをJavaにアップロードすると、次のようにCertificateオブジェクトが取得されます...

KeyStore ks = Java.security.KeyStore.getInstance("PKCS12");
ks.load(null, "somePassword".toCharArray());

CertificateFactory cf = CertificateFactory.getInstance("X.509", new BouncyCastleProvider());
Java.security.cert.Certificate userCert  = cf.generateCertificate(new FileInputStream("/Users/me/Desktop/RecentlyExportedCert.cer"));

しかし、私が試してみると...

ks.setCertificateEntry("SomeAlias", userCert);

例外が発生します...

Java.security.KeyStoreException: TrustedCertEntry not supported

それで、証明書から私は鍵に移ります。しかし、これらの証明書(私もCA証明書を取得しました)を使用すると、公開鍵にのみアクセスでき、秘密鍵にはアクセスできません。そして、私がそのように公開鍵を追加しようとすると...

Java.security.cert.Certificate[] chain = {CACert};
ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain);

….

Java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: Java.io.IOException: DerValue.getOctetString, not an Octet String: 3

だから今私はここにいます。秘密鍵を.cerファイルからJavaのPKCS12キーストアに取得する方法を知っている人はいますか?私も正しい方向に進んでいますか?

前もって感謝します!

13
Staros

PKCS#12形式は、証明書チェーンに関連付けられた秘密鍵を格納することを目的としており、両方が必要です(ただし、チェーン全体は必要ない場合があります)。 _PKCS12_キーストアタイプは、この形式をJava KeyStoreにマッピングするのに適していますが、この理由ですべてがサポートされているわけではありません。

最初の試みで行おうとしているのは、証明書を単独で保存することですが、これは機能しません。

2回目の試行(ks.setKeyEntry("SomeAlias", userCert.getPublicKey().getEncoded(), chain))で実行しようとしているのは、秘密鍵である必要があるものの代わりに公開鍵を使用することです( _KeyStore#setKeyEntry_ を参照) 。

_.cer_ファイルは、秘密鍵ではなく証明書専用である傾向があります(もちろん、拡張子は最終的には単なる指標です)。 _.cer_ファイルをKeychain Access.appからエクスポートすると、秘密鍵は取得されません(これが、_.p12_エクスポート形式です。ために)。

[〜#〜]編集[〜#〜]KeychainStoreについて:

この変換を行おうとしている理由が、最終的にはすでにキーチェーンにある秘密鍵と証明書にアクセスするためである場合は、KeychainStoreから直接ロードできます。

_KeyStore ks = KeyStore.getInstance("KeychainStore", "Apple");
ks.load(null, "-".toCharArray());
_

これに関するいくつかの注意事項:

  • (他のアプリケーションの場合と同様に)アクセスはOSのセキュリティサービスによって要求されるため、null以外、空でないパスワードは秘密鍵("-".toCharArray()など)を使用します。
  • 私の知る限り、まだバグがあり、 1つの秘密鍵/証明書のペアにしかアクセスできません (キーチェーンに秘密鍵/証明書のペアのペアが多数存在する場合でも) )
17
Bruno

http://www.docjar.com/html/api/org/bouncycastle/jce/examples/PKCS12Example.Java.html

これは、PKCS12キーストアに関連付けられた秘密鍵を持つ証明書を追加する方法です。クライアント認証を使用している場合、キーストアには秘密キーも含める必要があります。その場合は、KeyStore.getInstance( "PKCS12")を使用します。

クライアント認証を使用せず、サーバー認証のみを使用する場合(および秘密鍵はサーバーに属しているため、キーストアに追加されません)、複数の証明書を追加するよりも、KeyStore.getInstance( "JKS")を使用する方が適切です。その1つのキーストアのエイリアス。

PKCS12を使用している場合、私が知る限り、秘密鍵に関連付けられている証明書は1つしか追加できません(証明書チェーン全体を追加する必要があります)。その証明書に使用します。

3
Fico