2011-08-28 65 views
10

セキュアソケットレイヤー(HTTPS)を使用してJavaのPHPスクリプトとの接続を確立しようとしていますが、最大限のセキュリティ/有効性を確保するために、SSL証明書をインポートする必要があります私のウェブサイトが私のアプリケーションに使用する...私は何をするか分からない。Java証明書とSSL証明書

私のSSL証明書は自己署名されておらず、むしろStartSSLで提供されています。私はEclipse IDEを使用しています。

誰かが正しい方向に向いていますか?つまり、どのファイルが必要なのですか、どこでインポートする必要がありますか、Javaなどで必要なコードは何ですか?

+0

証明書をインポートせずに動作する場合は、セキュリティがどのように確保されるかはわかりません。 Webサイト証明書をインポートします。 JavaがStartSSLを有効な認証局として認識できなかったため、証明書をインポートする必要がある場合はStartSSLのルート証明書で、Webサイト証明書はインポートできません。 –

+0

@JBああ。以前の質問では、虚偽のサービスに話していることを確認するためにクライアントのサーバの証明書を検証し、keytoolについて何か言及しておく必要があるとChubbardが言ったからです。だから、ウェブサイトの証明書をインポートしてもセキュリティに影響を与えないと言ったら、誰がSSL証明書をインポートするのですか? – Andy

+1

ブラウザと同じように、Webサイトの証明書を検証するJavaのSSLスタックです。あなたが訪問したすべてのSSLウェブサイトの証明書をインポートしますか?いいえ。ブラウザは、ブラウザが認識している既知の認証局によって認証されているため、証明書を検証します。 StartSSLは、あなたの場合の認証局です。 Javaも同じことをします。 StartSSLの証明書はインポートする必要がありますが、Webサイトの証明書はインポートする必要があります。 –

答えて

24

私は私のウェブサイトは、あなたがその文を作るときは、部分的に正しいです私のアプリケーション

に使用するSSL証明書をインポートする必要がmaxiumセキュリティ/妥当性を確保するためのことを見出しました。 SSL証明書をインポートする必要はありません。 StartSSL CA証明書をインポートすれば十分です。

さらに、証明書をJavaアプリケーションにインポートすることはありません。 JavaのSSLサポートは、キーストアとトラストストアという概念に依存しており、アプリケーション内にパッケージされている一部の証明書には依存しません。エンドユーザーがダウンロードして実行するようにアプリケーションを公開している場合は、証明書を発行する必要はなく、アプリケーションの秘密鍵も公開する必要はありません。秘密鍵と関連する証明書は、あなただけがアクセスできるキーストアに格納されます。

アプリケーションのエンドユーザーは、サーバー証明書が検証された後にアプリケーションがSSL接続を確立できるように、Javaランタイム内のSSLサポートに依存します。 Javaランタイムは、トラストストアにデフォルトのCA証明書セットを同梱しており、SSL接続が正常に確立するための唯一の前提条件は、サーバーのSSL証明書がトラストストアのいずれかのCAによって発行されることです。 StartSSLの証明書は、したがって、少なくともバージョン6のように、Javaランタイムのトラストストアには存在しない、と:

  • あなたはStartSSL CA証明書のインポートの活動を実行するためにエンドユーザーに指示することができJavaトラストストアに追加します。 this StartSSL forum thread(CA証明書をトラストストアにインポートするためには、最初の4つのステップのみが必要です)、a GitHub project、およびthis blog postが含まれています。免責事項 - 私はそれらのいずれかを使用しようとしていないし、あなた自身の責任でそれを使用するべきです。
  • それとも、あなたは-Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> JVMの起動フラグを使用して、独自のトラストストアを使用してアプリケーションを初期化、またはSSL接続を初期化する前に、次のコードを実行する可能性:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>"); 
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>"); 
    

    これは、アプリケーションがAである場合にのみ実行可能なアプローチでありますアプレットではないJava SEアプリケーション(またはトラストストアの指定方法に同様の制限があるアプリケーション)。


またJava keytool documentationを読むために役立つだろう。

+0

あなたの有益な「洞察力のある」答えをありがとう!基本的に言えば、私はStartSSLのCA証明書をインポートする必要があるだけで、セキュリティを確保する必要がありますか?私が正しいとすれば、あなたが提供したリンクはエンドユーザーにのみ適用され、証明書は自分のソフトウェアと共に配布されませんが、2番目の箇条書きの方法はStartSSLのCA証明書が常にそこにあり、何もする必要はありませんか?なぜなら私の顧客がStartSSLのCA証明書をインポートしなければならないからです。 – Andy

+0

CA証明書は複数の目的に使用できます。 StartSSLによって発行されたサイト証明書でHTTPS経由のサイトを提供するTomcatのようなJavaサーバーの場合は、サイト証明書を持つキーストアと、StartSSL CA証明書を持つ* truststoreが必要です。ブラウザやJavaアプリケーションのようなSSLクライアントは、トラストストア(またはトラストを検証するために使用されるもの)内にStartSSL CA証明書しか持たないようにする必要があります。したがって、エンドユーザはCA証明書をcacertsファイルにインポートする必要があり、アプリケーションによる接続は安全です。 –

+0

...違いがあるかどうかは分かりませんが、launch4jを使用してJREをアプリケーションに配布して、Javaをインストールした顧客に依存する必要はありません。それで、StartSSLのCA証明書もJREと一緒にパッケージ化されているのでしょうか? – Andy

0

次の記事をご覧ください。http://stilius.net/java/java_ssl.php コードからスクリプトにアクセスしようとしている場合に役立つコード例が含まれています。私はmaxiumを確保するためのものを見出した

+0

ご回答ありがとうございます@ Sergey。残念ながら、私はすでにあなたが提案した記事を見ていました。もう少し長く勉強すれば役に立つかもしれませんが、これは全く新しいテーマですので、少し時間がかかりますが、私はそれを言いたくはありませんが、ここで最も簡単な方法を探していました。幸いにも、私はVineetとの議論で私にとって最善の方法を発見しましたが、とにかく感謝します! – Andy

0

あなたのどちらかがkeytoolツールを使って、JVMにSSL証明書を渡すか、JREのキーストアにインポートするために、システムのプロパティ

javax.net.ssl.keyStore 
javax.net.ssl.keyStorePassword 

を使用する必要があります

注意セキュリティ/有効性私は SSL証明書をインポートする

いいえあなたはしていません。クライアントがサーバー証明書の署名者をまだ信頼していない場合は、サーバー証明書が自己署名または署名されている場合にのみ発生します。内部CAによって

+0

ありがとうございました。しかし残念ながら私は既に証明書をインポートしていますが、それは今のところ必要でしたが、私のクライアントがサーバー証明書の署名者を信用できないかどうかを知るにはどうすればよいですか? 'Htttpsurlconnection'を使用している場合のアプリケーションですか? – Andy

+0

@Andyあなたが最初に持っていたのと同じ例外が発生します。 – EJP

1

次のメソッドは、デフォルト(cacerts)キーストアを読み込み、証明書がインストールされているかどうかを確認し、インストールされていない場合はインストールします。任意のサーバー上で手動でkeystoreコマンドを実行する必要はありません。

デフォルトのキーストアパスワード(changeit)は変更されていないものとします。更新しない場合はCACERTS_PASSWORDとします。このメソッドは証明書を追加した後にキーストアを保存するので、一度実行すると証明書は永久にストアに保存されます。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.cert.Certificate; 
import java.security.cert.CertificateException; 
import java.security.cert.CertificateFactory; 

/** 
* Add a certificate to the cacerts keystore if it's not already included 
*/ 
public class SslUtil { 
    private static final String CACERTS_PATH = "/lib/security/cacerts"; 

    // NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG 
    // DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE 
    // ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO! 
    private static final String CACERTS_PASSWORD = "changeit"; 

    /** 
    * Add a certificate to the cacerts keystore if it's not already included 
    * 
    * @param alias The alias for the certificate, if added 
    * @param certInputStream The certificate input stream 
    * @throws KeyStoreException 
    * @throws NoSuchAlgorithmException 
    * @throws CertificateException 
    * @throws IOException 
    */ 
    public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream) 
      throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{ 
     //get default cacerts file 
     final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH); 
     if (!cacertsFile.exists()) { 
      throw new FileNotFoundException(cacertsFile.getAbsolutePath()); 
     } 

     //load cacerts keystore 
     FileInputStream cacertsIs = new FileInputStream(cacertsFile); 
     final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType()); 
     cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray()); 
     cacertsIs.close(); 

     //load certificate from input stream 
     final CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
     final Certificate cert = cf.generateCertificate(certInputStream); 
     certInputStream.close(); 

     //check if cacerts contains the certificate 
     if (cacerts.getCertificateAlias(cert) == null) { 
      //cacerts doesn't contain the certificate, add it 
      cacerts.setCertificateEntry(alias, cert); 
      //write the updated cacerts keystore 
      FileOutputStream cacertsOs = new FileOutputStream(cacertsFile); 
      cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray()); 
      cacertsOs.close(); 
     } 
    } 
} 

ので、同じようにそれを使用します。

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt")); 
+0

私のコードでは、java.io.FileNotFoundExceptionが発生します。C:\ Program Files(x86)\ Java \ jre1.8.0_45 \ lib \ security \ cacerts(アクセスは拒否されています)固有のエイリアス(starttlsではなく)とfileInputStreamを使用してインポートします。私の証明書はHTTPSサーバ(www.gmx.at)から来た – lumo

+0

ありがとう!このポストはキーストアの読み方に役立ちました。 – rray

+0

質問:あなたのコードにパスワードをプレーンテキストとして保存するのは非常に大きなセキュリティホールではありませんか?それとも、SSL接続に関しては関係ありませんか? – Flaom

2

どうやら何らかの理由でmailgunエンジニアが私たちにこの問題を解決する方法についての明確な指示を与えたくありません。これは私がやったことです

私たちはtomcat8を実行し、ジャージーWebサービス経由でmailgun APIに接続します。私はこのユーザーの指示に従って、うまくいきました。これが誰かを助けることを望みます。

1/22に、シマンテックのPKIインフラストラクチャが信頼できなくなるため、SSL証明書が更新されました。古いバージョンのJavaには、「DigiCert Global Root G2」CAがありません。

いくつかのオプションがあります。

は、あなたの "のcacerts" ファイルに "DigiCertグローバルルートG2" CAをインポートします。 JREをこのルートを含む8u91(またはそれ以上)にアップグレードします。 「DigiCert Global Root G2」をインポートするにはhttps://www.digicert.com/digicert-root-certificates.htmからルートをダウンロードできます。正しいルート証明書をダウンロードしていることを確認してください。

証明書がダウンロードされたら、次のようなコマンドを使用してにインポートする必要があります:

のkeytool -import -trustcacerts -keystore /パス/に/ cacertsに-storepass changeitと-noprompt -alias digicert -global-root-g2 -file /path/to/digicert.crt Javaキーストアのパスと、ダウンロードしたルート証明書の場所を設定する必要があります。


ので 1. /path/to/digicert.crtはあなただけでダウンロードしたファイルです。 2。/ path/to/cacerts - これはあなたのJREパスにあります。私は "/ -name cacerts -print"を見つけると、ファイルシステム上のすべてのJava cacertsをすばやく見つけるのに役立ちます。