使用 Node 的 HTTPS/TLS 与 OpenSSL s_client 时不同的证书链顺序
Different certificate chain order when using Node's HTTPS/TLS vs. OpenSSL s_client
我正在尝试使用 Node 的 HTTPS 请求解析证书链。我在 npmjs.com(不是 www.npmjs.com)上测试它。当我在 OpenSSL 上测试它时,它显示链的顺序不正确。
openssl s_client -connect npmjs.com:443 -showcerts
OpenSSL 响应第一个证书
subject: /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
issuer: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
下一个证书 ->
subject: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
issuer: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
下一个证书 ->
subject: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
issuer: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
但是,当我使用我的节点的 HTTPS 请求逐步通过证书链时,当套接字被发出时,我做了
socket.getPeerCertificate(true)
链的顺序正确,我在节点请求上获得的证书与我在 openssl 请求上获得的证书不同。
节点响应第一个证书:
subject
{ OU:
[ 'GT40876434',
'See www.rapidssl.com/resources/cps (c)14',
'Domain Control Validated - RapidSSL(R)' ],
CN: '*.npmjs.com' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
下一个证书 ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
下一个证书 ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
为什么会这样?
看起来节点正在为 getPeerCertificates 中的 returning 重新排序证书,以便它们反映信任链 (*) 中的正确顺序。但实际上证书的顺序是错误的,正如 openssl s_client
和 analysis of SSLLabs:
中所见
Chain issues Incorrect order
(*) node-4.5.0 (LTS) 中的相关代码在 src/node_crypto.cc
函数 void SSLWrap<Base>::GetPeerCertificate
中。在那里,它使用 SSL_get_peer_certificate
(叶证书)和 SSL_get_peer_cert_chain
(链)从 openssl 库中检索叶证书和原始对等证书。然后它不会 return 原始链顺序中的证书,而是扫描整个链并通过检查 X509_check_issued
按照它们相互依赖的顺序添加证书。
这样它 return 以正确的依赖顺序而不是对等方发送的原始顺序排列证书。它还会自动跳过不属于链中的任何证书。
它还会添加证书的颁发者,即使它不包含在链中(通常不包含)。这样,您不仅会获得示例中看到的不同顺序的证书,而且实际上会获得不同的证书。服务器按此顺序发送以下证书:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[B] /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, issued by Equifax
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
但是 getPeerCertificate
return 如下:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
[R] CA/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, self-signed
因此证书 [B] 将不包含在内,而是证书 [R],它是信任库中包含的根证书。两者具有相同的主题和密钥,但由不同的实体签名。 [B] 由 Equifax 签名,而 [R] 是自签名的。
我正在尝试使用 Node 的 HTTPS 请求解析证书链。我在 npmjs.com(不是 www.npmjs.com)上测试它。当我在 OpenSSL 上测试它时,它显示链的顺序不正确。
openssl s_client -connect npmjs.com:443 -showcerts
OpenSSL 响应第一个证书
subject: /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
issuer: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
下一个证书 ->
subject: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
issuer: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
下一个证书 ->
subject: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
issuer: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
但是,当我使用我的节点的 HTTPS 请求逐步通过证书链时,当套接字被发出时,我做了
socket.getPeerCertificate(true)
链的顺序正确,我在节点请求上获得的证书与我在 openssl 请求上获得的证书不同。
节点响应第一个证书:
subject
{ OU:
[ 'GT40876434',
'See www.rapidssl.com/resources/cps (c)14',
'Domain Control Validated - RapidSSL(R)' ],
CN: '*.npmjs.com' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
下一个证书 ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
下一个证书 ->
subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
为什么会这样?
看起来节点正在为 getPeerCertificates 中的 returning 重新排序证书,以便它们反映信任链 (*) 中的正确顺序。但实际上证书的顺序是错误的,正如 openssl s_client
和 analysis of SSLLabs:
Chain issues Incorrect order
(*) node-4.5.0 (LTS) 中的相关代码在 src/node_crypto.cc
函数 void SSLWrap<Base>::GetPeerCertificate
中。在那里,它使用 SSL_get_peer_certificate
(叶证书)和 SSL_get_peer_cert_chain
(链)从 openssl 库中检索叶证书和原始对等证书。然后它不会 return 原始链顺序中的证书,而是扫描整个链并通过检查 X509_check_issued
按照它们相互依赖的顺序添加证书。
这样它 return 以正确的依赖顺序而不是对等方发送的原始顺序排列证书。它还会自动跳过不属于链中的任何证书。
它还会添加证书的颁发者,即使它不包含在链中(通常不包含)。这样,您不仅会获得示例中看到的不同顺序的证书,而且实际上会获得不同的证书。服务器按此顺序发送以下证书:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[B] /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, issued by Equifax
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
但是 getPeerCertificate
return 如下:
[A] /OU=GT40876434/OU=See www.rapidssl.com/resources/cps (c)14/OU=Domain Control Validated - RapidSSL(R)/CN=*.npmjs.com
[C] /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3
[R] CA/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA, self-signed
因此证书 [B] 将不包含在内,而是证书 [R],它是信任库中包含的根证书。两者具有相同的主题和密钥,但由不同的实体签名。 [B] 由 Equifax 签名,而 [R] 是自签名的。