警报“SSL3_READ_BYTES:sslv3 警报坏证书”是否表示 SSL 失败

警报“SSL3_READ_BYTES:sslv3 警报坏证书”是否表示 SSL 失败

运行以下命令 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

如果您尝试连接到实际上不需要客户端证书即可连接的[配置错误]的机器,也会出现此错误。

相关内容