5

組み込みクラスcom.sun.net.httpserver.HttpsServerを使用して、Java(6)でカスタムHTTPSサーバーを構築しようとしています。クライアント認証が必要になるまでは正常に機能します。その時点で、サーバーのSSLデバッグで次の例外が発生して失敗します。

sun.security.validator.ValidatorException:Netscape証明書タイプはSSLクライアントの使用を許可していません

内部CAによって発行された証明書を使用しています。これは、内部のすべてのアプリケーションに使用されます。証明書の詳細を確認したところ、タイプが「SSLサーバー」であることがわかりました(詳細は以下に引用)。すべての内部アプリケーションに「SSLサーバー」タイプを使用することをポリシーとしているため、証明書を変更することは困難です。クライアントにサーバー証明書を使用したいので、これはセキュリティの問題ではないと思います。

私が探しているのは、Javaでこの制約チェックを無効にする方法です。誰かがこれに遭遇し、これを解決しましたか?どんな助けでも大歓迎です。

よろしく、アルン

Owner: CN=myapp, OU=mygroup, O=mycompany

Issuer: O=MYCA

Serial number: 4cc8c1da

Valid from: Mon Jan 10 13:46:34 EST 2011 until: Thu Jan 10 14:16:34 EST 2013

Certificate fingerprints:
         MD5:  8C:84:7F:7A:40:23:F1:B5:81:CD:F9:0C:27:16:69:5E
         SHA1: 9B:39:0B:2F:61:83:52:93:D5:58:E5:43:13:7A:8F:E1:FD:AC:98:A4
         Signature algorithm name: SHA1withRSA
         Version: 3

Extensions:

[1]: ObjectId: 2.5.29.16 Criticality=false
PrivateKeyUsage: [
From: Mon Jan 10 13:46:34 EST 2011, To: Wed Jul 11 21:16:34 EDT 2012]

[2]: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
  DigitalSignature
  Key_Encipherment
]

[3]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: D3 47 35 9B B4 B7 03 18   C6 53 2C B0 FE FD 49 D8  .G5......S,...I.
0010: D0 FB EE 15                                        ....
]
]

[4]: ObjectId: 1.2.840.113533.7.65.0 Criticality=false

[5]: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
  [DistributionPoint:
     [CN=CRL413, O=SWIFT]
]]

[6]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:false
  PathLen: undefined
]

****[7]: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
   SSL server
]****

[8]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 8F AF 56 BC 80 77 A3 FD   9E D2 89 83 98 FE 98 C7  ..V..w..........
0010: 20 65 23 CC                                         e#.
]

]
4

1 に答える 1

1

デフォルトの信頼マネージャーをラップして、この特定の例外をキャッチできます。これは、次のようなものです。

class IgnoreClientUsageTrustManager extends X509TrustManager {
    private final X509TrustManager origTrustManager;
    public class IgnoreClientUsageTrustManager(X509TrustManager origTrustManager) {
        this.origTrustManager = origTrustManager;
    }

    public checkClientTrusted(X509Certificate[] chain, String authType
        throws IllegalArgumentException, CertificateException {
        try {
            this.origTrustManager.checkClientTrusted(chain, authType);
        } catch (ValidatorException e) {
             // Check it's that very exception, otherwise, re-throw.
        }
    }

    // delegate the other methods to the origTrustManager
}        

次に、そのトラスト マネージャーを使用して を作成SSLContextし、サーバーで使用します。

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore)null);
TrustManager[] trustManagers = tmf.getTrustManagers();

for (int i = 0; i < trustManagers.length; i++) {
    if (trustManagers[i] instanceof X509TrustManager) {
       trustManagers[i] = IgnoreClientUsageTrustManager(trustManagers[i]);
    }
}

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(... you keymanagers ..., trustManagers, null);

サーバーキーストアからキーマネージャーを初期化する必要があります (通常どおり)。その後、 を使用して をセットアップできるはずです(ドキュメントの例を参照) HttpsServerHttpsConfiguratorSSLContext

ただし、この手法は理想的ではありません。

もちろん、代わりに Java Certificate Path API を使用して独自の検証を再実装し、この目的でのキーの使用のみを無視することもできます。これには、もう少しコードが必要です。

より一般的には、適切な拡張子がない場合に SSL/TLS の証明書をクライアント証明書として使用する場合は、とにかく仕様をバイパスしようとしています。これに対する最善の解決策は、CA ポリシーを修正することです。これは、とにかく内部 CA である場合に実行できるはずです。大規模な CA であっても、サーバー証明書に TLS クライアント拡張キー使用法が設定されていることは非常に一般的です。

于 2012-09-23T18:54:23.367 に答える