X509TrustManagerの実装-検証の一部を既存の検証に渡す
PKIXパス構築例外を無視する必要があります
javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException:
PKIX path building failed: Sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target
isServerTrusted
から常にX509TrustManager
を実装するreturn true
を実装する独自のクラスを作成することで、これを行う方法を知っています。
ただし、すべてのサーバーとクライアントを信頼する必要はありません。
- 現在行われているように、クライアントに対してすべてのデフォルトの検証を実行してください。
- サーバーの場合、1つの特定の証明書についてのみサーバー証明書の検証を無視しますが、現在行われているように(たとえば、cacertsストアを使用して)検証します。
どうすればこのようなことを実現できますか?つまり、検証の一部を、X509TrustFactoryオブジェクトを置き換える前にX509TrustFactoryオブジェクトに渡します。
つまり、これは私がやりたいことです
public boolean isServerTrusted(X509Certificate[] chain)
{
if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
return true;
// else I want to do whatever verification is normally done
}
また、既存のisClientTrusted
検証を妨害したくありません。
これどうやってするの?
既存のデフォルトのトラストマネージャーを手に入れ、次のようなものを使用して独自にラップすることができます:
_TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);
// Get hold of the default trust manager
X509TrustManager x509Tm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
x509Tm = (X509TrustManager) tm;
break;
}
}
// Wrap it in your own class.
final X509TrustManager finalTm = x509Tm;
X509TrustManager customTm = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return finalTm.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
finalTm.checkServerTrusted(chain, authType);
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
finalTm.checkClientTrusted(chain, authType);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);
// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);
_
次に、finalTm.checkServerTrusted(chain, authType);
の周りに独自のロジックを実装できます。
ただし、無視する特定の証明書を例外にしていることを確認する必要があります。
以下では、これらの発行者DNとサブジェクトDNを使用してany証明書を通過させています(偽造するのは難しくありません)。
_if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
return true;
_
代わりに、既知の参照から_X509Certificate
_インスタンスをロードして、チェーン内の実際の値を比較できます。
また、checkClientTrusted
およびcheckServerTrusted
はtrue
またはfalse
を返すメソッドではなく、デフォルトでサイレントに成功するvoid
メソッドです。期待する証明書に問題がある場合は、CertificateException
を明示的にスローします。