4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TLSでポスト量子暗号を試してみる (その2: 署名)

Last updated at Posted at 2022-02-22

1. はじめに

この記事では、オープンソースプロジェクトのオープン量子安全(OQS: Open Quantum Safe)のライブラリーliboqsとwolfSSLを組み合わせて、TLSでポスト量子暗号を実際に動かして試してみます。前回の「鍵交換」に引き続き今回は「署名」を中心にみていきいます。ポスト量子暗号標準化(Post-Quantum Cryptography Standardization)の背景については「TLSでポスト量子暗号を試してみる (その1:鍵交換)」を参照してください。

2. ポスト量子暗号の署名アルゴリズム

liboqsでは、署名アルゴリズムとしてNISTコンペティション ラウンド3の最終候補 Dilithium, Falcon, Rainbowの3つがサポートされています。

アルゴリズム 詳細種別
Dilithium Dilithium2
Dilithium2-AES
Dilithium3
Dilithium3-AES
Dilithium5
Dilithium5-AES
Falcon Falcon-512
Falcon-1024
Rainbow Rainbow-I-Classic
Rainbow-I-Circumzenithal
Rainbow-I-Compressed
Rainbow-III-Classic
Rainbow-III-Circumzenithal
Rainbow-III-Compressed
Rainbow-V-Classic
Rainbow-V-Circumzenithal
Rainbow-V-Compressed

表1: liboqsのサポートするアルゴリズム

署名のためのAPIとしては、鍵ペアの生成、署名、検証などのAPIが用意されていて、概ねこれまでの公開鍵署名と同じようなイメージでプログラムすることができるようになっています。

API名 機能
OQS_SIG_keypair 鍵ペアの生成
OQS_SIG_sign 署名
OQS_SIG_verify 検証

表2:主な署名用API

3. TLS1.3の署名と検証

下の図はTLSの公開鍵証明書を利用した公開鍵署名と検証の関連を示しています。ポスト量子暗号でもこの枠組みはそのまま踏襲します。

サーバ側はサーバ証明書にCAによる署名をもらいます。クライアント側はCA証明書を用意しておきます。TLSハンドシェーク時には、TLS1.3では"Certificate"メッセージでサーバ証明書を送り、"Certificate Verify" でそれまでのハンドシェークメッセージに対する署名を送ります。クライアント側では、受けとったサーバ証明書が真正であることをCA証明書の公開鍵で検証し、サーバ証明書の公開鍵で送られてきた署名を検証します。

ServerVerification.png

                        図1: TLSの署名と検証

これらの全ての署名、検証をポスト量子アルゴリズムで実現することで、量子コンピューティングの時代において通信相手に対するピア認証が安全にできることになります。

4. サンプルプログラムを動かしてみる

4.1 サンプルのダウンロード

まずは、ポスト量子暗号を使ったTLSサーバ、クライアントのサンプルをwolfSSLのGithubレポジトリからダウンロードします。

$ git clone https://github.com/wolfssl/wolfssl-example
$ cd wolfssl-examples/pq

4.2 サンプル証明書を見てみる

レポジトリをクローンするとサンプルプログラムと同時にwolfssl-examples/certsディレクトリの下にポスト量子暗号(Falcon)によるCA証明書、サーバ証明書、プライベート鍵などのサンプルファイルも格納されています。OpenSSLコマンドを使ってx509ファイルの内容を見てみるのですが、現在の通常版OpenSSLだと公開鍵の部分がまだポスト量子に未対応のために、正しく表示されません。その部分も正しく表示してみたいという場合は次のようにポスト量子暗号対応のバージョンをダウンロード、ビルドして使用します。ただし、このバージョンは暫定バージョンなのでno-sharedでビルドしてインストールせず、本件のためだけにローカルに使用するのがよいと思います。

liboqsのビルドが必要ですが、これのビルド、インストール方法とポスト量子暗号による鍵交換については「TLSでポスト量子暗号を試してみる (その1:鍵交換)」を参照してください。

ポスト量子暗号アルゴリズム部分をきちんと表示させたい場合は、次にliboqs対応版のOpenSSLをダウンロード、ビルドします。その部分は感じだけでよいという場合は通常版のOpenSSLを使います。

$ tar xf openssl-OQS-OpenSSL_1_1_1-stable-snapshot-2021-08.tar.gz
$ cd openssl-OQS-OpenSSL_1_1_1-stable-snapshot-2021-08
$ ./config no-shared
$ make

ビルドが完了したら、ローカルに作成したopensslコマンドを使用してx509サブコマンドでサンプル証明書の内容を見てみます。
公開鍵証明書のアルゴリズムに "Public Key Algorithm: falcon1024" と表示され、たいへん長い鍵の内容が表示されます。また、下部の署名にも "Signature Algorithm: falcon1024" と表示され長い署名の内容が表示されます。

$ ./apps/openssl x509 -in <サンプルRoot>/certs/falcon_level5_root_cert.pem -text

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1024 (0x400)
        Signature Algorithm: falcon1024
        Issuer: C = CA, ST = ON, L = Waterloo, O = wolfSSL Inc., OU = Engineering, CN = Root Certificate, emailAddress = root@wolfssl.com
        Validity
            Not Before: Jan 15 03:39:16 2022 GMT
            Not After : Jan 15 03:39:16 2023 GMT
        Subject: C = CA, ST = ON, L = Waterloo, O = wolfSSL Inc., OU = Engineering, CN = Root Certificate, emailAddress = root@wolfssl.com
        Subject Public Key Info:
            Public Key Algorithm: falcon1024
                falcon1024 Public-Key:
                pub:
                    0a:8a:50:9f:b6:01:2e:8f:98:5a:a7:9b:05:20:2f:
                    0a:f8:eb:4b:9e:8e:3b:b2:d6:38:07:dc:5c:17:33:
                    ...
                    e7:e7:20:41:fa:f9:da:97:26:48:0c:e2:e0:5b:ee:
                    48:69:0a:8d:f5:0b:f1:98:3d:a2:50:c2:b2:52:ce:
                    b5:80:2d:95:c9:78:64:3a
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                26:36:0F:AA:53:E3:7B:DF:5C:FC:EC:CE:CF:D7:46:8F:F0:54:22:2F
            X509v3 Authority Key Identifier: 
                keyid:26:36:0F:AA:53:E3:7B:DF:5C:FC:EC:CE:CF:D7:46:8F:F0:54:22:2F
                DirName:/C=CA/ST=ON/L=Waterloo/O=wolfSSL Inc./OU=Engineering/CN=Root Certificate/emailAddress=root@wolfssl.com
                serial:04:00

            X509v3 Key Usage: critical
                Certificate Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: falcon1024
         3a:cc:5c:5d:00:11:f6:fa:1a:8d:56:1c:5d:a2:94:ea:19:61:
         6b:6b:37:67:ce:21:df:b7:e8:ab:a1:df:21:54:97:b3:2d:8f:
         ...
         c4:f9:a5:87:17:ef:97:c9:31:b1:d3:93:7f:b8:bb:38:6c:6b:
         02:f0:2a:5b:18:2f:40:95:2b:54:b3:cd
-----BEGIN CERTIFICATE-----
MIIOkDCCCYagAwIBAgICBAAwBwYFK84PAwQwgZYxCzAJBgNVBAYTAkNBMQswCQYD
VQQIDAJPTjERMA8GA1UEBwwIV2F0ZXJsb28xFTATBgNVBAoMDHdvbGZTU0wgSW5j
...
28cMdmpWFmVxK2dJrbXn25qOIgu2fFMD6FS2PelvTejVPpF4Oi515dR6uvhlzKu1
iCAvy8OexPmlhxfvl8kxsdOTf7i7OGxrAvAqWxgvQJUrVLPN
-----END CERTIFICATE-----

通常版のOpenSSLでは、アルゴリズムのOIDが生のまま表示され、内容の表示は残念ながらエラーとなってしまいますが、だいたいの感じは理解できるかと思います。:

Public Key Algorithm: 1.3.9999.3.4

いずれにせよ、これでわかるように現状のポスト量子暗号による公開鍵や署名は少々長くなってしまいます。致命的な長さではないもののこれがTLSハンドシェークとして送られることを考えると改善課題ではあります。

4.3 wolfSSLとサンプルのビルド

最新のwolfSSLライブラリーはポスト量子暗号に対応しているので、TLSによる通信自身については普通のTLSサーバとクライアントを使用してもよいのですがTLS1.3ではハンドシェークメッセージが暗号化されていてそのままでは見えません。これを復号してメッセージを見るためにはサンプルプログラム中にセッション鍵情報を取得する仕掛けを埋め込んでおいて、その情報をWiresharkで参照する必要があります。wolfSSLライブラリのほうもそのためのオプションを指定してビルドする必要があります。

wolfSSLのダウンロード、ビルド手順は "その1:鍵交換"で紹介した手順と基本的に同じですが、上記オプション指定を追加します。

$ git clone https://github.com/wolfssl/wolfssl
$ cd wolfssl
$ ./autogen.sh
$ ./configure --with-liboqs CFLAGS="-DHAVE_SECRET_CALLBACK"
$ make all
$ sudo make install

サンプルプロラムのビルドも同様のオプションを追加します。

$ cd wolfssl-examples/pq
$ make CFLAGS="-DHAVE_SECRET_CALLBACK"

4.4 TLSハンドシェークを見てみる

次に、サンプルサーバとクライアントを動作させてTLSハンドシェークのほうを見てみることにします。サンプルはwolfssl-examples/pq/server-pq-tls13.cとclient-pq-tls13.cを使います。

サンプルクライアント(client-pq-tls13.c) のソースコードを見ると、下のようにデフォルトの証明書パスが定義され、それがロードされていることがわかります。それ以外の部分は普通のTLSクライアントです。サーバ側(server-pq-tls13.c)もほぼ同様です。

#define CERT_FILE "../certs/falcon_level5_root_cert.pem"

char *cert_file = CERT_FILE;

/* 証明書のロード */
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, cert_file, NULL))

Wireshark を立ち上げて、サンプルサーバを起動します。

$ ./server-pq-tls13 

次にクライアント側を起動し、サーバに送るメッセージを入力します。

$ ./client-pq-tls13 127.0.0.1
Message for server: Hello Server
Server: I hear ya fa shizzle!

その内容はサーバ側に表示されます。

Waiting for a connection...
Client connected successfully
Client: Hello Server

Waiting for a connection...

この状態でWireshakeを "Filter:tls" で見てみると、下のように"Server Hello" が暗号化された状態で表示されます。

No.	Time	Source	Destination	Protocol	Length	Info
889	10.059814	127.0.0.1	127.0.0.1	TLSv1.3	1990	Client Hello
891	10.078259	127.0.0.1	127.0.0.1	TLSv1.3	1820	Server Hello
893	10.078592	127.0.0.1	127.0.0.1	TLSv1.3	84	Application Data
...
1447	19.384021	127.0.0.1	127.0.0.1	TLSv1.3	91	Application Data
1449	19.384158	127.0.0.1	127.0.0.1	TLSv1.3	100	Application Data
1451	19.384188	127.0.0.1	127.0.0.1	TLSv1.3	80	Application Data

この時、サンプルプログラムを起動したディレクトリの直下に "sslkeylog.log" という名前でセッション鍵情報のファイルが生成されているはずです。Wirehsarkの設定→プロトコル→TLS→"(Pre)-Master-Secret log file name"でこのファイル名を指定すると下のように各メッセージが復号されて表示され普通のTLS1.3のハンドシェークであることがわかります。

No.	Time	Source	Destination	Protocol	Length	Info
889	10.059814	127.0.0.1	127.0.0.1	TLSv1.3	1990	Client Hello
891	10.078259	127.0.0.1	127.0.0.1	TLSv1.3	1820	Server Hello
893	10.078592	127.0.0.1	127.0.0.1	TLSv1.3	84	Encrypted Extensions
895	10.078722	127.0.0.1	127.0.0.1	TLSv1.3	3871	Certificate
897	10.079683	127.0.0.1	127.0.0.1	TLSv1.3	1358	Certificate Verify
899	10.080004	127.0.0.1	127.0.0.1	TLSv1.3	114	Finished
901	10.087176	127.0.0.1	127.0.0.1	TLSv1.3	114	Finished
903	10.087343	127.0.0.1	127.0.0.1	TLSv1.3	238	New Session Ticket
1447	19.384021	127.0.0.1	127.0.0.1	TLSv1.3	91	Application Data
1449	19.384158	127.0.0.1	127.0.0.1	TLSv1.3	100	Application Data
1451	19.384188	127.0.0.1	127.0.0.1	TLSv1.3	80	Alert (Level: Warning, Description: Close Notify)

まずは、 "Client Hello" の内容をみてみます。"Signature Algorithms" の "Signature Hash Algorithms" を見てみると "Unknown Unknown (0xfe0b)" のように生のID値が示されてりるものが二つほどあるのがわかります。wolfSSLのこのバージョンでサポートしているFalcon Level1 とLevel5なのですが、通常版のWiresharkではまだこれらのアルゴリズムのシンボル表示に対応していないのでこのように表示されます。(こちらのパッチで内容を表示することもできます。)

        Handshake Protocol: Client Hello
            ...
            Extension: signature_algorithms (len=36)
                Type: signature_algorithms (13)
                Length: 36
                Signature Hash Algorithms Length: 34
                Signature Hash Algorithms (17 algorithms)
                    Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                    ...
                    Signature Algorithm: Unknown Unknown (0xfe0b) <--- Falcon Level 1
                    Signature Algorithm: Unknown Unknown (0xfe0e) <--- Falcon Level 5
                    ...

次に、"Certificate" の内容を見てみると、Signature 、subjectPublicKeyのAlgorithm IDとしてiso.3.9999.3.4とFalconに対応する生のID値が表示されているのがわかります。

            Handshake Type: Certificate (11)
            Length: 3789
            Certificate Request Context Length: 0
            Certificates Length: 3785
            Certificates (3785 bytes)
                Certificate Length: 3780
                Certificate: 30820ec0308209baa00302010202020401300706052bce0f0304308196310b3009060355… 
                    signedCertificate
                        version: v3 (2)
                        serialNumber: 0x0401
                        signature (iso.3.9999.3.4)
                            Algorithm Id: 1.3.9999.3.4 (iso.3.9999.3.4)
                        ...
                        subjectPublicKey: 
                        0a4b323a9b7f054c1d518c50dfd2ee85f8f3c2b70b3a29847e28a9658f034c227acf2150…
                        extensions: 6 items
                    algorithmIdentifier (iso.3.9999.3.4)
                        Algorithm Id: 1.3.9999.3.4 (iso.3.9999.3.4)
                    Padding: 0
                    encrypted: 3ac3fcf54764f8a90c3e390bb76f1bbc0f501b6b5ea20ba39d0eda45b38d3a7baf2c2854…
                Extensions Length: 0

サンプルのサーバ、クライアントは次のようにオプションアーギュメントでファイル名を指定できるようになっているので、certsディレクトリ下のその他のサンプルファイルやその他のファイルで試すこともできます。

$ ./server-pq-tls13 [<サーバ証明書> <プライベート鍵>]
$ ./client-pq-tls13 IPアドレス [<CA証明書>] 

5. まとめ

この記事では、ポスト量子暗号によるTLSプロトコルのうち署名部分ついてみてきました。記事中にもコメントしたように、従来のRSAやECCによる署名にくらべて署名サイズはかなり大きなものになってしまう点でアルゴリズムにはまだまだ改善の余地があるようにも感じられます。しかし、現時点でTLSの枠組みののなかでまがりなりにも実際に使用できるアルゴリズムができあがりつつあることが感じられるかと思います。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?