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

Java 用于SSL身份验证的自签名证书和客户端密钥库,java,ssl,certificate,keystore,keytool,Java,Ssl,Certificate,Keystore,Keytool,我需要在服务器(一个XML硬件设备)上创建并安装一个自签名证书,以对Java客户机/应用程序进行SSL身份验证,该应用程序通过其接口配置可以设置密钥库,即jks。出于明显的原因,我只需要出于测试目的而非生产目的进行此设置。以下是我如何创建密钥库(PKCS12类型): 1) 生成私钥(对) 2) 生成证书请求(是否需要?)——我只将值设置为CN 3) 创建自签名证书 $> openssl x509 -req -days 365 -in request.csr -signkey private

我需要在服务器(一个XML硬件设备)上创建并安装一个自签名证书,以对Java客户机/应用程序进行SSL身份验证,该应用程序通过其接口配置可以设置密钥库,即jks。出于明显的原因,我只需要出于测试目的而非生产目的进行此设置。以下是我如何创建密钥库(PKCS12类型):

1) 生成私钥(对)

2) 生成证书请求(是否需要?)——我只将值设置为CN

3) 创建自签名证书

$> openssl x509 -req -days 365 -in request.csr -signkey private.key -out cert.crt
4) 创建PKCS12密钥库

5) 创建客户端JKS


我是否从根本上遗漏了一些关于证书和SSL身份验证的信息?

目前还没有答案,但对于评论来说太复杂了,因此我将在稍后开始并进行编辑

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

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

目前,您有一个密钥和自签名证书,您正试图为客户端和服务器共享。虽然您可能希望在以后更改这些,但我建议您首先关注如何使某些功能正常工作。同时改变几个相互关联的事物往往会引起混乱

“提取”证书?对于当前设置,使用一个(共享)密钥+证书(自签名),您已经在JKS中具有密钥+证书,在P12中具有相同的密钥+证书,并且在文件(cert.crt)中具有相同的证书,因此您无需提取任何内容。如果您(稍后)使用keytool为Java(客户端)生成一个新密钥和自签名证书,那么您需要提取该证书。 如果获得现有密钥或新密钥的CA签名证书,可能需要提取根/锚点,但可能已经有了,请参见下文

需要信任哪些证书?客户端总是(除了此处不相关的小例外)需要在其信任库中存储服务器证书的锚点,并且当客户端进行身份验证时(也称为双向或双向)在您的案例中,服务器需要在其信任库中为客户端证书存储锚。在您当前的案例中,客户端和服务器使用相同的证书,因此双方都需要相同的锚

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

  • 对于颁发的CA证书,锚可以是且(始终?)应该是该CA的证书;CA根证书通常寿命较长(如20年或更长),并且不需要在合作伙伴/实体证书发生更改时进行更改

  • 如果您使用著名的CA,如Verisign或GoDaddy,而不是您自己或当地红灯区的“Joe's Dicount酒店和证书颁发机构”经营的CA,在某些系统中,那些众所周知的CA的根可能已经安装了,在这种情况下,您不需要做任何事情

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

服务器信任库呢?另一方面,对密钥库使用pkcs12格式的软件,或者至少要导入密钥库条目,有时(我经常说)对其信任库不使用相同的格式,当然也不使用相同的文件。事实上,它确实拒绝客户端使用它已经拥有的证书,这可能意味着它不会将您提供给它的pkcs12视为信任库数据,尽管原则上它可能不喜欢其他东西,例如缺少ExtendedKeyUsage扩展或吊销/状态数据不可用

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


如果您可以在您的服务器/设备上向我们提供(指向)文档的链接,或者告诉我们文档显示、提供和/或接受的详细信息,我可能会更具体。

您可以使用keytool完成所有操作。不需要OpenSSL
$> openssl req -new -key private.key -out request.csr
$> openssl x509 -req -days 365 -in request.csr -signkey private.key -out cert.crt
$> openssl pkcs12 -export -in cert.crt -inkey private.key -out keystore.p12
$> keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -srcalias myalias -destkeystore client.jks -deststoretype jks -deststorepass <same pass as private key> -destalias myalias
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate