在PyOpenSSL中验证客户端证书

时间:2012-02-01 02:33:51

标签: python validation ssl client-certificates pyopenssl

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

   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()

警告:在这里编写乐趣,不要专业人士,所以如果我的Q显示我的完全跛足,天真和/或基本缺乏理解,那么请不要太粗暴!

谢谢:)

罗杰

1 个答案:

答案 0 :(得分:6)

set_verify() 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() 中,您关注的关键是返回代码

  

回调应该采用五个参数:一个Connection对象,一个X509   对象和三个整数变量,这些变量又是潜在的错误   数字,错误深度和返回代码。回调应该返回true   如果验证通过,否则为假。

有一个完整的工作示例,或多或少地显示了您想要做的事情:OpenSSL documentation

基本上你可以忽略前4个参数,只需检查第五个参数中返回码的值,如下所示:

from OpenSSL.SSL import ...

注意:我进行了另一项更改SSL.,以便在我测试时简化您的代码,这样您就不会在每个导入符号前面加上{{1}}前缀。