运行以下命令 openssl s_client -host example.xyz -port 9093
我收到以下错误:
139810559764296:error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate:s3_pkt.c:1259:SSL alert number 42
39810559764296:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
但最后我收到了"Verify return code: 0 (ok)"
消息。
我的问题是上述警报表示什么,以及 SSL 是否真的成功。
SSL handshake has read 6648 bytes and written 354 bytes
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : AES128-SHA
Session-ID: xx
Session-ID-ctx:
Master-Key: xx
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1475096098
Timeout : 300 (sec)
**Verify return code: 0 (ok)**
答案1
“握手失败”表示握手失败,并且没有 SSL/TLS 连接。您应该看到openssl
退出到 shell(或 CMD 等),并且不等待输入数据发送到服务器。“验证返回代码 0”表示没有问题成立在服务器的证书中,要么是因为它根本没有被检查,要么是因为它被检查过并且是好的(就 OpenSSL 的检查而言,它并不能涵盖所有内容);在这种情况下,通过了解协议,我们可以推断出后一种情况适用。
接收警报bad certificate
(代码 42)意味着服务器要求你进行身份验证使用证书,而您没有这样做,这导致握手失败。 在该行之前几行,SSL handshake has read ... and written ...
您应该看到一行,Acceptable client certificate CA names
通常后面跟着几行标识 CA 的行,后面可能跟着一行开头Client Certificate Types
,也可能跟着一些关于的内容,具体Requested Signature Algorithms
取决于您的 OpenSSL 版本和协商的协议。
查找证书由“可接受”列表中的 CA 颁发,或者如果列表为空,请在服务器上查找或查看有关服务器的文档,说明它信任哪些 CA,或者联系服务器运营商或所有者并询问他们,加上匹配的私钥,均为 PEM 格式,并指定它们使用-cert $file -key $file
;如果您将两者放在一个文件中,就像使用 PEM 一样,只需使用-cert $file
。如果您拥有不同的格式,请指定它,或者在此处搜索,也许还有 superuser 和 security.SX;已经有很多关于转换各种证书和私钥格式的问答。如果您的证书需要“链”或“中间”证书(甚至多个)进行验证,就像通常来自公共 CA(而不是内部 CA)的证书一样,具体取决于服务器的配置方式,则s_client
需要一个技巧:将链证书添加到您的系统信任库,或创建一个本地/临时信任库,其中包含您需要验证服务器的 CA 证书以及您需要发送的链证书。
如果您没有这样的证书,您要么需要获取一个,这是一个不同的问题,需要更详细地回答,要么您需要找到一种不使用证书认证来连接服务器的方法;再次检查文档和/或询问操作员/所有者。
编辑:从评论中可以看出,您可能拥有 Java 中的客户端密钥和证书链以及服务器锚点(?)。检查后,我没有看到一个好的现有答案完全涵盖这种情况,因此即使这可能搜索效果不佳:
# Assume Java keystore is type JKS (the default but not only possibility)
# named key.jks and the privatekey entry is named mykey (ditto)
# and the verify certs are in trust.jks in entries named trust1 trust2 etc.
# convert Java key entry to PKCS12 then PKCS12 to PEM files
keytool -importkeystore -srckeystore key.jks -destkeystore key.p12 -deststoretype pkcs12 -srcalias mykey
openssl pkcs12 -in key.p12 -nocerts -out key.pem
openssl pkcs12 -in key.p12 -nokeys -clcerts -out cert.pem
openssl pkcs12 -in key.p12 -nokeys -cacerts -out chain.pem
# extract verify certs to individual PEM files
# (or if you 'uploaded' PEM files and still have them just use those)
keytool -keystore trust.jks -export -alias trust1 -rfc -file trust1.pem
keytool -keystore trust.jks -export -alias trust2 -rfc -file trust2.pem
... more if needed ...
# combine for s_client
cat chain.pem trust*.pem >combined.pem
openssl s_client -connect host:port -key key.pem -cert cert.pem -CAfile combined.pem
答案2
就我而言,当私钥与证书不匹配时,我收到此错误。我的证书过期后,我更新了证书,需要创建一个新的私钥。但是,我忘记在我的应用程序中引用它了。当我指向新的私钥时,这个错误就消失了。
答案3
当我在日期和时间设置错误的嵌入式目标上运行测试套件中的 ssl_test 时,我遇到了同样的错误。目标时间设置为 2000 年,这比提供的测试证书要早。将目标时间/年份设置为 2020 年可以解决问题。
答案4
如果您尝试连接到实际上不需要客户端证书即可连接的[配置错误]的机器,也会出现此错误。