HTTPSの証明書の問題を優雅に処理する方法
12379 ワード
JavaでHTTPSが遭遇する問題自己署名HTTPSサイト にアクセス高バージョンJREアクセスSSLv 3/SSLv 2サイト 一部の銀行インタフェースはkeystoreをロードする必要があるシーン *SSLの歴史を知るにはこの記事もご覧ください.
1自己署名のHTTPSサイトへのアクセス
よく見られる答えは、すべてを信頼することで支持されているが、これは優雅ではない.エレガントな操作:サービス側CA証明書 をダウンロードコードでサービス側証明書をロードした後、カスタムSSLContextでターゲットサーバにアクセスする:
2高バージョンJRE SSLv 3/SSLv 2サイトへのアクセス
通常、あなたが得た答えは、
各バージョンのSSLに対するサポート状況
JDK8
JDK7
JDK6
TLS Protocols
TLSv1.2 (default)TLSv1.1TLSv1SSLv3
TLSv1.2TLSv1.1TLSv1 (default)SSLv3
TLS v1.1 (JDK 6 update 111 and above)TLSv1 (default)SSLv3
JSSE Ciphers:
Ciphers in JDK 8
Ciphers in JDK 7
Ciphers in JDK 6
Reference:
JDK 8 JSSE
JDK 7 JSSE
JDK 6 JSSE
Java Cryptography Extension, Unlimited Strength (explained later)
JCE for JDK 8
JCE for JDK 7
JCE for JDK 6
*SSLv 3のサポートは、2015年1月にリリースされたアップグレードパッチでも無効になっています.
そのため、いくつかのバージョンでHTTPSサイトにアクセスできない理由は、次の可能性があります.サービス・エンド・サポートは、ローカルJREでSSLバージョンが無効になっています.たとえば、サービス・エンド・サポートはSSLv 3のみをサポートし、JDKはSSLv 3のサポートをデフォルトでオフにしています. サービス側で使用される
2.1現在のJREでSSLプロトコルが有効であることを確認する
出力:
2.2現在のJREがCipherSutesを有効にしていることを確認する
しゅつりょく
2.3サーバがサポートするSSLプロトコルを確認する
ここでは
サーバが正常であるにもかかわらず、
出力:
出力によれば、
2.4ソリューション
JREは
現在のJREが
もちろん、手動でファイルを変更することで、これらの制限を取り消すことができますが、プログラムが新しい環境に配備されると、正常に動作しない可能性があります.優雅ではありません.優雅な操作は以下の通りです.プロトコルバージョンに従ってJREペアの設定を動的にキャンセルし、JREで関連するSSLプロトコルおよびアルゴリズムの構成項目を管理するのは主に カスタム
これであなたは完璧で優雅にこの問題を解決することができます.
ふろく
[1] HTTPS https://en.wikipedia.org/wiki/HTTPS [2] Obtain a Certificate from Server https://ldapwiki.com/wiki/Obtain%20a%20Certificate%20from%20Server [3] Transport Level Security (TLS) and Java http://www.ateam-oracle.com/tls-and-java/[4] Diagnosing TLS, SSL, and HTTPS https://blogs.oracle.com/java-platform-group/diagnosing-tls,-ssl,-and-https
1自己署名のHTTPSサイトへのアクセス
よく見られる答えは、すべてを信頼することで支持されているが、これは優雅ではない.エレガントな操作:
# 1: DER
# servername
openssl s_client -showcerts -connect self-signed.badssl.com:443 -servername self-signed.badssl.com /dev/null|openssl x509 -outform der >self-signed.badssl.com.der
private SSLContext sslContext(File certificateFile, String certificateType) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(certificateFile);
CertificateFactory cf = CertificateFactory.getInstance(certificateType);
Certificate certificate = cf.generateCertificate(inputStream);
System.out.println("ca=" + ((X509Certificate) certificate).getSubjectDN());
String alias = ((X509Certificate) certificate).getSubjectDN().toString();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry(alias, certificate);
// Create a KeyStore containing our trusted CAs
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy())
.build();
return sslcontext;
} catch (IOException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
} finally {
if (inputStream != null) try { inputStream.close(); } catch (IOException e) { }
}
}
@Test
public void testSelfSign() throws IOException {
File certFile = ResourceUtils.getFile(this.getClass().getResource("/root.cer"));
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLContext(sslContext(certFile, "X.509")) //
.build();
String body = Executor.newInstance(httpclient).execute(Request
.Get("https://self-signed.badssl.com/"))
.returnContent()
.asString();
System.out.println(body);
}
2高バージョンJRE SSLv 3/SSLv 2サイトへのアクセス
通常、あなたが得た答えは、
${JRE_HOME}/lib/security/java.security
ディレクトリの下のいくつかの構成項目を変更することによって、いくつかの不安全なSSLプロトコルバージョンまたはアルゴリズムに対する高バージョンSDKの制限を解除することです.各バージョンのSSLに対するサポート状況
JDK8
JDK7
JDK6
TLS Protocols
TLSv1.2 (default)TLSv1.1TLSv1SSLv3
TLSv1.2TLSv1.1TLSv1 (default)SSLv3
TLS v1.1 (JDK 6 update 111 and above)TLSv1 (default)SSLv3
JSSE Ciphers:
Ciphers in JDK 8
Ciphers in JDK 7
Ciphers in JDK 6
Reference:
JDK 8 JSSE
JDK 7 JSSE
JDK 6 JSSE
Java Cryptography Extension, Unlimited Strength (explained later)
JCE for JDK 8
JCE for JDK 7
JCE for JDK 6
*SSLv 3のサポートは、2015年1月にリリースされたアップグレードパッチでも無効になっています.
そのため、いくつかのバージョンでHTTPSサイトにアクセスできない理由は、次の可能性があります.
JSSE Ciphers
と、ローカルでサポートされているJSSE Ciphers
との共通項がないため、暗号化アルゴリズムが正常に選択できません.2.1現在のJREでSSLプロトコルが有効であることを確認する
@Test
public void sslSupport() throws IOException {
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket soc = (SSLSocket) factory.createSocket();
// Returns the names of the protocol versions which are
// currently enabled for use on this connection.
String[] protocols = soc.getEnabledProtocols();
System.out.println("Enabled protocols:");
for (String s : protocols) {
System.out.println(s);
}
}
出力:
Enabled protocols:
TLSv1
TLSv1.1
TLSv1.2
2.2現在のJREがCipherSutesを有効にしていることを確認する
String[] cipers = soc.getEnabledCipherSuites();
System.out.println("Enabled CipherSutes:");
for (String s : cipers) {
System.out.println(s);
}
しゅつりょく
Enabled CipherSutes:
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
2.3サーバがサポートするSSLプロトコルを確認する
ここでは
nmap
検査をお勧めします.nmap --script ssl-enum-ciphers -p 443 badssl.com
サーバが正常であるにもかかわらず、
Nmap done: 1 IP address (0 hosts up) scanned
に-Pn
のパラメータを使用するように要求された場合:nmap -Pn --script ssl-enum-ciphers -p 443 badssl.com
出力:
Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-01 22:26 CST
Nmap scan report for badssl.com (104.154.89.105)
Host is up (0.32s latency).
rDNS record for 104.154.89.105: 105.89.154.104.bc.googleusercontent.com
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.0:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| TLSv1.1:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
| TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (secp256r1) - C
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 39.91 seconds
出力によれば、
badssl.com
はTLSv1.0
、TLSv1.1
、およびTLSv1.2
を同時にサポートし、現在対応するプロトコルがサポートしている暗号化アルゴリズムも見ることができる.2.4ソリューション
JREは
${JRE_HOME}/lib/security/java.security
でいくつかのアルゴリズムの構成を構成しています.例えば、ローカルの私の${JRE_HOME}/lib/security/java.security
の構成内容は次のとおりです.jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC
現在のJREが
SSLv3
プロトコルおよびRC4
、DES
などのアルゴリズムを無効にすることを示す.もちろん、手動でファイルを変更することで、これらの制限を取り消すことができますが、プログラムが新しい環境に配備されると、正常に動作しない可能性があります.優雅ではありません.優雅な操作は以下の通りです.
jdk.tls.disabledAlgorithms
である.// SSLv3、RC4、DES 3DES_EDE_CBC
static {
String disabledAlgorithms = Security.getProperty("jdk.tls.disabledAlgorithms");
HashSet keys = Sets.newHashSet(disabledAlgorithms.split(", +"));
if (keys.contains("SSLv3")) keys.remove("SSLv3");
if (keys.contains("RC4")) keys.remove("RC4");
if (keys.contains("DES")) keys.remove("DES");
if (keys.contains("3DES_EDE_CBC")) keys.remove("3DES_EDE_CBC");
Security.setProperty("jdk.tls.disabledAlgorithms", StringUtils.join(keys, ", "));
log.debug("SECURITY PROPERTY UPDATED \"jdk.tls.disabledAlgorithms\" = " + Security.getProperty("jdk.tls.disabledAlgorithms"));
}
SSLConnectionSocketFactory
は、低バージョンプロトコルのサポートと互換性があり、JREのデフォルトの制限を突破します.// Allow SSLv3, TLSv1, TLSv1.2 protocol only
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
sslContext,
new String[] { "SSLv3", "TLSv1", "TLSv1.2"},
null,
NoopHostnameVerifier.INSTANCE);
これであなたは完璧で優雅にこの問題を解決することができます.
ふろく
[1] HTTPS https://en.wikipedia.org/wiki/HTTPS [2] Obtain a Certificate from Server https://ldapwiki.com/wiki/Obtain%20a%20Certificate%20from%20Server [3] Transport Level Security (TLS) and Java http://www.ateam-oracle.com/tls-and-java/[4] Diagnosing TLS, SSL, and HTTPS https://blogs.oracle.com/java-platform-group/diagnosing-tls,-ssl,-and-https