How does PHP use Socket to obtain the SSL Certificate and public key of a website?
Sample Code:
12345678910111213141516171819202122232425262728293031323334353637 |
// Create stream context $context = stream_context_create([ 'ssl' => [ 'capture_peer_cert' => true, 'capture_peer_cert_chain' => true, ], ]); $resource = stream_socket_client( "ssl://$domain:$port" , $errno , $errstr , 30, STREAM_CLIENT_CONNECT, $context ); $cert = stream_context_get_params( $resource ); $ssl = $cert [ 'options' ][ 'ssl' ]; $resource = $ssl [ 'peer_certificate' ]; // Only the public key is in the website certificate. Use openssl_pkey_get_details to export the public key. $ret = [ 'crt' => '' , 'pub' => '' , ]; $pkey = openssl_pkey_get_public( $resource ); $ret [ 'pub' ] = openssl_pkey_get_details( $pkey )[ 'key' ]; openssl_x509_export( $resource , $pem ); $ret [ 'crt' ] = $pem ; foreach ( $ssl [ 'peer_certificate_chain' ] as $resource ) { openssl_x509_export( $resource , $pem ); $ret [ 'crt' ] .= "\n" . $pem ; } // Save $ ret ['crt '] As domain. crt // Save $ ret ['pub'] As domain. pub return $ret ; |
Verify that the public key A in the certificate is correct. Use the private key to export the Public Key B.
12345678910111213 |
$domain = 'blog.zhengxianjun.com' ; $port = '443' ; // ... $pub_a = $ret [ 'pub' ]; $private_key_path = '/conf/ssl/blog.zhengxianjun.com.key' ; // No password is set for the certificate. $ passphrase is an empty string. $pkey = openssl_pkey_get_private(file_get_content( $private_key_path ), $passphrase = '' ); $pub_b = openssl_pkey_get_details( $pkey )[ 'key' ]; // The two are the same var_dump( $pub_a === $pub_b ); |
The stream_socket_client function can also be used to obtain the domain names that may be used by the server when the server IP address is known.
12345678 |
$resource = stream_socket_client( "ssl://$ip:$port" , $errno , $errstr , 30, STREAM_CLIENT_CONNECT, $context ); $cert = stream_context_get_params( $resource ); // Parse the X.509 Certificate $info = openssl_x509_parse( $cert [ 'options' ][ 'ssl' ][ 'peer_certificate' ]); // Obtain the list of trusted domain names in the certificate $domain = str_replace ( 'DNS:' , '' , $info [ 'extensions' ][ 'subjectAltName' ]); |
You can see that the private key is not obtained when you obtain the website certificate.
In some websites that use CDN, if you use HTTPS and want to use your own domain name, do you need to provide your private key to CDN vendors? In fact, the certificate path does not need to be consistent with the user name (a domain name that supports https.
That is, when using your own domain name and CDN acceleration, you do not need to use your own ssl certificate, you just need to add your own CDN domain name to the domain name list of the vendor certificate.
Summary
The above is all about this article. I hope the content of this article will help you in your study or work. If you have any questions, please leave a message. Thank you for your support.
Link: https://blog.zhengxianjun.com/2017/02/php-curl-ssl/