16

クライアント ブラウザに証明書をインストールする必要があるアプリを作成しています。「Context」オブジェクトの PyOpenSSL ドキュメントでこれを見つけましたが、コールバックが証明書を検証する方法については何もわかりません。

   set_verify(モード、コールバック)
      この Context オブジェクトの検証フラグをモードに設定し、
      検証コールバックにコールバックを使用するように指定します。
      mode は VERIFY_NONE と VERIFY_PEER のいずれかにする必要があります。もしも
      VERIFY_PEER が使用され、mode は OR:ed で使用できます
      VERIFY_FAIL_IF_NO_PEER_CERT および VERIFY_CLIENT_ONCE でさらに
      行動を制御します。コールバックは 5 つの引数を取る必要があります: A
      Connection オブジェクト、X509 オブジェクト、および 3 つの整数変数
      これらは、潜在的なエラー番号、エラーの深さ、および戻り値です
      コード。コールバックは、検証が成功した場合に true を返す必要があり、
      それ以外の場合は false。

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 が SSL に関して私の完全な不自由さ、素朴さ、および/または基本的な理解の欠如を明らかにした場合でも、あまり大雑把にしないでください!

ありがとう :)

ロジャー

4

1 に答える 1

5

OpenSSL ドキュメントset_verify()は、重要なキーは戻りコードです

callback は 5 つの引数を取る必要があります: Connection オブジェクト、X509 オブジェクト、および 3 つの整数変数。これらは、潜在的なエラー番号、エラーの深さ、および戻りコードです。callback は、検証が成功した場合は true を返し、それ以外の場合は false を返す必要があります。

多かれ少なかれやりたいことを示す完全な動作例があります:クライアント証明書はいつ検証されますか?

基本的に、最初の 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 ...を付けないようにするために、もう 1 つの変更を加えました。SSL.

于 2012-02-02T03:18:49.420 に答える