我正在尝试使用Python 3和ssl.get_server_certificate下载SSL证书,以便我的工具可以以通用方式处理自签名证书。但是,当我运行此命令时:$ pythonPython 3.7.0 (default, Sep 15 2018, 19:13:07)[GCC 8.2.1 20180831] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import ssl>>> ssl.get_server_certificate(('self-signed.badssl.com', 443))'-----BEGIN CERTIFICATE-----\nMIIE8DCCAtigAwIBAgIJAM28Wkrsl2exMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp\nc2NvMQ8wDQYDVQQKDAZCYWRTU0wxMjAwBgNVBAMMKUJhZFNTTCBJbnRlcm1lZGlh\ndGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE2MDgwODIxMTcwNVoXDTE4MDgw\nODIxMTcwNVowgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw\nFAYDVQQHDA1TYW4gRnJhbmNpc2NvMTYwNAYDVQQKDC1CYWRTU0wgRmFsbGJhY2su\nIFVua25vd24gc3ViZG9tYWluIG9yIG5vIFNOSS4xNDAyBgNVBAMMK2JhZHNzbC1m\nYWxsYmFjay11bmtub3duLXN1YmRvbWFpbi1vci1uby1zbmkwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDCBOz4jO4EwrPYUNVwWMyTGOtcqGhJsCK1+ZWe\nsSssdj5swEtgTEzqsrTAD4C2sPlyyYYC+VxBXRMrf3HES7zplC5QN6ZnHGGM9kFC\nxUbTFocnn3TrCp0RUiYhc2yETHlV5NFr6AY9SBVSrbMo26r/bv9glUp3aznxJNEx\ntt1NwMT8U7ltQq21fP6u9RXSM0jnInHHwhR6bCjqN0rf6my1crR+WqIW3GmxV0Tb\nChKr3sMPR3RcQSLhmvkbk+atIgYpLrG6SRwMJ56j+4v3QHIArJII2YxXhFOBBcvm\n/mtUmEAnhccQu3Nw72kYQQdFVXz5ZD89LMOpfOuTGkyG0cqFAgMBAAGjRTBDMAkG\nA1UdEwQCMAAwNgYDVR0RBC8wLYIrYmFkc3NsLWZhbGxiYWNrLXVua25vd24tc3Vi\nZG9tYWluLW9yLW5vLXNuaTANBgkqhkiG9w0BAQsFAAOCAgEAsuFs0K86D2IB20nB\nQNb+4vs2Z6kECmVUuD0vEUBR/dovFE4PfzTr6uUwRoRdjToewx9VCwvTL7toq3dd\noOwHakRjoxvq+lKvPq+0FMTlKYRjOL6Cq3wZNcsyiTYr7odyKbZs383rEBbcNu0N\nc666/ozs4y4W7ufeMFrKak9UenrrPlUe0nrEHV3IMSF32iV85nXm95f7aLFvM6Lm\nEzAGgWopuRqD+J0QEt3WNODWqBSZ9EYyx9l2l+KI1QcMalG20QXuxDNHmTEzMaCj\n4Zl8k0szexR8rbcQEgJ9J+izxsecLRVp70siGEYDkhq0DgIDOjmmu8ath4yznX6A\npYEGtYTDUxIvsWxwkraBBJAfVxkp2OSg7DiZEVlMM8QxbSeLCz+63kE/d5iJfqde\ncGqX7rKEsVW4VLfHPF8sfCyXVi5sWrXrDvJm3zx2b3XToU7EbNONO1C85NsUOWy4\nJccoiguV8V6C723IgzkSgJMlpblJ6FVxC6ZX5XJ0ZsMI9TIjibM2L1Z9DkWRCT6D\nQjuKbYUeURhScofQBiIx73V7VXnFoc1qHAUd/pGhfkCUnUcuBV1SzCEhjiwjnVKx\nHJKvc9OYjJD0ZuvZw9gBrY7qKyBX8g+sglEGFNhruH8/OhqrV8pBXX/EWY0fUZTh\niywmc6GTT7X94Ze2F7iB45jh7WQ=\n-----END CERTIFICATE-----\n'它不会返回与openssl s_client相同的证书:$ openssl s_client -connect self-signed.badssl.com:443 -servername self-signed.badssl.com -showcertsCONNECTED(00000005)depth=0 C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.comverify error:num=18:self signed certificateverify return:1depth=0 C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.comverify return:1---Certificate chain 0 s:C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.com i:C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.com-----BEGIN CERTIFICATE-----MIIDeTCCAmGgAwIBAgIJAPlgiuOcJ/T1MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0xODA4MTUxNTIxNTNaFw0yMDA4MTQxNTIxNTNaMGIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzAS2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMWhyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3AxPxTuW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqveww9HdFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SYQCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0TBAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZIhvcNAQELBQADggEBAKr7JtZHTDuYs8/vGDFrtXb+dkjdNsZEIgyVh4vWZtLOANtO39wM/LwGXUSjonEsYJabJgYpRdRSex41f78QfnARJona7fkcc1aHci7jdrzsxaNJiCc4G49ahgJ1NEIFmRNeEYlKYNNFeyGT6wxkLaV9AnC45MHlaumQyrRJwuXCQH/i16Wk/qDtsu2nw6t+13OqwGfxR9krxDikVFO0YqgSMhqPmufz/6nY6uaXuOqzGv+PrjJZDqCoRmVMqrISIUALWGCF3yasrViM6owIEhtN71UwrFZYYOeZ9nw2wvRK210zc8LlWjgG56wRkLrq/mSINsQ3xmChO1PsBAeSHDU=-----END CERTIFICATE--------Server certificatesubject=C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.comissuer=C = US, ST = California, L = San Francisco, O = BadSSL, CN = *.badssl.com---No client certificate CA names sentPeer signing digest: SHA512Peer signature type: RSAServer Temp Key: ECDH, P-256, 256 bits---SSL handshake has read 1599 bytes and written 450 bytesVerification error: self signed certificate---New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256Server public key is 2048 bitSecure Renegotiation IS supportedCompression: NONEExpansion: NONENo ALPN negotiatedSSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: FF42F7711650D30FCB32C352CED98BB7EE5E4A6CC1EC5398150CE5398D740B72 Session-ID-ctx: Master-Key: D8174DC9863D4D2700432501BD315312473279C24478141D9CCDB03EA6E2EB9779CF98FA998A76E8A591BAC77FBA9CEB PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 84 88 44 09 93 10 49 77-c5 12 b5 3a 9b 2a 06 75 ..D...Iw...:.*.u 0010 - a7 34 c2 95 8b cd db 80-81 68 09 9f b1 79 8e da .4.......h...y.. 0020 - c9 0f f0 d1 3d 74 39 81-58 ac 9b b6 9c e4 3f 51 ....=t9.X.....?Q 0030 - 5d 89 12 aa e7 78 9a 8b-0b c5 74 8c d4 6e 79 8f ]....x....t..ny. 0040 - b0 25 3a 5f 72 8f f1 6c-24 30 b9 b9 19 23 33 ae .%:_r..l$0...#3. 0050 - 1c f1 d7 20 4f 88 60 32-1a cd a1 25 34 d0 03 6d ... O.`2...%4..m 0060 - c2 e2 25 0d 6f d9 22 6c-6a 92 df bd 3a 02 fe 2f ..%.o."lj...:../ 0070 - 4a 9a 23 84 b0 d9 27 ec-05 9c 3a e7 bc 2e a2 4e J.#...'...:....N 0080 - ca 42 f3 5f 57 cc 90 e5-c8 42 de 91 c3 99 eb b5 .B._W....B...... 0090 - 9b 27 c1 12 2d 17 46 c4-52 ff 4a a3 93 22 10 b8 .'..-.F.R.J..".. 00a0 - 45 74 db 7f e4 66 6d 10-dd b7 49 e4 da 9c e5 b6 Et...fm...I..... 00b0 - 08 bb 50 68 69 b3 f9 e8-37 69 9f c1 68 9a ce 0e ..Phi...7i..h... 00c0 - c9 cc 23 49 50 de ee 08-22 61 0d dd 3c a2 32 44 ..#IP..."a..<.2D Start Time: 1539840980 Timeout : 7200 (sec) Verify return code: 18 (self signed certificate) Extended master secret: no---我不能使用前一个证书进行验证,而后者可以工作。我究竟做错了什么?编辑:解决了下面的“重复”注释,替换了openssl调用。 最佳答案 虽然没有这样记录,但get_server_certificate只会将给定的(host,port)视为连接目标,但不会像浏览器那样将设置为TLS SNI扩展中的host。这将产生以下证书:$ python3 -c 'import ssl; print(ssl.get_server_certificate(("self-signed.badssl.com", 443)))' |\ openssl x509 -text... Subject:... O=BadSSL Fallback. Unknown subdomain or no SNI., CN=badssl-fallback-unknown-subdomain-or-no-sni与使用server_name选项(并且在openssl s_client ...的较新版本中也没有此选项)时,与此-servername相反,会将SNI扩展名设置为给定的主机名,结果为:$ openssl s_client -connect self-signed.badssl.com:443 -servername self-signed.badssl.com |\ openssl x509 -text... Subject: C=US, ST=California, L=San Francisco, O=BadSSL, CN=*.badssl.com如果不使用SNI扩展名,则可以通过忘记旧版本openssl中的-servername选项或在新版本中显式设置openssl来获得与-noservername返回的证书相同的证书:$ openssl s_client -connect self-signed.badssl.com:443 [-noservername] |\ openssl x509 -text... Subject:... O=BadSSL Fallback. Unknown subdomain or no SNI., CN=badssl-fallback-unknown-subdomain-or-no-sni 10-05 18:12