21

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

X509TrustManagerwhere I always return truefromを実装する独自のクラスを作成することで、これを行う方法を知っていますisServerTrusted

ただし、すべてのサーバーとすべてのクライアントを信頼したくありません。

  • 現在行われているように、すべてのデフォルトの検証をクライアントに対して行う必要があります。
  • サーバーの場合、特定の1つの証明書についてのみサーバー証明書の検証を無視したいが、現在行われているように検証したい(たとえば、cacertsストアを使用するため)。

どうすればこのようなことを達成できますか。つまり、検証の一部を、置き換える前の 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また、既存の検証を妨げたくありません。

これどうやってするの?

4

3 に答える 3

49

既存のデフォルトの信頼マネージャーを取得し、次のようなものを使用して独自にラップできます。

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 (偽造するのは難しくありません) を持つ証明書を通過させることです。

if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer"))
    return true;

X509Certificate代わりに、既知の参照からインスタンスをロードし、チェーン内の実際の値を比較できます。

さらに、checkClientTrustedandはorcheckServerTrustedを返すメソッドではなく、デフォルトでサイレントに成功するメソッドです。期待する証明書に問題がある場合は、明示的にスローします。truefalsevoidCertificateException

于 2013-09-25T13:08:51.850 に答える