Java和SSL证书
我正尝试使用安全套接字层(HTTPS)与Java中的PHP脚本建立连接,但我已经发现为确保最大的安全性/有效性,我必须导入SSL证书我的网站用于我的应用程序...我不知道该怎么做。Java和SSL证书
如果有帮助,我的SSL证书不是自签名的,而是由StartSSL提供的,我正在使用Eclipse IDE。
有人能指出我正确的方向吗?即我需要什么文件,我应该在哪里导入它们,以及在Java中需要什么代码等等?
我发现,要保证最大信号的安全性/有效性我要导入我的网站使用SSL证书到我的应用程序
你是正确的部分,当你作出这样的声明。您不需要导入您的SSL证书。导入StartSSL CA证书就足够了。
此外,没有将证书导入到Java应用程序中。 Java中的SSL支持依赖于密钥库和信任库的概念,而不是在应用程序中打包的某些证书上。如果您要发布应用程序以供最终用户下载和执行,则不需要在应用程序中发布您的证书或私钥。私钥和相关证书将存储在密钥库中,只有您可以访问。
您的应用程序的最终用户将依赖于Java运行时的SSL支持,这将允许应用程序在验证服务器证书后建立到站点的SSL连接。 Java运行时会在信任库中附带一组默认的CA证书,并且SSL连接成功建立的唯一先决条件是服务器的SSL证书由信任库中的一个CA颁发。 startssl如果的证书不存在于Java运行时的信任,至少为6个版本,因此:
- 你可以指导你的最终用户执行导入startssl如果CA证书的活动到Java信任库中。可能有帮助的链接包括this StartSSL forum thread(仅需要将前面4个步骤导入CA信任库到信任库),a GitHub project和this blog post;一个免责声明 - 我没有尝试使用任何这些,你应该使用它,风险自负。
-
或者,你可以使用
-Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password>
JVM启动标志用自己的信任初始化应用程序,或初始化SSL连接之前执行以下代码:System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>"); System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
这是唯一的,如果你的应用程序是一个可行的方法Java SE应用程序不会碰巧是一个小程序(或者对指定信任库的方式有类似限制的应用程序)。
这也将有助于阅读了Java keytool documentation。
谢谢您提供的信息丰富且“富有洞察力”的答案!基本上你在说什么,是我应该只需要导入StartSSL的CA证书,然后我应该安全下去?如果我是正确的,那么您提供的链接仅适用于最终用户,并且证书不会与我的软件一起分发,但第二项要点中的方法意味着StartSSL的CA证书将始终存在,并且我的最终用户不需要做任何事情?因为我不想让我的客户必须导入StartSSL的CA证书...... – Andy
CA证书有多种用途;对于像Tomcat这样的可以通过HTTPS为站点提供站点证书的Java服务器,您需要拥有带站点证书的密钥库,以及带有StartSSL CA证书的*信任库。 SSL客户端(如浏览器或Java应用程序)只需在信任库中拥有StartSSL CA证书(或任何用于验证信任的证书)。因此,您的最终用户必须将CA证书导入到cacerts文件中,并且该应用程序所建立的连接将是安全的。 –
......我不知道它是否有所作为,但我计划使用launch4j将JRE与我的应用程序一起分发,这样我就不必依赖我的客户安装了Java。那么,这是否意味着StartSSL的CA证书也可以与JRE一起打包? – Andy
看看下面的文章:http://stilius.net/java/java_ssl.php 它包含代码示例,这可能有助于在您尝试从代码访问您的脚本的情况下。
需要注意的是,你要么应该使用系统属性
javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword
使用keytool工具SSL证书传递到JVM或将其导入到JRE密钥库
谢谢你的回答@Sergey。不幸的是,我已经看过你建议的文章。如果我再研究一下它可能会有所帮助,但这对我来说是一个全新的主题,所以我有时会面临一些压力,所以我讨厌这么说,但我一直在寻找最简单的方法。幸运的是,我发现了与Vineet讨论的最佳方式,但是非常感谢! – Andy
以下方法加载默认(cacerts)密钥库,检查是否安装了证书,如果没有,则安装它。它消除了在任何服务器上手动运行keystore
命令的需要。
它假设默认密钥库密码(changeit)未更改,如果不是,则更新CACERTS_PASSWORD
。请注意,该方法在添加证书后保存密钥库,因此在证书永久存储在商店后运行后。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
/**
* Add a certificate to the cacerts keystore if it's not already included
*/
public class SslUtil {
private static final String CACERTS_PATH = "/lib/security/cacerts";
// NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG
// DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE
// ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO!
private static final String CACERTS_PASSWORD = "changeit";
/**
* Add a certificate to the cacerts keystore if it's not already included
*
* @param alias The alias for the certificate, if added
* @param certInputStream The certificate input stream
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws CertificateException
* @throws IOException
*/
public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
//get default cacerts file
final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH);
if (!cacertsFile.exists()) {
throw new FileNotFoundException(cacertsFile.getAbsolutePath());
}
//load cacerts keystore
FileInputStream cacertsIs = new FileInputStream(cacertsFile);
final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType());
cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray());
cacertsIs.close();
//load certificate from input stream
final CertificateFactory cf = CertificateFactory.getInstance("X.509");
final Certificate cert = cf.generateCertificate(certInputStream);
certInputStream.close();
//check if cacerts contains the certificate
if (cacerts.getCertificateAlias(cert) == null) {
//cacerts doesn't contain the certificate, add it
cacerts.setCertificateEntry(alias, cert);
//write the updated cacerts keystore
FileOutputStream cacertsOs = new FileOutputStream(cacertsFile);
cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray());
cacertsOs.close();
}
}
}
使用它,像这样:
SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));
显然,由于某种原因,mailgun工程师不希望给我们如何解决这个明确的指示。这就是我所做的
我们运行tomcat8并通过球衣web服务连接到mailgun API。我遵循这个用户指示,它工作正常。希望这可以帮助某人。
1/22,由于赛门铁克的PKI基础设施设置为不可信,我们更新了SSL证书。某些旧版本的Java没有“DigiCert Global Root G2”CA.
有几种选择:
导入 “DigiCert全局根G2” CA到您 “的cacerts” 文件。 将您的JRE升级到8u91(或更高版本),其中包含此根目录。 要导入“DigiCert Global Root G2”您可以从https://www.digicert.com/digicert-root-certificates.htm下载根目录。确保您正在下载正确的根证书。
一旦证书下载后,您需要将它与类似如下的命令导入:
的keytool -import -keystore -trustcacerts /路径/到/ cacerts的-storepass的changeit -noprompt -alias digicert -global-root -g2 -file /path/to/digicert.crt 您需要设置Java密钥库的路径以及下载的根证书的位置。
所以 1. /path/to/digicert.crt是您刚刚下载的文件。 2。/ path/to/cacerts - 这是你的JRE路径。我找到/ -name cacerts -print“这将帮助您快速找到文件系统上的所有java cacerts。对我来说,它是/ usr/lib/jvm/java-7 -openjdk-amd64/jre/lib/security/cacerts
如果它在没有导入任何证书的情况下工作,我不会看到如何确保/增加安全性通过导入网站证书。如果必须导入任何证书,则它是StartSSL的根证书,但不是您的网站证书,因为Java无法将StartSSL识别为有效的证书颁发机构。 –
@JB哦。这只是因为在我之前的问题中,chubbard说我应该确保在我的客户端验证服务器的证书,以确保我正在与虚假服务对话,并提到了有关keytool的一些信息。因此,如果您说导入网站证书不影响安全性,为什么有人会导入SSL证书? – Andy
这是Java的SSL堆栈,它将验证网站证书,就像浏览器一样。您在访问之前是否导入了您访问的所有SSL网站的证书?不是。浏览器验证其证书,因为它通过浏览器知道的知名证书颁发机构的认证。 StartSSL是您的案例中的证书颁发机构。 Java做同样的事情。您可能需要导入StartSSL的证书,但不需要导入网站证书。 –