Java에서 인증서 암호화를 지원합니까?
HTTP를 통해 원격 서버에서 REST API를 쿼리하는 Java 애플리케이션을 개발 중입니다. 보안상의 이유로이 통신은 HTTPS로 전환해야합니다.
지금 하자 암호화가 자신의 공개 베타를 시작, 내가 자바는 현재 작동 (또는 미래에 작동하는 확인) 기본적으로 자신의 인증서를 알고 싶습니다.
암호화하자 IdenTrust가 중간 서명을 받았으며 , 이는 좋은 소식입니다. 그러나이 명령의 출력 에서이 두 가지를 찾을 수 없습니다.
keytool -keystore "..\lib\security\cacerts" -storepass changeit -list
각 컴퓨터에 신뢰할 수있는 CA를 수동으로 추가 할 수 있지만 추가 구성 없이도 응용 프로그램을 무료로 다운로드하여 실행할 수 있으므로 "즉시"작동하는 솔루션을 찾고 있습니다. 나에게 좋은 소식이 있습니까?
[ 2016-06-08 업데이트 : https://bugs.openjdk.java.net/browse/JDK-8154757 에 따르면 IdenTrust CA는 Oracle Java 8u101에 포함됩니다.]
[ 업데이트 2016-08-05 : Java 8u101이 릴리스되었으며 실제로 IdenTrust CA가 포함되어 있습니다. 릴리스 정보 ]
Java에서 인증서 암호화를 지원합니까?
예. Let 's Encrypt 인증서는 일반 공개 키 인증서 일뿐입니다. Java는이를 지원합니다 ( Java 7> = 7u111 및 Java 8> = 8u101의 경우 인증서 호환성 암호화 에 따라 ).
Java는 인증서를 즉시 암호화 할 수 있습니까?
아니오 / JVM에 따라 다릅니다. 최대 8u66의 Oracle JDK / JRE 신뢰 저장소에는 구체적으로 Let 's Encrypt CA와이를 서명 한 IdenTrust CA가 없습니다. new URL("https://letsencrypt.org/").openConnection().connect();
예를 들어 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
.
그러나 고유 한 유효성 검증기를 제공하거나 필수 루트 CA가 포함 된 사용자 정의 키 저장소를 정의하거나 인증서를 JVM 신뢰 저장소로 가져올 수 있습니다.
https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 에서도 주제에 대해 설명합니다.
다음은 런타임시 인증서를 기본 신뢰 저장소에 추가하는 방법을 보여주는 예제 코드입니다. 인증서를 추가하기 만하면됩니다 (firefox에서 .der로 내보내고 클래스 경로에 저장).
을 바탕으로 어떻게 자바에서 신뢰할 수있는 루트 인증서 목록을받을 수 있나요? 및 http://developer.android.com/training/articles/security-ssl.html#UnknownCa
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;
public class SSLExample {
// BEGIN ------- ADDME
static {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
Path ksPath = Paths.get(System.getProperty("java.home"),
"lib", "security", "cacerts");
keyStore.load(Files.newInputStream(ksPath),
"changeit".toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (InputStream caInput = new BufferedInputStream(
// this files is shipped with the application
SSLExample.class.getResourceAsStream("DSTRootCAX3.der"))) {
Certificate crt = cf.generateCertificate(caInput);
System.out.println("Added Cert for " + ((X509Certificate) crt)
.getSubjectDN());
keyStore.setCertificateEntry("DSTRootCAX3", crt);
}
if (false) { // enable to see
System.out.println("Truststore now trusting: ");
PKIXParameters params = new PKIXParameters(keyStore);
params.getTrustAnchors().stream()
.map(TrustAnchor::getTrustedCert)
.map(X509Certificate::getSubjectDN)
.forEach(System.out::println);
System.out.println();
}
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
SSLContext.setDefault(sslContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// END ---------- ADDME
public static void main(String[] args) throws IOException {
// signed by default trusted CAs.
testUrl(new URL("https://google.com"));
testUrl(new URL("https://www.thawte.com"));
// signed by letsencrypt
testUrl(new URL("https://helloworld.letsencrypt.org"));
// signed by LE's cross-sign CA
testUrl(new URL("https://letsencrypt.org"));
// expired
testUrl(new URL("https://tv.eurosport.com/"));
// self-signed
testUrl(new URL("https://www.pcwebshop.co.uk/"));
}
static void testUrl(URL url) throws IOException {
URLConnection connection = url.openConnection();
try {
connection.connect();
System.out.println("Headers of " + url + " => "
+ connection.getHeaderFields());
} catch (SSLHandshakeException e) {
System.out.println("Untrusted: " + url);
}
}
}
OP가 로컬 구성을 변경하지 않고 솔루션을 요청했지만 키 체인에 신뢰 체인을 영구적으로 추가하려는 경우 :
$ keytool -trustcacerts \
-keystore $JAVA_HOME/jre/lib/security/cacerts \
-storepass changeit \
-noprompt \
-importcert \
-file /etc/letsencrypt/live/hostname.com/chain.pem
구성 파일 백업을 포함하여 로컬 구성을 변경하려는 사람들을위한 자세한 답변 :
1. 변경 전에 작동하는지 테스트
If you don't have a test program already, you can use my java SSLPing ping program which tests the TLS handshake (will work with any SSL/TLS port, not just HTTPS). I'll use the prebuilt SSLPing.jar, but reading the code and building it yourself is a quick and easy task:
$ git clone https://github.com/dimalinux/SSLPing.git
Cloning into 'SSLPing'...
[... output snipped ...]
Since my Java version is earlier than 1.8.0_101 (not released at the time of this writing), a Let's Encrypt certificate will not verify by default. Let's see what failure looks like before applying the fix:
$ java -jar SSLPing/dist/SSLPing.jar helloworld.letsencrypt.org 443
About to connect to 'helloworld.letsencrypt.org' on port 443
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
[... output snipped ...]
2. Import the certificate
I'm on Mac OS X with the JAVA_HOME environment variable set. Later commands will assume this variable is set for the java installation you are modifying:
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/
Make a backup of the cacerts file we will be modifying so you can back out any change without reinstalling the JDK:
$ sudo cp -a $JAVA_HOME/jre/lib/security/cacerts $JAVA_HOME/jre/lib/security/cacerts.orig
Download the signing certificate we need to import:
$ wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der
Perform the import:
$ sudo keytool -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed -file lets-encrypt-x3-cross-signed.der
Certificate was added to keystore
3. Verify that it is working after the changes
Verify that Java is now happy connecting to the SSL port:
$ java -jar SSLPing/dist/SSLPing.jar helloworld.letsencrypt.org 443
About to connect to 'helloworld.letsencrypt.org' on port 443
Successfully connected
For JDK which do not support Let's Encrypt certificates yet, you can add those to the JDK cacerts
following this process (thanks to this).
Download all the certificates on https://letsencrypt.org/certificates/ (choose the der format) and add them one by one with this kind of command (example for letsencryptauthorityx1.der
):
keytool -import -keystore PATH_TO_JDK\jre\lib\security\cacerts -storepass changeit -noprompt -trustcacerts -alias letsencryptauthorityx1 -file PATH_TO_DOWNLOADS\letsencryptauthorityx1.der
참고URL : https://stackoverflow.com/questions/34110426/does-java-support-lets-encrypt-certificates
'development' 카테고리의 다른 글
C # 정적 클래스 생성자 (0) | 2020.07.20 |
---|---|
MySQL : 주어진 데이터베이스에 열려있는 모든 연결을 보십니까? (0) | 2020.07.20 |
비밀번호로 보호되지 않은 Java 키 저장소에 들어가거나 비밀번호를 변경하려면 어떻게합니까? (0) | 2020.07.20 |
Mercurial 오류 : 사용자 이름을 제공하지 않음 (0) | 2020.07.19 |
bash 루프 목록에서 공백을 어떻게 피할 수 있습니까? (0) | 2020.07.19 |