web-dev-qa-db-ja.com

JavaおよびBouncycastleを使用したX.509証明書の検証

bouncycastle wikiページ X.509ルート証明書と認証要求の作成方法は理解できましたが、その後の概念とプログラミングの進め方はよくわかりません。

パーティAが証明書要求を行い、CAからクライアント証明書を取得するとします。一部のパーティBはAの証明書をどのように検証できますか? Aにはどのような証明書が必要ですか?ルート証明書? 「通常の」クライアント証明書?

また、Aが証明書をDERまたはPEM形式でBに正常に送信したと仮定した場合、検証はプログラミングレベルでどのように機能しますか?

どんな助けでも大歓迎です。

よろしく、ロブ

18
Rob

プログラマーの観点からは、X.509証明書を検証するためにいくつかのことが必要です。

  1. 「トラストアンカー」のセット—信頼するCAのルート証明書。攻撃者がCA証明書を自分の偽物に置き換えないように、これらは改ざんから保護する必要があります。これらの証明書の公開鍵は、他の証明書のデジタル署名を検証するために使用されます。
  2. 中間証明書のコレクション。アプリケーションはこれらのコレクションを保持する場合がありますが、SSLやS/MIMEなど、証明書を使用するほとんどのプロトコルには、追加の証明書を提供する標準的な方法があります。これらを保存するのに特別な注意は必要ありません。それらの整合性は、ルートCAの署名によって保護されます。
  3. 失効情報。証明書がCAによって発行された場合でも、秘密鍵が開示されたか、エンドエンティティがIDを変更したために、証明書が時期尚早に取り消された可能性があります。 (たとえば、人が転職し、古い会社の名前が含まれている証明書が取り消されます。)CRLまたはOCSPなどのWebサービスを使用して、証明書のステータスに関する最新情報を取得できます。

これらの入力を使用できる場合は、 組み込みのPKIXサポート を使用して、証明書パスを作成および検証できます。

/* Givens. */
InputStream trustStoreInput = ...
char[] password = ...
List<X509Certificate> chain = ...
Collection<X509CRL> crls = ...

/* Construct a valid path. */
KeyStore anchors = KeyStore.getInstance(KeyStore.getDefaultType());
anchors.load(trustStoreInput, password);
X509CertSelector target = new X509CertSelector();
target.setCertificate(chain.get(0));
PKIXBuilderParameters params = new PKIXBuilderParameters(anchors, target);
CertStoreParameters intermediates = new CollectionCertStoreParameters(chain)
params.addCertStore(CertStore.getInstance("Collection", intermediates));
CertStoreParameters revoked = new CollectionCertStoreParameters(crls);
params.addCertStore(CertStore.getInstance("Collection", revoked));
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
/* 
 * If build() returns successfully, the certificate is valid. More details 
 * about the valid path can be obtained through the PKIXBuilderResult.
 * If no valid path can be found, a CertPathBuilderException is thrown.
 */
PKIXBuilderResult r = (PKIXBuilderResult) builder.build(params);

注意すべき重要なことは、パスが見つからない場合、その理由について多くの情報が得られないということです。これはイライラする可能性がありますが、設計上はそうです。一般に、多くの潜在的なパスがあります。それらがすべて異なる理由で失敗した場合、パスビルダーはどのように理由として何を報告するかを決定しますか?

33
erickson

わかりました。CAの背後にある考え方は次のとおりです。

  • CAは誰もが信頼する人々です。この目的のために、信頼できるCAの選択は、ブラウザ/電子メールクライアント/私の携帯電話でも利用できます。あなたの場合、あなたの公開ルートキー(証明書)はあなたのアプリケーションにあるべきです。
  • ユーザーは、公開鍵を使用してPEM形式の証明書を求める要求をCAに送信します。 CAは、エンドユーザーに料金を請求したり、強化された検証(緑色)証明書の場合は身元調査など、エンドユーザーの検証のいくつかの形式(これは意図的にあいまいなままにしておきます)を行います。
  • CAがユーザーの要求が有効であると思わない場合、CAはこれを何らかの方法で伝達します。
  • その場合、公開鍵に署名し、この情報を含む証明書を作成します。ここで、cert-reqを処理し、それをX.509証明書に変換します。
  • 他のユーザーは私たちの架空のユーザーに出くわし、彼らが彼らを信頼できるかどうか知りたいと思っています。それで、彼らは証明書を見て、それが彼らの信頼リストにある誰かによってデジタル署名されているのを見つけます。したがって、ルートCAを信頼し、ルートCAのみが(秘密鍵を介して)このユーザーの公開鍵に署名でき、CAがユーザーを信頼するという事実から、新しいユーザーは架空のユーザーを信頼できると推測されます。

プログラムレベルでは、X.509証明書を読み取り、CAが誰であるかを判断することにより、これを実装します。そのCAのフィンガープリントを指定すると、データベースでそれを見つけて署名を確認します。それが一致する場合、あなたはあなたの信頼の連鎖を持っています。

これが機能するのは、私が言ったように、CAだけがデジタル署名を作成でき、誰でもそれを検証できるからです。これは、暗号化の概念の正反対です。署名したいデータを「秘密鍵で暗号化」し、「公開鍵で復号化」が取得したデータと等しいことを確認します。

9
user257111