Java 和 SSL 证书

发布于 2024-12-02 04:16:06 字数 296 浏览 6 评论 0原文

我正在尝试使用安全套接字层 (HTTPS) 与我的 Java 中的 PHP 脚本建立连接,但我发现为了确保最大的安全性/有效性,我必须将我的网站使用的 SSL 证书导入到我的应用程序中……有些事情我不知道该怎么办。

如果有帮助的话,我的 SSL 证书不是自签名的,而是由 StartSSL 提供的,并且我正在使用 Eclipse IDE。

有人能指出我正确的方向吗?即我需要什么文件,我应该在哪里导入它们以及我需要什么Java代码等等?

I am trying to establish a connection with a PHP script of mine in Java using the secure socket layer (HTTPS), but I have found out that to ensure maximum security/validity I have to import the SSL certificate that my website uses into my application... Something I don't know how to do.

If it helps, my SSL Certificate is not self signed, rather provided by StartSSL AND I am using Eclipse IDE.

Could anybody point me in the right direction? i.e. What files do I need, where should I import them and what code do I need in Java, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

陈独秀 2024-12-09 04:16:06

我发现为了确保最大的安全性/有效性,我必须将我的网站使用的 SSL 证书导入到我的应用程序中

当您做出该声明时,您说得部分正确。您不需要导入 SSL 证书。导入 StartSSL CA 证书就足够了。

此外,不存在将证书导入 Java 应用程序之类的事情。 Java 中的 SSL 支持依赖于密钥库和信任库的概念,而不依赖于应用程序中打包的某些证书​​。如果您要发布应用程序以供最终用户下载和执行,则无需在应用程序中发布您的证书或私钥。私钥和关联的证书将存储在密钥库中,只有您可以访问。

应用程序的最终用户将依赖 Java 运行时中的 SSL 支持,这将使应用程序能够在验证服务器证书后建立与站点的 SSL 连接。 Java 运行时在信任库中附带了一组默认的 CA 证书,成功建立 SSL 连接的唯一先决条件是服务器的 SSL 证书由信任库中的 CA 之一颁发。 至少从版本 6 开始,Java 运行时的信任库中不存在 StartSSL 的证书,因此:

  • 您可以指示最终用户执行导入活动将 StartSSL CA 证书添加到 Java 信任库中。可能有帮助的链接包括此 StartSSL 论坛主题(仅限第一个将 CA 证书导入信任库需要 4 个步骤)、GitHub 项目这篇博文;免责声明 - 我没有尝试使用其中任何一个,您应该自行承担使用它的风险。
  • 或者,您可以使用 -Djavax.net.ssl.trustStore=使用您自己的信任库初始化应用程序-Djavax.net.ssl.trustStorePassword= JVM启动标志,或者在初始化SSL连接之前执行以下代码:

    System.setProperty("javax.net.ssl.trustStore","");
    System.setProperty("javax.net.ssl.trustStorePassword","");
    

    仅当您的应用程序是 Java SE 应用程序且恰好不是小程序(或者在指定信任库时具有类似限制的应用程序)时,这才是可行的方法。


阅读 Java keytool 文档。

I have found out that to ensure maxium security/validity I have to import the SSL certificate that my website uses into my application

You are partially right when you make that statement. You do not need to import your SSL certificate. It is sufficient that the StartSSL CA certificate be imported.

Additionally, there is no such thing as importing a certificate into a Java application. SSL support in Java relies on the concept of keystores and truststores, and not on some certificate packaged within your application. If you are publishing your application to be downloaded and executed by end-users, there is no need for your to publish your certificate or for that matter your private key in your application. The private key, and the associated certificate would be stored in a keystore, that only you may access.

The end-users of your application would rely on the SSL support within the Java runtime, that would enable the application to establish SSL connections to sites, after the server-certificate is verified. The Java runtime ships with a default set of CA certificates in a truststore, and the only prerequisite for SSL connections to be successfully established is that the SSL certificate of the server be issued by one of the CAs in the truststore. The certificates of StartSSL are not present in the truststore of the Java runtime, atleast as of version 6, and therefore:

  • You could instruct your end users to perform the activity of importing the StartSSL CA certificate into the Java truststore. Links that may help include this StartSSL forum thread (only the first 4 steps are needed to import the CA certs into a truststore), a GitHub project, and this blog post; a disclaimer - I haven't attempted using any of those and you ought to be using it at your own risk.
  • Or, you could initialize your application with your own truststore using the -Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password> JVM startup flags, or execute the following code before initializing SSL connections:

    System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>");
    System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
    

    This is a viable approach only if your application is a Java SE application that does not happen to be an applet (or an application with similar restrictions on how the truststore is specified).


It would also help to read up the Java keytool documentation.

屌丝范 2024-12-09 04:16:06

以下方法加载默认 (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"));

The following method loads the default (cacerts) keystore, checks to see if a certificate is installed, and installs it if not. It eliminates the need to manually run the keystore command on any servers.

It assumes that the default keystore password (changeit) is unchanged, update CACERTS_PASSWORD if not. Note that the method saves the keystore after adding a certificate, so after being run once the certificate will permanently be in the store.

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();
        }
    }
}

Use it like so:

SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));
您的好友蓝忘机已上羡 2024-12-09 04:16:06

显然,邮件枪工程师出于某种原因不想向我们提供有关如何解决此问题的明确指示。这就是我所做的

我们运行 tomcat8 并通过 jersey Web 服务连接到 mailgun API。我按照这个用户的说明进行操作,效果很好。希望这对某人有帮助。

1 月 22 日,由于赛门铁克的 PKI 基础设施将变得不受信任,我们更新了 SSL 证书。某些旧版本的 Java 没有“DigiCert Global Root G2”CA。

有多种选择:

将“DigiCert Global Root G2”CA 导入到“cacerts”文件中。
将您的 JRE 升级到 8u91(或更高版本),其中包括此根目录。
要导入“DigiCert 全局根 G2”,您可以从 https://www 下载根.digicert.com/digicert-root-certificates.htm。确保您下载的是正确的根证书。

下载证书后,您需要使用如下命令将其导入:

keytool -import -trustcacerts -keystore /path/to/cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file /路径/到/digicert.crt
您需要设置 Java 密钥库的路径以及下载的根证书的位置。


所以
1. /path/to/digicert.crt 是您刚刚下载的文件。
2. /path/to/cacerts - 这位于您的 JRE 路径中。我“find / -name cacerts -print”这将帮助您快速找到文件系统上的所有java cacert。对我来说是 /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/cacerts

Apparently the mailgun engineers for some reason don't want to give us clear instructions on how to solve this. This is what I did

We run tomcat8 and connect via jersey web services to the mailgun API. I followed this users instructions and it worked fine. Hope this helps someone.

On 1/22, we updated our SSL certificates due to Symantec's PKI infrastructure set to become untrusted. Some older versions of Java do not have the "DigiCert Global Root G2" CA.

There are several options:

Import the "DigiCert Global Root G2" CA into your "cacerts" file.
Upgrade your JRE to 8u91 (or higher), which includes this root.
To import the "DigiCert Global Root G2" You can download the root from https://www.digicert.com/digicert-root-certificates.htm. Ensure you are downloading the correct root certificate.

Once the certificate is downloaded, you'll need to import it into with a command like the following:

keytool -import -trustcacerts -keystore /path/to/cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file /path/to/digicert.crt
You will need to set the path to your Java Keystore and the location of the root certificate you downloaded.


So
1. /path/to/digicert.crt is the file you just downloaded.
2. /path/to/cacerts - This is in your JRE path. I "find / -name cacerts -print" this will help you quickly find all the java cacerts on your filesystem. For me it was /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/cacerts

水溶 2024-12-09 04:16:06

看看下面的文章: http://stilius.net/java/java_ssl.php
它包含代码示例,如果您尝试从代码访问脚本,它可能会有所帮助。

请注意,您应该使用系统属性

javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

将 SSL 证书传递到 JVM,或者使用 keytool 工具

Have a look at the following article: http://stilius.net/java/java_ssl.php
It contains code example which may help in case if you are trying to access your script from code.

Note that you either should use system properties

javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

to pass the SSL certificate to JVM or import it into JRE keystore by using keytool tool

鹤舞 2024-12-09 04:16:06

我发现为了确保最大的安全性/有效性,我必须
导入SSL证书

不,您不需要。仅当您的客户端尚未信任服务器证书的签署者时才需要执行该步骤,只有当服务器证书是自签名或由内部 CA 签名时才会出现这种情况。

I have found out that to ensure maxium security/validity I have to
import the SSL certificate

No you don't. You only need that step if your clients don't already trust the signer of the server certificate, which only arises if the server certificate is self-signed or signed e.g. by an internal CA.

神经暖 2024-12-09 04:16:06

该文章包含用于更改信任存储密码并在其中添加其他证书的代码:

thetechawesomeness。 ideasmatter.info

That article contains the code for changing trust store's password and adding other certificates there:

thetechawesomeness.ideasmatter.info

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文