尝试使用客户端证书时解决 sslv3 警报握手失败

Solving sslv3 alert handshake failure when trying to use a client certificate

我正在尝试连接到需要证书进行授权的服务。过程是我向服务发送 CSR 文件。该服务签署 CSR 并向我发送一个我用于连接的证书。

  1. 我通过以下命令行生成了 CSR:

    openssl req -new -nodes -newkey rsa:2048 -keyout cert.key -out cert.csr
    
  2. 我把cert.csr的内容发给了他们。他们生成了客户端证书,我得到了一个 PEM 文件。

  3. 我现在尝试在 SSLCERT 中为 curl() 使用他们的证书文件进行连接,并提供来自 cert.key 的私钥作为 CURLOPT_SSLKEY -(我在第 1 步获得).

  4. 失败:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

我在这个过程中做错了什么?

当我尝试使用收到的测试证书(包括来自服务的私钥(自签名证书))时,它有效。但是当我使用他们从我的 CSR 生成的证书然后使用我的私钥作为密钥时,它会因握手失败而出错。

所以我知道这与 openssl / curl 不支持 v3/TLS 等其他人在研究解决方案时发现他们的问题无关。

这是我运行:

  curl -i -v --request POST https://service.com/ --cert clientcert.pem --key private_key.pem --cert-type pem --tlsv1.1 --insecure
* Connected to service.com (1xx.xxx.xxx.xx) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS handshake, CERT verify (15):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS alert, Server hello (2):
* error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
* Closing connection 0

运行 以下版本:curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 [=49= .28 librtmp/2.3

What SSL private key should be sent along with the client certificate?

None 个 :)

客户端证书的一个吸引人的地方是它不会做愚蠢的事情,比如以纯文本形式将秘密(如密码)传输到服务器 (HTTP basic_auth)。密码仍用于解锁客户端证书的密钥,只是不直接用于交换或 tp 验证客户端。

相反,客户端会为该会话选择一个临时的随机密钥。然后客户端用他的证书签署临时的随机密钥并将其发送到服务器(一些人手放弃)。如果一个坏人拦截了任何东西,它是随机的,所以将来不能使用。它甚至不能用于服务器的第二个 运行 协议,因为服务器也会 select 一个新的随机值。


Fails with: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

使用TLS 1.0及以上;并使用 Server Name Indication.

你没有提供任何代码,所以我不清楚如何告诉你该怎么做。相反,这里是 OpenSSL 命令行来测试它:

openssl s_client -connect www.example.com:443 -tls1 -servername www.example.com \
    -cert mycert.pem -key mykey.pem -CAfile <certificate-authority-for-service>.pem

你也可以使用-CAfile来避免“验证error:num=20”。例如,参见 “verify error:num=20” when connecting to gateway.sandbox.push.apple.com.

不是一个明确的答案,但太多不适合评论:

我假设他们给你的证书要么有错误的颁发者(尽管他们的服务器可以为此使用更具体的警报代码)或错误的主题。我们知道该证书与您的私钥相匹配——因为 curlopenssl client 都将它们配对而没有抱怨不匹配;但我们实际上并不知道它与他们想要的 CA 匹配——因为您的 curl 使用 openssl 并且 openssl SSL 客户端不强制配置的客户端证书匹配 certreq.CAs.

对来自测试 P12 的有效证书执行 openssl x509 <clientcert.pem -noout -subject -issuer 和相同操作。做 openssl s_client(或勾选你做的)并查看 Acceptable client certificate CA names;那里的名称或其中之一应该匹配(完全!)您的证书的颁发者。如果不是,那很可能是您的问题,您需要与他们确认您是否以正确的方式将 CSR 提交到了正确的位置。也许他们在不同的地区或业务线有不同的制度,或测试与生产,或活跃与待定等。

如果您的证书颁发者确实匹配所需的 CA,请将其主题与工作 (test-P12) 的主题进行比较:它们的格式是否相似?工作组件中是否有任何组件不存在于您的组件中?如果他们允许,请尝试生成并提交一个新的 CSR,其主题名称与 test-P12 完全相同,或者尽可能接近,看看是否会产生效果更好的证书。 (您不必生成新的 key 来执行此操作,但如果您选择这样做,请跟踪哪些证书与哪些密钥匹配,这样您就不会混淆它们。)如果这无济于事,请查看带有 openssl x509 <cert -noout -text 的证书扩展,了解可能与主体授权合理相关的任何差异,例如 KeyUsage、ExtendedKeyUsage、可能是 Policy、可能是 Constraints,甚至可能是非标准的东西。

如果一切都失败了,请询问服务器操作员他们的日志对问题的看法,或者如果您有权访问,请自行查看日志。

我在 CentOS 8 系统上的解决方案是通过验证 /etc/crypto-policies/config 读取默认值 DEFAULT[ 来检查系统加密策略=20=] 而不是任何其他值。

将此值更改为 DEFAULT 后,运行 以下命令:

/usr/bin/update-crypto-policies --set DEFAULT

重新运行 curl 命令,它应该可以工作。

在我的例子中,错误的原因是我只将证书(例如cert1.pem)和私钥(例如privkey1.pem)导入到密钥库中并解决了问题,我还必须导入完整的证书链。
我从“Let's Encrypt”证书颁发机构获得了以下文件:

privkey1.pem
fullchain1.pem
chain1.pem
cert1.pem

所以我做了以下事情:

  1. 将三个证书文件的内容合并到一个名为all.pem:
  2. 的文件中
cat cert1.pem chain1.pem fullchain1.pem > all.pem
  1. 创建我的包含完整证书链的密钥库:
openssl pkcs12 -export -in all.pem -inkey privkey1.pem -out my_keystore.p12 -name mycertalias -CAfile chain1.pem -caname root