Javaでhttps通信時の証明書検証について †JavaからHTTP接続する際に行われる検証 †https接続する際には、以下の2つの検証が行われる。 (1) 証明書/認証局の検証 ・・・ 有効な証明書か。(信頼できる認証局によって署名された証明書か) 検証を通過させる為のコード †テスト環境等で、まっとうな証明書がインストールされたサーバがない場合、以下のように証明書の検証をスルーする事ができる。 以下は、Android関連の注意換気、ガイド等 /** * HTTPS通信 */ private void sendHttpsRequest(String uri, String method, Map param) { URL urlObj = new URL(uri); HttpURLConnection http = (HttpsURLConnection) urlObj.openConnection(); // デフォルトのホスト名検証ルールを設定 setDefaultHostnameVerifier(); // 証明書情報を取得 TrustManager[] tm = getTrustManager(); SSLContext sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(null, tm, null); // 空の証明書情報が設定されたオブジェクトをセット ((HttpsURLConnection) http).setSSLSocketFactory(sslcontext.getSocketFactory()); . . . } /** * 信頼する証明書情報を取得する。<br /> * @return 証明書情報 */ private TrustManager[] getTrustManager() { TrustManager[] tm = {new X509TrustManager() { @Override public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { // 何も検証しない } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { // 何も検証しない } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { // 証明書情報として空を返す(つまり検証を行わない) return null; } } }; return tm; } /** * https通信時のデフォルトのホスト名検証ルールを設定する<br /> */ private void setDefaultHostnameVerifier() { // テスト用なので全てtrueを返す(つまり検証を行わない) HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); } 検証を通過させる為のコードを書かない為のテスト環境構築 †上記のコードを書かない為に、できるだけ本番に近い環境構築を行う方法を記載する。 署名用の自己認証局(CA)の作成 †mkdir -p /var/certs/myCA cd /var/certs/myCA mkdir private mkdir newcerts chmod 700 private echo 01>serial touch index.txt sudo openssl req -new -x509 -newkey rsa:2048 -out myca.crt -keyout private/myca.key -days 365 -sha256 ・ いろいろ聞かれるので入力する。 ・ 証明書情報の Organization Name が認証局と一致していなくても署名できるようにする。 †※オリジナルの openssl.cnf からコピーして作成する。 cd /var/certs cp /etc/ssl/openssl.cnf ./ ↓旧メモ [ CA_default ] #dir = ./demoCA dir = ./myCA [ policy_match ] #organizationName = match organizationName = optional ↓新メモ [ca] default_ca = my_ca_default [my_ca_default] new_certs_dir = ./myCA/newcerts database = ./myCA/index.txt serial = ./myCA/serial policy = my_ca_policy default_md = md5 default_days = 365 [my_ca_policy] commonName = supplied countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional emailAddress = optional URLにIPアドレスを指定してアクセスする場合は以下の設定も追記 vim openssl.cnf [ v3_req ] subjectAltName = @alt_names [ alt_names ] IP.1 = XXX.XXX.XXX.XXX # 実際のIPアドレス サーバ秘密鍵 及び 証明書署名要求(CSR)の作成 †# サーバ秘密鍵の作成 openssl genrsa -des3 -out example_com.key 1024 Generating RSA private key, 1024 bit long modulus .++++++ ...............++++++ e is 65537 (0x10001) Enter pass phrase for example_com.key: Verifying - Enter pass phrase for example_com.key: # サーバ秘密鍵のパスフレーズを解除(Apache自動起動用) openssl rsa -in example_com.key -out example_com_nopass.key Enter pass phrase for example_com.key: writing RSA key # サーバ証明書の署名要求(CSR)を作成 openssl req -new -sha256 -key example_com.key -out example_com.csr ・ ・ いろいろ聞かれるので入力する。 (注意!) Common Name、Organization Name は 実際のドメイン名と合わせておく事。(IPアドレスでアクセスする場合はIPアドレスをそのまま入力) ・ ・ 自己認証局で署名 †sudo openssl ca -config ./openssl.cnf -md sha256 -cert myCA/myca.crt -keyfile myCA/private/myca.key -out example_com.crt -in example_com.csr # IPアドレスでアクセスする場合は引数に -extensions v3_req も追加 #sudo openssl ca -config ./openssl.cnf -md sha256 -cert myCA/myca.crt -keyfile myCA/private/myca.key -out 192.168.1.10.crt -in 192.168.1.10.csr -extensions v3_req ・ ・ Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated Apache設定ファイルの編集 †作成した鍵、サーバ証明書のpathを設定する(他のSSL周りの設定は ApacheでSSL(SNI)設定 等を参照 ) SSLCertificateFile /path_to/example_com.crt SSLCertificateKeyFile /path_to/example_com_nopass.key クライアント端末へのインストール †上記で作成したCA証明書(myca.crt)を対象の端末にインストールする。 |