用于 SSL 身份验证的自签名证书和客户端密钥库

Self-signed Certificate and Client Keystore for SSL Authentication

我需要在服务器(XML 硬件设备)上创建并安装一个自签名证书,以便对 Java 进行 SSL 身份验证client/application,通过其接口配置,可以设置keystores,即.jks。出于显而易见的原因,我只需要此设置用于测试目的而不是生产目的。这是我创建 keystorePKCS12 类型)的方式:

1) 生成私钥(对)

$> openssl genrsa -des3 -out private.key 1024

2) 生成证书请求(需要这个吗?)——我只设置了值CN

$> openssl req -new -key private.key -out request.csr

3) 创建自签名证书

$> openssl x509 -req -days 365 -in request.csr -signkey private.key -out cert.crt

4) 创建 PKCS12 密钥库

$> openssl pkcs12 -export -in cert.crt -inkey private.key -out keystore.p12

5) 创建客户端JKS

$> keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -srcalias myalias -destkeystore client.jks -deststoretype jks -deststorepass <same pass as private key> -destalias myalias

当我在 server/appliance、client.jks 客户端 Java 应用程序上安装 keystore.p12 并发出请求时,我得到以下错误:

javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

我是否从根本上遗漏了有关证书和 SSL 身份验证的内容?

还没有答案,但对于评论来说太复杂了,所以我会给出一个开始并稍后编辑。

(SSL/TLS) 服务器和客户端是否应该共享一个密钥(和证书)? 可以用于开发,也可以用于测试,因生产而异.作为一般规则,每个需要进行身份验证的独立系统都应该有自己的私钥和该密钥的证书(或者有时但很少有多个证书)。如果所涉及的两个(或更一般地所有)系统以及它们之间的通信将由同一管理员控制,那么放宽此规则并(重新)使用一个密钥+证书并没有什么坏处。由于使用的密钥+证书应该始终是(重新)配置的,因此您可以稍后更改这个决定,如果结果是可取或必要的,甚至可以更改几次。

证书应该是自签名的吗? 通常适合开发和测试,但因生产而异。同样,如果所有相关系统都在一个管理员的控制之下,或者至少是一群相互认识的有限人员(例如一个组织的部门或办公室),那么 CA 验证身份和确定信任就没有真正的安全需要。一个考虑因素是服务器证书必须在证书中对域名(或 IP 地址,如果您使用该选项)进行编码,因此更改它们(开发和测试中经常需要)意味着返回到新证书的 CA,至少是一个小麻烦,有时还有延迟。

目前您拥有一个密钥和您正在尝试为客户端和服务器共享的自签名证书。虽然您以后可能很想更改这些内容,但我建议您首先关注让 something 工作。同时更改几个相互关联的事物往往会造成混乱。

"Extract" 证书? 对于当前设置,使用一个(共享)密钥+证书(自签名),您已经在 J​​KS 中拥有密钥+证书,P12 中的相同密钥+证书,以及文件中的相同证书 (cert.crt),因此您无需提取任何内容。如果您(稍后)使用 keytool 为 Java(客户端)生成新密钥和自签名证书,是的,您需要提取该证书。 如果您获得现有密钥或新密钥的 CA 签名证书,您 可能 需要提取 root/anchor,但您可能已经拥有它,请参见下文。

需要信任什么证书?客户端总是(除了此处不相关的小例外)在其信任库中需要 anchor 用于服务器的证书,并且在您的情况下使用客户端身份验证(也称为相互或双向)时,服务器在其信任库中需要 anchor 用于客户端的证书。在您当前的情况下,客户端和服务器使用相同的证书,因此双方都需要相同的锚点。

  • 对于自签名证书锚必须证书本身 -- 必须在合作伙伴证书更改时更改,通常是手动更改。

  • 对于 CA 颁发的 证书,锚可以是并且(总是?)应该是 root 证书对于那个 CA; CA 根通常是长期存在的(比如 20 年或更长时间)并且不需要在 partner/entity 证书发生变化时进行更改。

  • 如果您使用像 Verisign 或 GoDaddy 这样的众所周知的 CA,而不是您自己或 "Joe's Dicount Liquor Store and Certificate Authority" 在您当地的红灯区,在某些系统中,那些知名 CA 的根可能已经 安装,在这种情况下您不需要做任何事情。

客户端如何工作以信任服务器?您的 Java 客户端显然使用 client.jks 文件作为密钥库和信任库。这很容易工作,因为 Java 使用一种可以包含两种数据的文件格式,并进一步将自有密钥条目中的证书视为 受信任的证书(锚).

服务器信任库如何? 另一方面,使用 pkcs12 格式作为密钥库或至少导入密钥库条目的软件,有时(我经常说)不会为其信任库使用相同的格式,当然也不会使用相同的文件。它 did 拒绝客户端使用它已经拥有的相同证书这一事实 probably 意味着它不会处理你给它的 pkcs12作为信任库数据,尽管原则上它 可能 不喜欢其他内容,例如缺少 ExtendedKeyUsage 扩展或 revocation/status 数据不可用。

您没有识别或描述您的服务器设备,所以我只能猜测 SSL/TLS 服务器(尤其是嵌入式服务器)可以工作的无数种方式。但是在您的设备中某处可能 一种将证书添加到其信任库的方法。此外,它 应该 在某处有某种错误日志,其中可能包含有关它是否只需要信任库中的锚点(此处为自签名证书)或其他信息的其他信息 - 假设你可以查看没有 SSL/TLS 身份验证的日志!

如果你能给我们(一个 link 到)关于你的 server/device 的文档,或者足够详细地告诉我们它显示、提供、and/or 接受的内容,我可能可以更具体。