1

2つのデスクトップJavaアプリ間で通信する必要があります。これを行うための最良の方法は、SSLを使用することです(スニファーを防ぐため)。私はクライアントとサーバーの両方を制御しているので、自己署名は問題ありません。

私の質問は、プログラムで証明書を最初から作成して使用できるかどうかです(つまり、エンドユーザーは自分で物理的に何もする必要はありません)。

これが可能であれば、私にいくつかの指針を教えていただけますか?

4

2 に答える 2

4

私の質問は、プログラムで証明書を最初から作成して使用できるかどうかです(つまり、エンドユーザーは自分で物理的に何もする必要はありません)。

(プログラムであるかどうかにかかわらず)証明書の生成を検討する前に、証明書を検証する方法を決定する必要があります。2つのデスクトップアプリケーションのコンテキストでは、サーバー証明書を検証する従来の方法は適切でない場合があります。

証明書の目的は、中間者攻撃を防ぐために、リモートパーティのIDを確認する方法を提供することです。検証側は、すでに信頼しているものを使用してこの検証を行います。そうしないと、証明書を使用しても意味がありません。

従来のモデル(固定サーバーを使用)では、サーバー証明書はPKIの一部であり、CAによって発行されます。クライアントは、信頼する一連のCA証明書に対してその信頼性を検証します(通常、RFC 5280で説明されているルールを使用し、証明書が探しているホスト名に対して有効であることを検証します(これがどのように行われるかはプロトコルによって異なりますが、最適です)。および過去の慣行はRFC6125に記載されいます)。MITM攻撃を防ぐには、両方の手順が必要です。これは、パスポートを使用して誰かの身元を確認するのと似ています。パスポートが本物であり、信頼できる機関からのものであることを確認し、確認する必要があります。名前(または写真)が探している名前(または目の前の顔)と一致していること。

2つのデスクトップアプリケーション間の通信を確立する場合、確かに両方の側面で問題が発生します。証明書が信頼できるエンティティによって発行され、通信するエンティティに発行されたことをクライアントに確認させる方法です。プログラムでどちらの側も証明書を生成しない場合、証明書は確実に自己署名されます。これにより、別の交換手段(このSSL / TLS通信とは関係ありません)がないと、反対側からの証明書の信頼性を検証できなくなります。さらに、デスクトップには固定のホスト名がない傾向があるため、DNSベース(またはIPアドレス)の識別子はこのコンテキストでは不十分な場合があります。

リモートパーティが証明書を信頼していることを確認できる方法で証明書を公開する方法を考え、証明書が適切なエンティティに属していることを確認するための識別スキームを考える必要があります(これは通常、証明書のサブジェクトDNまたはサブジェクト代替名の拡張子)。

これらの決定を行ったら、BouncyCastleorg.bouncycastle.x509.X509V3CertificateGeneratorを使用して証明書を生成できます(X.509 v3証明書を使用すると、必要に応じて、キーの使用目的などで証明書に拡張機能を追加できます)。BouncyCastle wikiには、さまざまな例(v1、v3、および/または自己署名、つまりSubject = Issuerの場合)があります。残念ながら、これを使用するのは簡単なことだと思います(信頼の管理面が最も難しいでしょう)。

両方のデスクトップアプリケーションが実際には両方ともより中央のアプリケーションの一部である場合、アプリケーション内で生成された証明書要求(CSR)から、この証明書を発行するサービスを実行できます。中央サーバーは独自のCAを効果的に実行し、デスクトップアプリケーションはそのCAを信頼します。組織の複雑さに応じて、これを行うために利用できるツールがあります。または、同じクラスを使用してBouncyCastleを使用して実装することもできます(証明書を取り消すことができるようにCRL / OSCPを実装した場合はさらに良いでしょう)。この場合、アプリケーションにCSRを生成させ、それを中央CAに送信することができます。CSRは、BouncyCastleを使用して生成できます。PKCS10CertificationRequest。繰り返しになりますが、外部情報を使用してCSRが適切な関係者からのものであることをCAがどのように検証するかは、管理上の問題でもあります。おそらく、電子メール検証スキームなどに関連付けることができます。

証明書を生成すると、 JavaのJSSEをSSL / TLSスタックとして使用できるようになります(通常はを使用しますSSLSocket)。証明書の検証を実装するには、カスタムを使用する必要がある場合がありX509TrustManagerます(従来のCAモデルを使用できない場合は、証明書を検証するためのスキームの設計方法によって異なります)。check*メソッドで何もしないトラストマネージャーを使用しないように注意してください。これにはいくつかの例があります。この場合、証明書を検証するために何もしなければ、証明書をまったく使用しない方がよいでしょう(これにより、接続がMITM攻撃に対して脆弱になります)。

于 2012-09-09T17:47:47.393 に答える
1

JCEベースのソリューションをSSLSocket、jdk6のドキュメント、およびその実装で使用できます:SSLSocketImpl。

Java SSL SSH:

SSHプロトコルを使用して任意のサーバーに接続するためのJschlibがあります。

SSL用のJavaツールボックス:

弾力がある城があります。それらのリソースドキュメントを見てください。wikiは、最新リリースでいくつかの有用な例を提供します。

ContentSigner sigGen = ...;
PublicKey publicKey = ....;

Date startDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
Date endDate = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000);

X509v1CertificateBuilder v1CertGen = new JcaX509v1CertificateBuilder(
          new X500Principal("CN=Test"), 
          BigInteger.ONE, 
          startDate, endDate, 
          new X500Principal("CN=Test"), 
          publicKey);

X509CertificateHolder certHolder = v1CertGen.build(sigGen);
于 2012-09-09T14:21:46.450 に答える