简体   繁体   中英

Different certificate chain order when using Node's HTTPS/TLS vs. OpenSSL s_client

I'm trying to parse the certificate chain using Node's HTTPS request. I'm testing it on npmjs.com (not www.npmjs.com). When I test it on OpenSSL, it shows me that the chain is in the incorrect order.

openssl s_client -connect npmjs.com:443 -showcerts 

OpenSSL Response First Certificate

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

Next Certificate ->

subject: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA

issuer: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority

Next Certificate ->

subject: /C=US/O=GeoTrust Inc./CN=RapidSSL SHA256 CA - G3

issuer: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA

However, when I go to step through the certificate chain using my Node's HTTPS request, when the socket is emitted and I do

socket.getPeerCertificate(true) 

the chain is in the correct order and I'm getting one different certificate on the Node request than I am on the openssl request.

Node's Response First Certificate:

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' }

Next Certificate ->

subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'RapidSSL SHA256 CA - G3' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }

Next Certificate ->

subject
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }
issuer
{ C: 'US', O: 'GeoTrust Inc.', CN: 'GeoTrust Global CA' }

Why is this happening?

It looks like node is reordering the certificates for returning in getPeerCertificates so that they reflect the correct order in the trust chain (*). But in reality the certificates are in the wrong order, as can be seen by openssl s_client and also in the analysis of SSLLabs :

Chain issues    Incorrect order

(*) the relevant code in node-4.5.0 (LTS) is in src/node_crypto.cc function void SSLWrap<Base>::GetPeerCertificate . There it retrieves the leaf certificate and the original peer certificates from the openssl library using SSL_get_peer_certificate (leaf certificate) and SSL_get_peer_cert_chain (chain). It then does not return the certificates in the original chain order but scans through the chain and adds the certificates in the order how they are depend on each other by checking with X509_check_issued .

This way it returns the certificates in proper dependency order instead of the original order as send by the peer. It also automatically skips any certificates which don't belong in the chain.

It will also add the issuer of the certificate even if it is not contained it the chain (which it usually isn't). This way you not only get a different order of certificates as seen in your example but actually different certificates. The server sends the following certificates in this order:

[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

But getPeerCertificate returns the following:

[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

Thus certificate [B] will not be included but instead certificate [R] which is the root certificate contained in the trust store. Both have the same subject and key, but are signed by different entities. [B] is signed by Equifax while [R] is self-signed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM