[英]How to trust my self signed certificate
我想通過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
我需要做什么才能使它正常工作? 有人可以為不太熟悉cryto領域的人解釋必要的步驟嗎?
編輯:根據Donal Fellows的建議,我嘗試了使用自定義X509TrustManager的方法,並且該方法有效。 但是這樣安全嗎? 如果我只是在方法“ getAcceptedIssuers”中返回“ null”,它也可以正常工作,而我不確定為什么:
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();
}
};
如果您確實要限制一切,則可以通過安裝自定義X509TrustManager
進行測試,該測試將測試所使用的證書是否等於您認為應該的證書(您肯定知道;已經生成了該證書)。 這實際上是相當安全的,但是完全沒有操作靈活性。 如果服務器受到威脅,並且您必須重新生成密鑰,則所有客戶端也將需要更新。
因為這確實很煩人(並且無法擴展到WWW之類的功能),所以使用信任根更為正常。 信任根是一個自簽名的CA證書,通常具有很長的壽命,用於對部署到服務器的工作證書進行簽名。 (您可以使用CA證書本身,但通常最好將其保持脫機狀態,最好將其保存在防火安全的可移動媒體上。)然后,將CA證書放入客戶端上的信任庫(即僅保存證書的密鑰庫)中。並告訴Java使用它。
在實踐中,您快到了。 您可能只需要告訴Java使用cacerts
信任庫即可。 您可以通過設置正確的系統屬性來實現 。
// Be careful on Windows; this property (unusually!) uses “/” instead of “\”
System.setProperty("javax.net.ssl.trustStore", "/path/to/cacerts");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.