Я хочу подключиться к своему серверу через SSL. Поэтому я сгенерировал сертификаты на сервере с помощью следующих команд:
openssl genrsa -out server.pem 2048
openssl req -new -x509 -nodes -sha1 -days 3650 -key server.pem > server.cert
Соединение работает, если я доверяю всем сертификатам на клиенте с помощью TrustManager следующим образом:
X509TrustManager tm = new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
};
Но доверять всем сертификатам я конечно не хочу, а только своим. Я попробовал несколько команд для импорта сертификатов, например:
keytool -import -alias ca -file server.cert -keystore cacerts
Но я всегда получаю эту ошибку:
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
Что мне нужно сделать, чтобы это заработало? Может ли кто-нибудь объяснить шаги, необходимые для человека, не очень знакомого с критополем?
Редактировать: по предложению Донала Феллоуза я попробовал этот подход с пользовательским X509TrustManager, и он работает. Но так ли это безопасно? Если я просто верну "null" в методе "getAcceptedIssuers", он тоже сработает, и я не совсем уверен, почему:
X509TrustManager tm = new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
X509Certificate[] trustedCerts = new X509Certificate[1];
try{
InputStream inStream = new FileInputStream("server.cert");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
inStream.close();
trustedCerts[0] = cert;
}catch(Exception e){
e.printStackTrace();
}
return trustedCerts;
}
@Override
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
boolean match = false;
try{
InputStream inStream = new FileInputStream("server.cert");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
inStream.close();
for(X509Certificate c : chain){
if(c.equals(cert)){
match = true;
}
}
}catch(Exception e){
throw new CertificateException();
}
if(!match)
throw new CertificateException();
}
};