zkat’s diary

技術ブログ

CT(Certificate Transparency:RFC6962)の勉強メモ

概要

RFC6962の4.4と4.5に記載される、get-sth-consistencyget-proof-by-hashという仕組みで何か情報が取れるらしいのだが、 なにに使えるのかよくわからなかったので、調べた結果をめも

get-sth-consistencyとget-proof-by-hash

RFCにはそれぞれ以下のように書いてある。

4.4. Retrieve Merkle Consistency Proof between Two Signed Tree Heads

4.5. Retrieve Merkle Audit Proof from Log by Leaf Hash

RFC 6962 - Certificate Transparency

ここでいう、Consistency ProofとAudit Proofってなんだろうという疑問をもった。
以下に詳しい説明があったので確認してみる。

www.certificate-transparency.org

A Merkle consistency proof lets you verify that any two versions of a log are consistent

A Merkle audit proof lets you verify that a specific certificate has been included in a log

consistency proofを用いることで二つのMerkle Hash Tree(新旧)に一貫性があることを確認できる。
audit proofを用いることで、特定の証明書がMerkle Hash Treeに存在していることを確認できる。
上記、certificate-transparency.orgのサイトで詳細が図示されてて分かりやすい

UbuntuでOpenSSL1.1.1をソースからビルドしてローカルインストール

概要

タイトルの通り、OpenSSL1.1.1をUbuntuでビルドしてローカルにインスールしたときにやったことメモです

依存ライブラリのインストール

以下の通りPerlのいくつかのモジュールに依存してるらしいので、 インストールします。

$ sudo apt-get install libtext-template-perl libtest-most-perl
 We make increasing use of Perl modules, and do our best to limit
 ourselves to core Perl modules to keep the requirements down.  There
 are just a few exceptions:

 Test::More         We require the minimum version to be 0.96, which
                    appeared in Perl 5.13.4, because that version was
                    the first to have all the features we're using.
                    This module is required for testing only!  If you
                    don't plan on running the tests, you don't need to
                    bother with this one.

 Text::Template     This module is not part of the core Perl modules.
                    As a matter of fact, the core Perl modules do not
                    include any templating module to date.
                    This module is absolutely needed, configuration
                    depends on it.

コンフィグ

以下の通りconfigスクリプトを実行します。 prefixとopenssldirは同じところを記載するのがよいらいしいです。

$ ./config --prefix=/path/to/dir --openssldir=/path/to/dir
The rule of thumb to use when you want something that "just works" for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:
specify both --prefix and --openssldir
set --prefix and --openssldir to the same location

wiki.openssl.org

共有ライブラリのパス

libssl.so.1.1がないと言われたりするので、LD_LIBRARY_PATHにインストール先のlibディレトリを追加します。

$ openssl version
openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
$ export LD_LIBRARY_PATH="/path/to/dir/lib/:$LD_LIBRARY_PATH"
$ openssl version
OpenSSL 1.1.1d  10 Sep 2019

InfluxdbのContinuous Query

はじめに

測定した生のデータをそのままInfluxDBに貯めて、各種操作をすると重すぎるので適当な時間間隔でデータをダウンサンプリングすることにしました。 公式ドキュメントはこちらです。 docs.influxdata.com

Continuous Queryでgroup by timeすることで、ダウンサンプリングします。

シンタックス

Continuous Queryのシンタックスを公式ドキュメントから引用します。

CREATE CONTINUOUS QUERY <cq_name> ON <database_name>
BEGIN
    SELECT <function[s]> 
    INTO <destination_measurement> 
    FROM <measurement> 
    [WHERE <stuff>] 
    GROUP BY time(<interval>)[,<tag_key[s]>]
END

ダウンサンプルした結果は別の適当なretention policydbで保持したくなると思います。 <destination_measurement>は、"dbname"."retention policy name"."measurement name"の形で保存先を指定することができます。 retention policyはあらかじめ作っておく必要があります。 データ取得元の<measurement>も同じ形で指定します。

実行したContinuous Query

show continuous queryすると実行したクエリを表示できます。 time_tookについて5分間の平均をとって格納します。保存先に、"1day"という1日だけデータを保持するretention policyを設定しているので、 古くなったデータは順次消えていきます。

CREATE CONTINUOUS QUERY  cq_downsampled_successed_5min_1day ON downsampled_dnsprobe
BEGIN 
    SELECT mean(time_took)
    INTO downsampled_dnsprobe."1day".mes_cq_downsampled_successed_5min_1day 
    FROM dnsprobe.thirty_five_days.dnsprobe 
    WHERE got_response = 'True' 
    GROUP BY  time(5m), prb_id, af, proto, dst_name, rrtype 
END

データ取得元のdnsprobeは以下のようなスキーマです。

> show field keys
name: dnsprobe
fieldKey       fieldType
--------       ---------
data           string
id             integer
mname          string
name           string
probe_asn      string
probe_asn_desc string
probe_uptime   string
reason         string
rname          string
serial         integer
time_took      float
ttl            integer
type           string

> show tag keys
name: dnsprobe
tagKey
------
af
dst_addr
dst_name
error_class_name
got_response
nsid
prb_id
prb_lat
prb_lon
proto
qname
rrtype
src_addr

Influxdbでpercentileを計算する

組み込みの関数、percentileがinfluxdbに存在するので簡単に計算することができます。

docs.influxdata.com

適当なデータを積んで、計算してみます。 あるサーバーへのRTTを測定していることを想定し、以下のようなデータを適当に作りました。

insert testdb,server=target1,addr=v4,proto=tcp measured=98.4236389454876
insert testdb,server=target1,addr=v4,proto=tcp measured=49.02986276817023
insert testdb,server=target1,addr=v4,proto=tcp measured=73.68319133987919
insert testdb,server=target1,addr=v4,proto=udp measured=14.515447132468166
insert testdb,server=target1,addr=v4,proto=udp measured=10.153058203214846
insert testdb,server=target1,addr=v4,proto=udp measured=13.858574248282208
insert testdb,server=target1,addr=v6,proto=tcp measured=37.193169776622106
insert testdb,server=target1,addr=v6,proto=tcp measured=75.22886073245671
insert testdb,server=target1,addr=v6,proto=tcp measured=6.350597491749054
insert testdb,server=target1,addr=v6,proto=udp measured=9.58538941785223
insert testdb,server=target1,addr=v6,proto=udp measured=14.100650500638428
insert testdb,server=target1,addr=v6,proto=udp measured=15.64195452574981

20パーセンタイルと50パーセンタイルを計算してみます。

> select percentile(measured, 20) from testdb group by proto
name: testdb
tags: proto=tcp
time                percentile
----                ----------
1577766044022027112 6.350597491749054

name: testdb
tags: proto=udp
time                percentile
----                ----------
1577766044050092539 9.58538941785223


> select percentile(measured, 50) from testdb group by proto
name: testdb
tags: proto=tcp
time                percentile
----                ----------
1577766043809580444 49.02986276817023

name: testdb
tags: proto=udp
time                percentile
----                ----------
1577766043931028528 13.858574248282208

10パーセンタイルで計算して結果をgnuplotで図示してみます。横軸はlogスケールで示しています。

f:id:zkat:20191231133754p:plain
influxdb-percentile

CT(Certificate Transparency)ログサーバーに書き込める証明書

結論

RFC 6962によれば、ルートに信頼の連鎖がある証明書を登録することができるようです。
1. Informal Introduction

In order to avoid logs being spammed into uselessness, it is required that each chain is rooted in a known CA certificate.

3.1. Log Entries

Each submitted certificate MUST be accompanied by all additional certificates required to verify the certificate chain up to an accepted root certificate

ログサーバーへの証明書の書き込みは認証局以外も実施することができますが、以上の制約がある為、 悪意ある人が自己署名証明書を作成して、CTログサーバーに登録しまくるようなことはできません。

概要

適当なCTログサーバー(今回はあえてTesttubeというログサーバーにします)について、どんなルートにチェーンする証明書の登録を 許可しているか確認してみます。

Testtubeについての説明は、以下に記載される通りでテスト目的で運用されているログサーバーとなります。

www.certificate-transparency.org

These logs are intended for testing purposes only and will only log certificates that chain to a test root explicitly added to it.

調査

CTログサーバーが受け付ける、ルートの一覧は、次にアクセスすることで取得することができます: https://<log server>/ct/v1/get-roots
Testtubeであれば、https://ct.googleapis.com/testtube/ct/v1/get-rootsです。 アクセスすると、証明書のPEMデータがJSONで取得できるのでIssuer部分を表示してみます。

239件ありましたが、数件挙げてみます。

Issuer
C=AE,O=TEST UAE Government,CN=TEST UAE Global Root CA G4 E2
C=AE,ST=Dubai,L=Dubai,O=Dubai Government,OU=DESC,CN=Dubai Root CA TEST
C=AT,O=A-Trust Ges. fur Sicherheitssysteme im elektr. Datenverkehr GmbH,OU=A-Trust-Test-nQual-04,CN=A-Trust-Test-nQual-04
C=AT,O=Bundesrechenzentrum GmbH,OU=BRZ CA,CN=Test BRZ CA Root 2017
C=AT,ST=Wien,L=Wien,O=e-commerce monitoring GmbH,OU=GLOBALTRUST Certification Service,CN=ECM TEST 2015
C=AU,ST=ACT,L=Lyneham,O=Verizon,OU=IAM Operations,CN=TEST ROOT CA
C=BE,O=GlobalSign nv-sa,CN=GlobalSign Non-Public Root CA - R3 SIT
C=BE,O=GlobalSign nv-sa,CN=GlobalSign Root E46 - staging
C=BE,O=GlobalSign nv-sa,CN=GlobalSign Root R46 - staging

想定通り、ログサーバーからルート証明書を取得することができました。 なお、上述の通り、Testtube自体はテスト用のログサーバーなので、上記記載のルート証明書も広くクライアントが信頼しているようなものではありません。

TLDのZSKでよく使われている署名アルゴリズム

はじめに

DNSSECで使われる署名鍵はKSK(Key Signing Key)とZSK(Zone Signing Key)の2種類があります。

TLDゾーンのZSKについて、どの署名アルゴリズムがよく使わええているか、調べました。

調べ方

まず、TLDの一覧をIANAから取得します。

https://data.iana.org/TLD/tlds-alpha-by-domain.txt

それぞれのTLDに対して、digでDNSKEYレコードを引きます。

DNSKEYリリースレコードのフラグが、256のものがZSKなので、そのアルゴリズム番号を確認します。

記載の番号が具体的になんのアルゴリズムであるかは、以下に記載のとおりです。

www.iana.org

例えば、よく使われる番号8であればRSASHA256であることを表します。

結果

2019年11月25日時点の結果で以下の通りとなりました。 ZSKは、ロールオバーの都合などを理由にあるゾーンで複数存在し得るので、 件数の総数はTLDの数より多くなっています。

二モニック アルゴリズム番号 ZSKの件数
RSASHA256 8 1568
RSASHA1-NSEC3-SHA1 7 488
RSASHA512 10 35
RSASHA1 5 32
ECDSAP256SHA256 13 8

RSASHA256を使用しているTLDが圧倒的でした。 今後普及してくるかもしれない、アルゴリズム番号13のECDSAを使っているTLDは具体的には以下でした。 全て、ccTLDでした。

アルゴリズム番号13のTLD
BR.
CZ.
LI.
NU.
SK.
UA.

Google Chromeで表示されるCertificate TransparencyのLog IDがKnown Logsに存在するか確認する方法

はじめに

Google Chromeでは、デベロッパーツールにて以下のように、閲覧しているウェブサイトの証明書がどのCTログサーバーに登録されているのか表示することができます。 例えば、google.comにて表示しています。

f:id:zkat:20191123144155j:plain
certificate-transparency-google.com

Google Chromeが自身のCTポリシーに準拠していると判断した対象のCTログサーバーのリスト(Known Logs)は、次の通りjsonにて公開されています。 www.certificate-transparency.org

確認方法

Chromeにて表示したgoogle.comのLog IDに注目すると、以下のようになっています。

Log name Log ID
Google 'Argon2020' log B2 1E 05 CC 8B A2 CD 8A 20 4E 87 66 F9 2B B9 8A 25 20 67 6B DA FA 70 E7 B2 49 53 2D EF 8B 90 5E
Cloudflare 'Nimbus2020' Log 5E A7 73 F9 DF 56 C0 E7 B5 36 48 7D D0 49 E0 32 7A 91 9A 0C 84 A1 12 12 84 18 75 96 81 71 45 58

Known Logsのjsonをみると、log_id部分がbase64にてエンコードされていますので、16進数をbase64に変換しましょう

$ echo -en "\xB2\x1E\x05\xCC\x8B\xA2\xCD\x8A\x20\x4E\x87\x66\xF9\x2B\xB9\x8A\x25\x20\x67\x6B\xDA\xFA\x70\xE7\xB2\x49\x53\x2D\xEF\x8B\x90\x5E" | base64
sh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4=
$ echo -en "\x5E\xA7\x73\xF9\xDF\x56\xC0\xE7\xB5\x36\x48\x7D\xD0\x49\xE0\x32\x7A\x91\x9A\x0C\x84\xA1\x12\x12\x84\x18\x75\x96\x81\x71\x45\x58" | base64
Xqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFxRVg=

以下の通り、Known Logsに記載されていることを確認できました。

{
          "description": "Google 'Argon2020' log",
          "log_id": "sh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4=",
          "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6Tx2p1yKY4015NyIYvdrk36es0uAc1zA4PQ+TGRY+3ZjUTIYY9Wyu+3q/147JG4vNVKLtDWarZwVqGkg6lAYzA==",
          "url": "https://ct.googleapis.com/logs/argon2020/",
          "mmd": 86400,
          "state": {
            "usable": {
              "timestamp": "2018-06-15T02:30:13Z"
            }
          },
          "temporal_interval": {
            "start_inclusive": "2020-01-01T00:00:00Z",
            "end_exclusive": "2021-01-01T00:00:00Z"
          }
        },
略
        {
          "description": "Cloudflare 'Nimbus2020' Log",
          "log_id": "Xqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFxRVg=",
          "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01EAhx4o0zPQrXTcYjgCt4MVFsT0Pwjzb1RwrM0lhWDlxAYPP6/gyMCXNkOn/7KFsjL7rwk78tHMpY8rXn8AYg==",
          "url": "https://ct.cloudflare.com/logs/nimbus2020/",
          "mmd": 86400,
          "state": {
            "usable": {
              "timestamp": "2018-06-15T02:30:13Z"
            }
          },
          "temporal_interval": {
            "start_inclusive": "2020-01-01T00:00:00Z",
            "end_exclusive": "2021-01-01T00:00:00Z"
          }
        },