6

HTTPS経由で多数のURLに接続し、SSL証明書をダウンロードして、CNを抽出するスクリプトを作成しています。無効なSSL証明書があるサイトでつまずいた場合を除いて、すべてが機能します。証明書が有効かどうかは絶対に気にしません。CNが欲しいのですが、証明書が検証されていない場合、Pythonは頑固に証明書情報の抽出を拒否します。この非常に愚かな行動を回避する方法はありますか?ああ、私は組み込みのソケットとsslライブラリのみを使用しています。スクリプトを可能な限り移植可能にしようとしているため、M2CryptoやpyOpenSSLなどのサードパーティライブラリを使用したくありません。

関連するコードは次のとおりです。

    file = open("list.txt", "r")
    for x in file:
    server = socket.getaddrinfo(x.rstrip(), "443")[0][4][0]
    sslsocket = socket.socket()
    sslsocket.connect((server, 443))
    sslsocket = ssl.wrap_socket(sslsocket, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
    certificate = sslsocket.getpeercert()`
4

2 に答える 2

6

ssl.get_server_certificateはそれを行うことができます:

import ssl
ssl.get_server_certificate(("www.sefaz.ce.gov.br",443)) 

関数のドキュメント文字列は、Pythonのドキュメントサイトよりも明確だと思います。

"""Retrieve the certificate from the server at the specified address,
   and return it as a PEM-encoded string.
   If 'ca_certs' is specified, validate the server cert against it.
   If 'ssl_version' is specified, use it in the connection attempt."""

したがって、一般名オブジェクト識別子を検索するバイナリDER証明書から一般名を抽出できます。

def get_commonname(host,port=443):
    oid='\x06\x03U\x04\x03' # Object Identifier 2.5.4.3 (COMMON NAME)
    pem=ssl.get_server_certificate((host,port))
    der=ssl.PEM_cert_to_DER_cert(pem)
    i=der.find(oid) # find first common name (certificate authority)
    if i!=-1:
        i=der.find(oid,i+1) # skip and find second common name
        if i!=-1:
            begin=i+len(oid)+2
            end=begin+ord(der[begin-1])
            return der[begin:end]
    return None
于 2012-08-18T03:19:36.087 に答える
2

Ok。証明書チェーン(ルート、中間、サーバー)に常に3つのCNがあると想定される問題を解決するために、olivecoderのコードをクリーンアップし、それを凝縮しました。これが私が使用する最後のコードです。

cert = ssl.get_server_certificate(("www.google.com", 443)) #Retrieve SSL server certificate
cert = ssl.PEM_cert_to_DER_cert(cert) #Convert certificate to DER format
begin = cert.rfind('\x06\x03\x55\x04\x03') + 7 #Find the last occurence of this byte string indicating the CN, add 7 bytes to startpoint to account for length of byte string and padding
end = begin + ord(cert[begin - 1]) #Set endpoint to startpoint + the length of the CN
print cert[begin:end] #Retrieve the CN from the DER encoded certificate
于 2012-08-18T21:17:31.367 に答える