python - 如何从 BaseHTTPRequestHandler python 获取 x509.Certificate

标签 python ssl basehttprequesthandler

我正在使用 this example 通过 python 2.7.5 设置一个 HTTPS/TLS 服务器.但是,我正在尝试使用扩展 BaseHTTPRequestHandler 的自定义类“CustomHandler”,以在一个 Python 应用程序中支持 HTML 和 Rest API。我一直坚持在 BaseHTTPRequestHandler 中调用哪些方法来获取用户/客户端证书作为 x509.Certificate 对象。归根结底,我想要来自 python 的 SSLSocket 对象的完整用户/客户端 DN。

我发现 self.connection.getpeercert() 返回一个字典对象作为 documented here

{'issuer': ((('countryName', 'IL'),),
            (('organizationName', 'StartCom Ltd.'),),
            (('organizationalUnitName',
              'Secure Digital Certificate Signing'),),
            (('commonName',
              'StartCom Class 2 Primary Intermediate Server CA'),)),
 'notAfter': 'Nov 22 08:15:19 2013 GMT',
 'notBefore': 'Nov 21 03:09:52 2011 GMT',
 'serialNumber': '95F0',
 'subject': ((('description', '571208-SLe257oHY9fVQ07Z'),),
             (('countryName', 'US'),),
             (('stateOrProvinceName', 'California'),),
             (('localityName', 'San Francisco'),),
             (('organizationName', 'Electronic Frontier Foundation, Inc.'),),
             (('commonName', '*.eff.org'),),
             (('emailAddress', 'hostmaster@eff.org'),)),
 'subjectAltName': (('DNS', '*.eff.org'), ('DNS', 'eff.org')),
 'version': 3}

开始工作的设置...

sudo apt-get install python
sudo apt-get install python-pip
pip install cryptography

# Generate Certificates - Root Certificate
sudo openssl req -out ca.pem -new -x509
...Generating a 2048 bit RSA private key
........................+++
.........+++
...writing new private key to 'privkey.pem'
...Enter PEM pass phrase:password
...Verifying - Enter PEM pass phrase:password
...-----
...You are about to be asked to enter information that will be incorporated
...into your certificate request.
...What you are about to enter is what is called a Distinguished Name or a DN.
...There are quite a few fields but you can leave some blank
...For some fields there will be a default value,
...If you enter '.', the field will be left blank.
...-----
...Country Name (2 letter code) [AU]:US
...State or Province Name (full name) [Some-State]:Florida
...Locality Name (eg, city) []:Tampa
...Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
...Organizational Unit Name (eg, section) []:Development
...Common Name (e.g. server FQDN or YOUR name) []:Home Development
...Email Address []:admin@homeoffice.com
# IMPORT THE ca.pem file into your browser's Certificate Authorities

# Generate Certificates - Server certificates
sudo openssl genrsa -out server.key 1024
sudo openssl req -key server.key -new -out server.req
...You are about to be asked to enter information that will be incorporated
...into your certificate request.
...What you are about to enter is what is called a Distinguished Name or a DN.
...There are quite a few fields but you can leave some blank
...For some fields there will be a default value,
...If you enter '.', the field will be left blank.
...-----
...Country Name (2 letter code) [AU]:US
...State or Province Name (full name) [Some-State]:Florida
...Locality Name (eg, city) []:Tampa
...Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
...Organizational Unit Name (eg, section) []:Development
...Common Name (e.g. server FQDN or YOUR name) []:homeoffice.com
...Email Address []:info@homeoffice.com
...
...Please enter the following 'extra' attributes
...to be sent with your certificate request
...A challenge password []:
...An optional company name []:
vi file.srl
...00
vi server.ext
...authorityKeyIdentifier=keyid,issuer
...basicConstraints=CA:FALSE
...keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
...subjectAltName = @alt_names
...
...[alt_names]
...DNS.1 = homeoffice.com
sudo openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out server.pem -days 1825 -sha256 -extfile server.ext
...Signature ok
...subject=C = US, ST = Florida, L = Tampa, O = Home, OU = Development, CN = Home Development, emailAddress = info@homeoffice.com
...Getting CA Private Key
...Enter pass phrase for privkey.pem:password

# Generate Certificates - Client Certificates
sudo openssl genrsa -des3 -out client.key 1024
...Generating RSA private key, 1024 bit long modulus
......................................++++++
.....................................++++++
...e is 65537 (0x010001)
...Enter pass phrase for client.key:password
...Verifying - Enter pass phrase for client.key:password
sudo openssl req -key client.key -new -out client.req
...Enter pass phrase for client.key:password
...You are about to be asked to enter information that will be incorporated
...into your certificate request.
...What you are about to enter is what is called a Distinguished Name or a DN.
...There are quite a few fields but you can leave some blank
...For some fields there will be a default value,
...If you enter '.', the field will be left blank.
...-----
...Country Name (2 letter code) [AU]:US
...State or Province Name (full name) [Some-State]:Florida
...Locality Name (eg, city) []:Tampa
...Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
...Organizational Unit Name (eg, section) []:Development
...Common Name (e.g. server FQDN or YOUR name) []:Smith John J jjsmith3
...Email Address []:jjsmith3@yahoo.com
...
...Please enter the following 'extra' attributes
...to be sent with your certificate request
...A challenge password []:
...An optional company name []:
sudo openssl x509 -req -in client.req -CA ca.pem -CAkey privkey.pem -CAserial file.srl -out client.pem
...Signature ok
...subject=C = US, ST = Florida, L = Tampa, O = Home, OU = Development, CN = Home Development, emailAddress = email@domain.com
...Getting CA Private Key
...Enter pass phrase for privkey.pem:password
sudo openssl pkcs12 -export -out client.p12 -in client.pem -inkey client.key
...Enter pass phrase for client.key:password
...Enter Export Password:password
...Verifying - Enter Export Password:password
# IMPORT THE client.p12 file into your browser's Personal Certificates

# change ownership of sudo-created files to your user
sudo chown user:group *
# add support to access local application by fqdn
sudo echo "127.0.0.1       homeoffice.com" >> /etc/hosts

这是我用来尝试使其正常工作的代码。

from BaseHTTPServer import BaseHTTPRequestHandler
import BaseHTTPServer, SimpleHTTPServer
import ssl
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.backends import default_backend

class CustomHandler(BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.end_headers()
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.end_headers()
    # Need x509.Certificate here instead of dict
        print(self.connection.getpeercert())
    that = x509.load_der_x509_certificate(self.connection.getpeercert(True), default_backend())
    print(that.issuer.rfc4514_string())
    print(that.subject.rfc4514_string())
        self.wfile.write(open("index.html", "r"))
    def do_POST(self):
        cert_dict = self.connection.getpeercert()
        # Need x509.Certificate here instead of dict
        print(type(cert_dict))
        print(cert_dict)

httpd = BaseHTTPServer.HTTPServer(('homeoffice.com', 4443), CustomHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile='./server.key', certfile='./server.pem', server_side=True, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1_2, ca_certs='./ca.pem', do_handshake_on_connect=True, suppress_ragged_eofs=True)
httpd.serve_forever()

我希望 self.connection.getpeercert() 返回一个 x509.Certificate 对象而不是一个字典对象。我宁愿使用现有的类也不愿编写自定义代码来解析字典。

更新:我在研究时发现有用的链接...

最佳答案

你可以试试 PyOpenSSL。

x509_cert = OpenSSL.crypto.load_certificate(
    OpenSSL.crypto.FILETYPE_ASN1, self.connection.getpeercert(True)
)

关于python - 如何从 BaseHTTPRequestHandler python 获取 x509.Certificate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56399023/

相关文章:

java - 使用java从本地商店获取SSL证书到sslContext对象

Python BaseHTTPRequestHandler : Respond with JSON

python - 为什么在使用 obj.x 语法调用时不调用 Python 描述符方法?

ssl - ActiveMQ 双向 SSL 认证

多线程或多进程中的python socket.connect超时错误

android - 使用 XA_HTTP_CLIENT_HANDLER_TYPE 在 AndroidEnvironment 设置中部署应用程序

python - 如何在 BaseHTTPRequestHandler.do_POST() 中提取 HTTP 消息体?

python-3.x - BaseHTTPRequestHandler cgi.parse_multipart 永远不会返回

python - setup.py 用于通过 pip 卸载

python - 无法在朴素贝叶斯中训练模型