Nginx Tomcat構築httpsサービスsslサポート改善

10990 ワード

アップルの暗号化アルゴリズムに対する要求のため
ATSは、サーバがトランスポート層セキュリティ(TLS)プロトコル1.2以上のバージョンをサポートする必要がある.証明書はSHA 256以上のハッシュアルゴリズムを使用して署名する必要があります.2048ビット以上のRSAキーや256ビット以上のECCアルゴリズムなどを使用する必要があります.条件を満たさない証明書では、ATSは接続を拒否します.
前の文章で構築した自己署名証明書の暗号化アルゴリズムが低すぎて要求に合わないので、この文章を改善します.
1.openssl genrsa -aes256 -out ca.key 8192
2.openssl req -sha256 -new -x509 -days 1826 -key ca.key -out ca.crt
3.openssl pkcs12 -export -clcerts -in ca.crt -inkey ca.key -out root.p12
4.keytool -import -v -trustcacerts -storepass holly.wang -alias root -file ca.crt -keystore root.jks

証明書関連の東東(SSL(TLS)、X.509、PEM、DER、CRT、CER、KEY、CSR、P 12など)についてお話しします
SSL
Secure Sockets Layerは、現在は「TLS」と呼ぶべきですが、習慣の問題のため、私たちはやはり「SSL」と呼ぶことが多い.httpプロトコルはデフォルトではコンテンツを暗号化しません.これにより、コンテンツ伝播時に他の人に傍受される可能性が高いので、セキュリティの要求が高い場合は暗号化しなければなりません.httpsは暗号化されたhttpプロトコルを持っていますが、httpsの暗号化はSSLに基づいています.それは1つの比較的に下層の暗号化を実行して、つまり、暗号化の前で、あなたのサーバーのプログラムは何をして、暗号化の後で同様に何をして、動かないで、この暗号化はユーザーと開発者にとってすべて透明です.
OpenSSL
OpenSSLはセキュリティソケット層の暗号ライブラリであり、主な暗号アルゴリズム、一般的な鍵と証明書パッケージ管理機能、SSLプロトコルを網羅し、テストやその他の目的で豊富なアプリケーションを提供しています.OpenSSLに重大なセキュリティ・ホールが発生したことが明らかになった後、SSLプロトコルで暗号化されたサイトの多くがOpenSSLというオープンソース・パッケージを使用していることが分かった.OpenSSLの脆弱性はhttpで始まるサイトに影響を与えるだけでなく、ハッカーはこの脆弱性を利用してパソコンに直接「心臓出血」(Heartbleed)攻撃を開始することができる.Windowsには脆弱性のあるOpenSSLコードライブラリを大量に使用しており、ハッカー攻撃でユーザーのパソコンのメモリデータを取り込む可能性があると分析されている.
証明書標準X.509
X.509-これは証明書の標準で、主に証明書に含まれるべき内容を定義します.デジタル証明書のフォーマットはX.509標準に従います.X.509は国際電信連盟(ITU-T)が制定したデジタル証明書の標準である.
コーディングフォーマット
同じX.509証明書には、異なる符号化フォーマットがあるかもしれませんが、現在は以下の2つの符号化フォーマットがあります.PEM-Privacy Enhanced Mail、ApacheとNGINXサーバーはこの符号化フォーマットを使用することに偏っています.テキストフォーマットを開いて、「---BEGIN...」で始まり、「---END...」で終わり、内容はBASE 64符号化です.PEM形式証明書の情報を表示するには、次の手順に従います.
openssl x509 -in certificate.pem -text -noout

DER-Distinguished Encoding Rules、JavaとWindowsサーバはこのような符号化フォーマットを使用する傾向がある.開くとバイナリ形式で、読めない.DER形式証明書の情報を表示する:
openssl x509 -in certificate.der **-inform der** -text -noout

関連ファイル拡張子
CRT-certificateの3文字、証明書の意味、よくあるNGINXシステム、PEM符号化かもしれないし、DER符号化かもしれないし、多くはPEM符号化であるべきだ.CER-それともcertificateか、証明書か、Windowsシステムによく見られる.同様に、PEM符号化かもしれないし、DER符号化かもしれない.多くはDER符号化であるべきだ.KEY-は通常、秘密鍵を格納するために使用される.X.509証明書ではありません.コードは同じです.PEMかもしれません.DER.PEMがKEYを表示する方法かもしれません.
openssl rsa -in mykey.key -text -noout

DERがKEYを表示する方法:
openssl rsa -in mykey.key -text -noout  -inform der

CSR-Certificate Signing Request、すなわち証明書署名要求、これは証明書ではなく、権威ある証明書発行機関に署名証明書を取得する申請であり、その核心内容は公開鍵(もちろん他の情報も付属している)であり、この申請を生成する際に、同時に秘密鍵を生成し、秘密鍵は自分で保管しなければならない.PEMはCSRを表示する方法:
openssl req -noout -text -in my.csr 

DERがCSRを表示する方法:
openssl req -noout -text -in my.csr -inform der

PFX/P 12-predessor of PKCS#12は、ngnixサーバにとって、一般的にCRTとKEYは別々に異なるファイルに格納されていますが、WindowsのIISはそれらを1つのPFXファイルに存在します(したがって、このファイルには証明書と秘密鍵が含まれています)これは安全ではありませんか?いいえ、PFXには通常「パスワードの抽出」があります.中のものを読み出したい場合は、パスワードの抽出を要求し、サービス側p 12フォーマットのルート証明書を生成します.
openssl pkcs12 -export -clcerts -in server-cert.cer -inkey server-key.key -out server.p12

PFX使用時DER符号化PFXをPEM符号化方式に変換
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes

抽出コードの入力を求めるメッセージが表示されます.for-iis.pemは読み取り可能なテキストです.pfxを生成するコマンドは似ています.
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt

このうちCACert.crtはCA(権威ある証明書発行機関)のルート証明書で、ある場合は-certfileパラメータで一緒に持ち込むこともあります.このように見ると、PFXは実は証明書鍵ライブラリです.
JKS-Java Key Storage、これはJavaの特許でOpenSSLとはあまり関係なく、Javaの「keytool」というツールを利用して、PFXをJKSに変えることができます.もちろん、keytoolも直接JKSを生成することができます
 keytool -import -v -trustcacerts -storepass 123456 -alias server -file server-cert.cer -keystore
server.jks

証明書コードの変換
PEMからDER openssl x 509-in cert.crt-outform der-out cert.der DERからPEM openssl x 509-in cert.crt-inform der-outform pem-out cert.pemへ(ヒント:KEYファイルを変換するのも似ていますが、x 509をrsaに、CSRを変換するにはx 509をreqに変更します)
ここでjavaがhttpclientを用いてサービス側に対するhttps要求を実現する第1の方式で証明書を迂回する方式(主にSSLContextを生成する際にすべての証明書に対して信頼方式)を添付する.
/** 
     *      
     *  
     * @param url            
     * @param map        
     * @param encoding     
     * @return 
     * @throws NoSuchAlgorithmException  
     * @throws KeyManagementException  
     * @throws IOException  
     * @throws ClientProtocolException  
     */  
    @SuppressWarnings("deprecation")
    public static String ignoreVerifySSL(String url,String json) {  
        String body = "";  
        try {
            //           https    
            SSLContext sslcontext = createIgnoreVerifySSL();  
      
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext,
                    new String[] { "SSLv3","TLSv1","TLSv1.1", "TLSv1.2" } ,//SSLv3 TLSv1 TLSv1.1 TLSv1.2
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
   
            CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(sslsf).build();
   
            HttpPost httpPost = new HttpPost(url);
            StringEntity stringEntity = new StringEntity(json);
            httpPost.setEntity(stringEntity);
            httpPost.setHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
    
            //      ,     (    )  
            CloseableHttpResponse response = client.execute(httpPost);  
            //        
            HttpEntity entity = response.getEntity();  
            if (entity != null) {  
                //            String    
                body = EntityUtils.toString(entity, HTTP.UTF_8);
            }  
            EntityUtils.consume(entity);  
            //      
            response.close();  
        } catch (ParseException | IOException | KeyManagementException | NoSuchAlgorithmException e) {
            log.error(e);
        }
        return body;  
    }
    
    /** 
     *      
     *   
     * @return 
     * @throws NoSuchAlgorithmException  
     * @throws KeyManagementException  
     */  
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {  
        SSLContext sc = SSLContext.getInstance("TLS");  
      
        //     X509TrustManager  ,      ,           
        X509TrustManager trustManager = new X509TrustManager() {  
            @Override  
            public void checkClientTrusted(  
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                    String paramString) throws CertificateException {  
            }  
      
            @Override  
            public void checkServerTrusted(  
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,  
                    String paramString) throws CertificateException {  
            }  
      
            @Override  
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
                return null;  
            }  
        };  
      
        sc.init(null, new TrustManager[] { trustManager }, null);  
        return sc;  
    }

2つ目の方法は、自己署名証明書を信頼することです.
 /** 
     *           
     *   
     * @param keyStorePath            
     * @param keyStorepass            
     * @return 
     */  
    public static SSLContext custom(String keyStorePath, String keyStorepass){  
        SSLContext sc = null;  
        FileInputStream instream = null;  
        KeyStore trustStore = null;  
        try {  
            trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  
            instream = new FileInputStream(new File(keyStorePath));  
            trustStore.load(instream, keyStorepass.toCharArray());  
            //      CA           
            sc = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();  
        } catch (KeyStoreException | NoSuchAlgorithmException| CertificateException | IOException | KeyManagementException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                instream.close();  
            } catch (IOException e) {  
            }  
        }  
        return sc;  
    }
    /** 
     *      
     *  
     * @param url            
     * @param map        
     * @param encoding     
     * @return 
     * @throws ParseException 
     * @throws IOException 
     * @throws KeyManagementException  
     * @throws NoSuchAlgorithmException  
     * @throws ClientProtocolException  
     */  
    public static String send(String url, String json,String encoding) throws ClientProtocolException, IOException {  
        String body = "";  
          
        //tomcat           ,           
        //      ,  "nopassword"    
        SSLContext sslcontext = custom("D:\\work\\jiezhike\\root.jks", "holly.wang");  
          
      /* //     http https     socket         
       Registry socketFactoryRegistry = RegistryBuilder.create()
               .register("http", PlainConnectionSocketFactory.INSTANCE)  
               .register("https", new SSLConnectionSocketFactory(sslcontext))  
               .build();  
       PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);  
       HttpClients.custom().setConnectionManager(connManager);  */
       
       // Allow TLSv1 protocol only
       SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
               sslcontext,
               new String[] { "SSLv3","TLSv1","TLSv1.1", "TLSv1.2" } ,//SSLv3 TLSv1 TLSv1.1 TLSv1.2
               null,
               SSLConnectionSocketFactory.getDefaultHostnameVerifier());
      
           //      httpclient    
//        CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();  
        CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(sslsf).build();  
//      CloseableHttpClient client = HttpClients.createDefault();  
          
        //  post      
        HttpPost httpPost = new HttpPost(url);
        StringEntity stringEntity = new StringEntity(json);
        httpPost.setEntity(stringEntity);
        httpPost.setHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
        
        //      ,     (    )  
        CloseableHttpResponse response = client.execute(httpPost);  
        //        
        HttpEntity entity = response.getEntity();  
        if (entity != null) {  
            //            String    
            body = EntityUtils.toString(entity, encoding);  
        }  
        EntityUtils.consume(entity);  
        //      
        response.close();  
        return body;  
    }