在PyOpenSSL中验证客户端证书

2024-06-06 13:07:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个应用程序,需要在客户端浏览器中安装证书。我在“Context”对象的PyOpenSSL文档中发现了这一点,但是我看不到回调应该如何验证证书,只是它应该以某种方式验证。

   set_verify(mode, callback)
      Set the verification flags for this Context object to mode and
      specify that callback should be used for verification callbacks.
      mode should be one of VERIFY_NONE and VERIFY_PEER. If
      VERIFY_PEER is used, mode can be OR:ed with
      VERIFY_FAIL_IF_NO_PEER_CERT and VERIFY_CLIENT_ONCE to further
      control the behaviour. callback should take five arguments: A
      Connection object, an X509 object, and three integer variables,
      which are in turn potential error number, error depth and return
      code. callback should return true if verification passes and
      false otherwise.

我告诉Context对象我的(自签名)密钥在哪里(见下文),所以我想我不明白为什么库不足以检查客户端提供的证书是否有效。在这个回调函数中应该做什么?

class SecureAJAXServer(PlainAJAXServer):
    def __init__(self, server_address, HandlerClass):
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.use_privatekey_file ('keys/server.key')
        ctx.use_certificate_file('keys/server.crt')
        ctx.set_session_id("My_experimental_AJAX_Server")
        ctx.set_verify( SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, callback_func )
        self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
        self.server_bind()
        self.server_activate()

注意:这里的代码是为了好玩,def不是专业的,所以如果我的Q显示了我完全的跛脚,天真和/或根本不了解SSL,请不要太粗暴!

谢谢:)

罗杰


Tags: andselfsslservermodecontextcallbacksocket
1条回答
网友
1楼 · 发布于 2024-06-06 13:07:25

OpenSSL documentationfor set_verify()中,您关心的关键是返回代码:

callback should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. callback should return true if verification passes and false otherwise.

有一个完整的工作示例或多或少地显示了您想要做的事情:When are client certificates verified?

实际上,您可以忽略前4个参数,只需检查第5个参数中返回代码的值,如下所示:

from OpenSSL.SSL import Context, Connection, SSLv23_METHOD
from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE

class SecureAJAXServer(BaseServer):
    def verify_callback(connection, x509, errnum, errdepth, ok):
        if not ok:
            print "Bad Certs"
        else:
            print "Certs are fine"
        return ok

    def __init__(self, server_address, HandlerClass):
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = Context(SSLv23_METHOD)
        ctx.use_privatekey_file ('keys/server.key')
        ctx.use_certificate_file('keys/server.crt')
        ctx.set_session_id("My_experimental_AJAX_Server")
        ctx.set_verify( VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_callback )
        self.socket = Connection(ctx, socket.socket(self.address_family, self.socket_type))
        self.server_bind()
        self.server_activate()

注意:我做了另一个更改,即from OpenSSL.SSL import ...,以便在测试代码时稍微简化代码,这样就不会在每个导入符号前面都有SSL.前缀。

相关问题 更多 >