我陷入了与服务提供商的指责匹配,其服务提供商的API受SSL服务器和客户端证书保护。
openssl s_client -connect ... -cert ... -key ...
[shell ~]$ openssl s_client -connect host:443 -cert cert_and_key.pem -key cert_and_key.pem -state -quiet
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 **SNIP**
verify return:1
depth=1 **SNIP**
verify return:1
depth=0 **SNIP**
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read finished A
140011313276744:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1197:SSL alert number 48
140011313276744:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
我对SSL3 alert read:fatal:unknown CA
错误的解读是服务器无法识别我(实际上)提供的证书的颁发者。但是,提供商“向我保证”CA证书已正确加载,否则我无法说服他们。
因此,除了其他(广泛的)故障排除步骤之外,我真正想知道的是:
openssl s_client
是否有一些输出最终显示客户端证书不仅仅是服务器请求的,而实际上是传输到服务器期间SSL握手?
我已尝试使用-state
,-msg
,-debug
和-trace
选项,但没有必要的背景来解释输出。
EJP的回答表明我提供的示例输出足够证明write client certificate A
,但无论是否在命令行上使用了-cert
选项,都会显示此输出,因此它不是指示性的证书已发送。
答案 0 :(得分:74)
为了验证客户端证书是否正在发送到服务器,您需要分析-state
和-debug
标志组合的输出。
首先作为基准,尝试运行
$ openssl s_client -connect host:443 -state -debug
你会得到大量的输出,但我们感兴趣的行看起来像这样:
SSL_connect:SSLv3 read server done A
write to 0x211efb0 [0x21ced50] (12 bytes => 12 (0xC))
0000 - 16 03 01 00 07 0b 00 00-03 .........
000c - <SPACES/NULS>
SSL_connect:SSLv3 write client certificate A
这里发生了什么:
-state
标志负责显示上一部分的结尾:
SSL_connect:SSLv3 read server done A
这对于帮助您在输出中找到自己的位置非常重要。
然后-debug
标志显示下一步发送的原始字节:
write to 0x211efb0 [0x21ced50] (12 bytes => 12 (0xC))
0000 - 16 03 01 00 07 0b 00 00-03 .........
000c - <SPACES/NULS>
最后,-state
标志再次报告-debug
刚刚回应的步骤的结果:
SSL_connect:SSLv3 write client certificate A
换句话说:s_client
读取了从服务器发送的数据,并将12个字节发送到服务器(我假设是)“no client certificate”消息。
如果您重复测试,但这次包括-cert
和-key
这样的标记:
$ openssl s_client -connect host:443 \
-cert cert_and_key.pem \
-key cert_and_key.pem \
-state -debug
SSL_connect:SSLv3 read server done A
write to 0x7bd970 [0x86d890] (1576 bytes => 1576 (0x628))
0000 - 16 03 01 06 23 0b 00 06-1f 00 06 1c 00 06 19 31 ....#..........1
(*SNIP*)
0620 - 95 ca 5e f4 2f 6c 43 11- ..^%/lC.
SSL_connect:SSLv3 write client certificate A
1576 bytes
本身就证明了证书的传输是一个很好的指示,但最重要的是,右栏会显示人类可读的部分证书:你应该能够在那里认可你的证书的CN和发行人字符串。
答案 1 :(得分:6)
我知道这是一个老问题,但它似乎还没有答案。 我已经复制了这种情况,但我正在编写服务器应用程序,所以我已经能够确定服务器端发生的事情。客户端在服务器请求时发送证书,并且在s_client命令行中引用了真实证书。我的服务器应用程序设置为要求提供客户端证书,如果没有提供,则会失败。这是我发出的命令行:
Yourhostname here -vvvvvvvvvv
s_client -connect <hostname>:443 -cert client.pem -key cckey.pem -CAfile rootcert.pem -cipher ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH -tls1 -state
当我省略命令的“-cert client.pem”部分时,服务器端的握手失败,s_client命令失败并报告错误。我仍然收到报告“没有发送客户证书CA名称”,但我认为这已在上面得到解答。
简短的回答是服务器确定客户端是否将在正常操作条件下发送证书(s_client不正常),并且失败是由于服务器无法识别所提供证书中的CA.虽然我的项目需要双向身份验证,但我并不熟悉这种情况。
您显然是在发送证书。服务器明显拒绝它。
这里缺少的信息是创建证书的确切方式以及提供者加载证书的方式,但现在可能全部都已完成。