2021/12/18

zmqの通信の認証と暗号化

目的


ZMQで認証&通信暗号化をしてみます。言語はPythonを使います。

コード


REQ-REPで試してみます。Public keyとSecret keyを作成するコード、サーバーのコード、クライアントのコードが必要になります。

キー作成


次のgen_keys.pyを作成し、pythonで実行します。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import os
import zmq
import zmq.auth

def main():
    os.makedirs("cert", exist_ok=True)
    server_public_file, server_secret_file = zmq.auth.create_certificates("cert", "server")
    client_public_file, client_secret_file = zmq.auth.create_certificates("cert", "client")

if __name__ == '__main__':
    main()
すると、certディレクトリに
client.key
client.key_secret
server.key
server.key_secret
の4つのファイルが作成されます。

サーバー


サーバーのコードは以下の通り。サーバー側に認証機能をつけます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import zmq
import zmq.auth
from zmq.auth.thread import ThreadAuthenticator

def main():
    ctx = zmq.Context.instance()
    auth = ThreadAuthenticator(ctx)
    auth.start()
    auth.configure_curve(location="cert") # Need only public keys
    server = ctx.socket(zmq.REP)
    server.curve_publickey, server.curve_secretkey = zmq.auth.load_certificate("cert/server.key_secret")
    server.curve_server = True
    server.bind('tcp://*:9000')

    while True:
        msg = server.recv_pyobj()
        print("server:", msg)
        server.send_pyobj("123")

if __name__ == '__main__':
    main()
無限ループをCtrl+Cで止める前提なので入れていませんが、普通はauth.stop()で認証用スレッドを終了しましょう。

クライアント


クライアントのコードは以下の通り。サーバーのpublic keyが必要です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import zmq
import zmq.auth

def main():
    ctx = zmq.Context.instance()
    client = ctx.socket(zmq.REQ)
    client.curve_publickey, client.curve_secretkey = zmq.auth.load_certificate("cert/client.key_secret")
    client.curve_serverkey, _ = zmq.auth.load_certificate("cert/server.key")
    client.connect('tcp://127.0.0.1:9000')

    client.send_pyobj("abc")
    msg = client.recv_pyobj()
    print("client:", msg)

if __name__ == '__main__':
    main()

サーバーを実行し、その後、クライアントを実行すると、サーバー側に

server: abc
クライアント側に
client: 123
と表示されます。

クライアント側で指定するサーバーのPublic keyを間違えるとサーバーには接続できません。 また、Wiresharkで通信内容を見た限りでは、abcや123は平文では通信されていませんでした。 一方、認証関連のコード(authやcurve関連)を削除して実行すると、abcや123を平文で読むことができました。

参考


https://github.com/zeromq/pyzmq/blob/main/examples/security/generate_certificates.py
https://github.com/zeromq/pyzmq/blob/main/examples/security/ironhouse.py

0 件のコメント :