需要为 SSL 配置 Tomcat7

Need to configure Tomcat 7 for SSL

我正在努力为 SSL 配置 Tomcat,如有任何帮助,我将不胜感激。出于我的目的,我需要创建一个根证书和一个由根证书签名的服务器证书。

为了帮助我理解,我将其分为两个步骤:使用 openssl 创建证书,以及将证书导入 Tomcat 的密钥库。这是我使用 openssl 和 keystore 命令的一系列步骤。

-- Create certficates --
1. Create CA key in private directory:                                               
openssl genrsa -out CA.key 4096
2. Create CA PEM request using CN <Root Name> and CA key:  
openssl req -key ../private/CA.key -new -out CA.req
3. Create CA PEM using Create CA PEM request:                   
openssl x509 -req -days 365 -in CA.req -signkey ../private/CA.key -sha256 -out CA.pem
4. Create server key (encrypted with password):                      
openssl genrsa -des3 -out server.key 4096
5. Create server PEM request using CN <FQDN of Server>:  
openssl req -new -key server.key -out server.req
6. Create server PEM using Create server PEM request:           
openssl x509 -req -days 3650 -in server.req -signkey ../private/CA.key -out server.pem
7. Export CA certificate as PKCS12 file (possibly not necessary):
openssl pkcs12 -export -inkey ../private/CA.key -in CA.pem -out CA.p12 
8. Export server certificate as PKCS12 file:
openssl pkcs12 -export -inkey ../private/CA.key -in server.pem -out server.p12

-- Install certificates --
9. Add CA PEM to server keystore:
keytool -import -trustcacerts -alias root -file CA.pem -keystore keystore.jks
10. Add server PKCS12 to client keystore:
keytool -import -alias server -file server.p12 -keystore KeyStore.jks

在最后一个命令中,我收到此错误消息:

keytool error: java.lang.Exception: Input not an X.509 certificate

我不完全理解 PEM 和 PKCS12 格式之间的关系以及为什么我需要导入 PEM 格式的根证书和 PKCS12 格式的服务器证书 - 也许这就是我出错的地方?

感谢您的帮助。

主要是欺骗 HAProxy SSL termination + client certificate validation + curl / java client .

首先,你的#6是错误的;您不会创建由 CA 签名的服务器证书,而是创建带有服务器名称和 CA 密钥的 self-signed 证书。这就是为什么您的 #8 需要将 'server' 证书与 CA 密钥配对,这通常是没有意义的。在 #6 中使用 -CA-CAkey,并将 8 更改为使用服务器密钥和服务器证书 最好也是 CA 证书(仅)作为 CA 证书 使用 -CA -- 即:

 openssl pkcs12 -export -in server.pem -inkey server.key -CA CA.pem -out server.p12

其次,正如我现在更新的 dupe 中所解释的那样,您可能根本不需要转换为 JKS; Java 经常可以处理 PKCS12。但是,如果这样做,则需要使用 -importkeystore,如此处所示,这是一个单独且不同的操作,而不是 -import[cert]

最后,您的部分困惑可能是由于误用'PEM'造成的。 PEM 不是单一的东西;它是一种可用于多种用途的格式,由包含 5 个连字符的 BEGIN 行、BEGIN 一词、一个或几个标识数据类型的词以及另外 5 个连字符组成;然后是可选的(并且相当罕见)RFC822 样式 header;然后是一行或多行 base64,它对 BEGIN 行指定的任何数据进行编码;然后用 END 代替 BEGIN 的类似行。

PEM 可用于证书(几种格式)、密钥(几种格式)、CSR、CRL、OCSP 请求和响应、多种格式的消息,也许还有其他东西。您命名为“.pem”的文件更准确地说是 PEM 格式的证书;您使用的“.key”和“.req”文件也是 PEM 格式,但不是证书,而是密钥和证书请求 (CSR)。证书文件(PEM 或任何其他格式)和 PKCS12 文件之间的主要区别(请原谅双关语)是 PKCS12 通常包含私钥 证书或(通常) 'chain' 几个证书。 (虽然 Java9 使用——可以说是滥用——PKCS12,所以它 可以 只包含证书;这是非常规的,AFAICT 不可互操作。)

所有这些 PEM 文件都有 non-PEM 等价物,OpenSSL 称之为 'DER'(尽管 'binary' 可能更准确)。您可以在 PEM DER 中拥有证书,它仍然是证书;您可以在 PEM DER 中拥有密钥; PKCS12 是一个例外;它仅支持 binary/non-PEM 格式。尽管并非所有 OpenSSL 命令在所有情况下都支持 PEM 和 DER。 您的错误消息不是由于尝试“-importcert”non-PEM 格式的内容,而是尝试“-importcert”不是特定证书的内容(任何格式)。这就是它说 'Input not an X.509 certificate' 的原因——这意味着输入不包含证书。

通常(除了此处不相关的极少数例外)SSL/TLS 服务器需要私钥 证书或链; Java SSL/TLS 服务器像旧的 Tomcat 需要私钥和 cert/chain 以 Java 支持的格式作为密钥库,如上所述可以是 JKS 或 PKCS12 . (Tomcat 8.5 和 9 将其更改为 'merge' Java JSSE 和 APR OpenSSL 的配置。) =37=]generated in Java 特别是在密钥库文件中,那么您通常需要导入构成该链的多个证书,作为单个链(通常是 P7B)或单独从根;您可能一直在查看有关这种情况的说明,这不是您在 OpenSSL 中而不是在 Java 密钥库中生成密钥对(以及证书)的情况。

SSL/TLS 客户端 OTOH 只需要 trust-anchor 证书(无密钥),通常是根 CA 证书。对于 'real' (public) CA 颁发的证书,包括 Java 在内的大多数客户端已经内置了 public 根 CA,但是由于您要创建自己的 CA,您需要将 CA 证书(仅)分发给您的客户(可能除了忽略不正确的证书,如 openssl s_clientcurl -k)。

最后警告:以这种方式使用 OpenSSL 生成的证书(因此您的服务器使用它们)将无法在 Chrome 58 或更高版本(自 2017 年中以来)中使用,因为它现在需要 SubjectAltNames aka SAN;查看关于此的大量现有问题。

我认为上面的答案是正确的,但如果它能帮助任何发现这个问题的人,那么我只是在这里发布我开始工作的脚本(将 <password> 替换为您在出现提示时使用的密码):

REM Create certficates --
REM 1. Create CA key in private directory:                                               
REM openssl genrsa -out CA.key 4096
REM 2. Create CA PEM request using CN <Root Name> and CA key:  
openssl req -key ../private/CA.key -new -out CA.req
REM 3. Create CA PEM using Create CA PEM request:                   
openssl x509 -req -days 365 -in CA.req -signkey ../private/CA.key -sha256 -out CA.pem
REM 4. Create server key (encrypted with password):                      
openssl genrsa -des3 -out server.key 4096
REM 5. Create server PEM request using CN <FQDN of Server>:  
openssl req -new -key server.key -out server.req
REM 6. Create server PEM using Create server PEM request:           
openssl x509 -req -days 3650 -in server.req -CA CA.pem -CAkey ../private/CA.key -CAcreateserial -CAserial ca.srl -out server.pem
REM 7. Export CA certificate as PKCS12 file (possibly not necessary):
REM openssl pkcs12 -export -inkey ../private/CA.key -in CA.pem -out CA.p12 
REM 8. Export server certificate as PKCS12 file:
openssl pkcs12 -export -in server.pem -inkey server.key -out server.p12 -name server -CAfile CA.pem -caname root

REM -- Install certificates --
REM 9. Add CA PEM to server keystore:
keytool -import -trustcacerts -alias root -file CA.pem -keystore keystore.jks
REM 10. Add server PKCS12 to keystore:
keytool -importkeystore -deststorepass <password> -destkeypass <password> -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass <password> -alias server
REM 11. List keys in keystore
keytool -list -keystore keystore.jks