クライアント証明書を期待している場合は、JSSEにこれらすべてを任せてください。特定の接続に独自のトラストストアを使用する場合は、それを使用するようにJSSEを構成します。リファレンスドキュメントの「JSSEのカスタマイズ」セクションを確認してください。
SSLContext
これは、カスタムトラストストアを使用してを構築するための簡単な例です。(他の、より複雑なX509TrustManager
ものも使用できますが、それが必要になることはめったにありません。)
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../example.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
既存のアプリケーションサーバーを使用している場合、これらすべてを構成に渡す方法は、サーバーとサーバーがどのように構成されるかによって異なります。これにJSSEを使用すると、主要な使用属性が適切であることも確認できます。
他の方法で証明書を取得し、それを検証する場合は、PKIAPIを使用する必要があります。PKIXアルゴリズムを使用して認証パスを検証する例に従うと、次のようになります。
X509Certificate certToVerify = ...
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertPath cp = cf.generateCertPath(Arrays
.asList(new X509Certificate[] { certToVerify }));
TrustAnchor trustAnchor = new TrustAnchor(caCert, null);
CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
PKIXParameters pkixParams = new PKIXParameters(
Collections.singleton(trustAnchor));
pkixParams.setRevocationEnabled(false);
cpv.validate(cp, pkixParams);
検証の結果を確認します(もちろん、検証例外がスローされていないことを確認します)。ここでは、簡略化するために失効チェックを無効にしました。PKIXParameters
ポリシーチェックの他の側面を設定することもできます。これは非常に複雑になる可能性があります(そして、デフォルトのJSSEマネージャーにそれを行わせる方がよい理由)。
また、Security.SEで尋ねたこの他の質問のコンテキストで、これらすべてについて質問していました。証明書のフィンガープリントの実際の値は何ですか。。
2つX509Certificate
のs:serverCert
とがあり、 (の公開鍵と一致する秘密鍵)によって署名されたcaCert
ことを確認するとします。serverCert
caCert
最も簡単な方法:
serverCert.verify(caCert.getPublicKey());
これをもう少し手動で行いたい場合は、Signature
APIを使用してください。
System.out
.println("Signature algorithm: " + serverCert.getSigAlgName());
Signature sig = Signature.getInstance(serverCert.getSigAlgName());
sig.initVerify(caCert.getPublicKey());
sig.update(serverCert.getTBSCertificate());
System.out
.println("Verified? " + sig.verify(serverCert.getSignature()));
アルゴリズムがであると仮定するとSHA1withRSA
、ダイジェストを計算することもできます。
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
digest.update(serverCert.getTBSCertificate());
byte[] digestBytes = digest.digest();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, caCert.getPublicKey());
byte[] cipherText = cipher.doFinal(serverCert.getSignature());
ダイジェスト自体は、次を使用した結果の一部になりCipher
ます。serverCert.getSignature()
実際には、より複雑なASN.1構造であり、ダイジェストアルゴリズム識別子が含まれています。この場合、digestBytes
接頭辞として次のようなものを付ける必要があります。
SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.
( ASN.1構造を適切に分析したい場合は、 BouncyCastleが役立つ場合があります。)
これはいずれも、時間の有効性やその他の属性を検証しないことに注意してください。PKIX準拠は、署名のチェック以上のものです(RFC 3820および5820を参照)。