PostgreSQLでの透過的暗号化

Masahiko Sawada
nttlabs
Published in
8 min readFeb 25, 2019

NTT OSSセンタの澤田です。NTT OSSセンタでは、PostgreSQLをより便利で強力なデータベースにするために、PostgreSQLコミュニティと連携してさまざまな開発を行っています。

近年PostgreSQLの適用領域が広がってきおり、金融系システムや、個人情報を扱うシステムにも適用したいという要望が高まってきています。NTT OSSセンタでは、PCI-DSS(クレジットカードのセキュリティについて国際規約)等のよりセキュリティ要件の高い環境でもPostgreSQLを利用できるようにするために、セキュリティ機能の強化に取り組んでいます。その中でも、保存データの暗号化を行う「透過的暗号化機能」は最も注力して開発している機能の一つです。

本記事では、開発中の透過的暗号化機能の概要や特徴について解説します。

PostgreSQLの暗号化における課題

PostgreSQLはPGP暗号化関数をはじめとした様々な暗号化、復号を行うSQL関数を提供するpgcryptoというツールを提供しています。pgcryptoを利用することでDBデータを保護することは可能ですが、以下の2つの課題があります。

1. 暗号化するデータに対してSQLの中で明示的に暗号化、復号関数を実行する必要がある
2. 外部の鍵管理サーバと連携できない

1つ目の課題は、主にアプリケーション開発、修正コストに関連します。アプリケーションを開発する際に、暗号化する列と、そうでない列を意識する必要があり、暗号化対象テーブルの変更に応じて修正する必要があります。

特に修正コストが影響が大きくなる一つの例として、DBマイグレーションが挙げられます。例えば、マイグレーション元のDBで透過的暗号化を利用している場合、マイグレーション先としてPostgreSQLを選定すると、DBマイグレーション時に現行のアプリケーション、SQLの大幅な修正が必要となります。PostgreSQLでは、pgcryptoやトリガ、ビューを用いることで修正にかかるコストを減らすことも可能ですが、依然大きなコストがかかる可能性があります。これらのコストは、透過的暗号化を利用することで大幅に削減することが可能です。

透過的暗号化は、DBの中で自動的にテーブルやインデックスのデータを暗号化して保存する機能です。ユーザは、(pgcryptoのように)データを操作するSQLのレベルで暗号化・復号の操作を記述する必要はないため、データが暗号化されていることを意識することなく、アプリケーションを開発できます。

また、2つ目の課題は、暗号化に用いる鍵の管理に関連します。

暗号化において、暗号鍵の管理はとても重要です。暗号鍵の管理が十分でない場合や、暗号鍵を平文のまま、暗号化されたデータと保存している場合、いくら強力な暗号アルゴリズムでDBデータを暗号化しても意味がありません。堅牢に鍵を管理する方法として鍵管理サーバを利用する方法があります。

透過的暗号化、鍵管理サーバとの連携、それぞれについての詳細を説明します。なお、本機能は開発中であるため、設計や仕様は変更される可能性があります。

透過的暗号化

NTT OSSセンタで開発中の透過的暗号化機能はdata at rest encryptionと呼ばれるもので、PostgreSQLがDBデータを暗号化してディスク上に保存することで、cat等のコマンドによるDBデータののぞき見、ディスクの物理的な盗難等の脅威からデータを守ることができます。

テーブルスペース(テーブルやインデックスを格納する物理的な場所)単位で透過的暗号化機能を有効にし、そのテーブルスペース上に作成されたテーブルやインデックスを自動的に暗号化します。以下に、暗号化機能を有効にしたテーブルスペースの作成、また、そのテーブルスペース上にテーブルの作成するSQLを記載します。

— 暗号化機能を有効にしたテーブルスペース(enctblsp)の作成
CREATE TABLESPACE enctblsp LOCATION ‘/path/to/enctblsp’ WITH (encryption_algorith = ‘aes-128’);

— enctblsp内にテーブルを作成する。自動的に暗号化される
CREATE TABLE card (userid int, card_number text) TABLESPACE enctblsp;

性能オーバヘッドの低減

PostgreSQLでは、テーブル、インデックス等のデータは共有バッファ上にキャッシュされ、テーブルの読み込み、更新処理はバッファ上のデータに対して行われます。そして、更新されたデータは、チェックポイント等のタイミングで定期的にディスク上のデータへ書き戻されます。このようにすることで、ディスクアクセスの回数を最小限に抑えています。透過的暗号化機能では、PostgreSQLが持つ共有バッファからDBデータを出し入れする際に、データの暗号化、復号処理を行うため、これらの処理の実行回数を最小限に抑えることができます。pgcryptoを用いた従来手法の暗号化では約20%の性能低下が観測された一方、評価用コードを用いた本手法では、約2%の性能低下に留まりました。

2層鍵アーキテクチャ

鍵の漏洩、盗難等の脅威に対応するために、暗号鍵は定期的に更新する必要があります。また、PCI-DSSでも定期的な鍵の更新が求められています。

鍵の更新では、暗号化対象データを現在の鍵で復号し、新しい鍵で再度暗号化します。そのため、暗号化対象のデータサイズに応じて、鍵更新にかかる時間も長くなります。暗号化されたDBのデータに対する鍵更新を、そのデータの復号と再暗号化によって実現した場合、大規模なDBでは長時間かかってしまいます。このようなデメリットは、実運用では大きな制約となる可能性があります。

このような課題を解決するために、本機能では、2種類の暗号化鍵、マスタ鍵とデータ鍵を利用してデータを暗号化する方式を利用しています。マスタ鍵はデータ鍵を暗号化するために使われ、暗号化対象データとは別の場所(鍵管理サーバ内など)に保存されます。データ鍵はDBデータを暗号化する暗号鍵で、マスタ鍵により暗号化された状態であれば、暗号対象データと同じ場所に保存することが可能です。このように、DBデータをデータ鍵で暗号化し、そのデータ鍵をマスタ鍵で暗号化するような2層の鍵のアーキテクチャを採用しています。

2層鍵アーキテクチャの最大のメリットは、鍵更新の高速化です。2層鍵アーキテクチャでは、鍵更新時にマスタ鍵を更新し、更新したマスタ鍵でデータ鍵のみを再暗号化します。データ鍵の中身は変更しないためDBデータを再暗号化する必要はなく、再暗号化するデータ鍵はとても小さいため(AES-128で16 byte)ため、鍵の更新は非常に高速に完了します。

鍵管理サーバとの連携

鍵管理サーバは、様々な鍵を堅牢に管理することに特化したサーバです。現在では、Gemalto社のVirtual KeySecureやAmazon Web Service社のAWS Key management Serviceなど、鍵管理サーバをSaaSとして提供するサービスも多くあります。

開発中の透過的暗号化機能では、鍵管理サーバとの連携が可能な仕組みを入れながら開発を進めています。マスタ鍵は鍵管理サーバに格納され、PostgreSQLが必要に応じて鍵管理サーバから取得します。PostgreSQLが直接鍵管理サーバと連携できることで、より堅牢に暗号鍵を管理することが可能です。

おわりに

NTT OSSセンタで開発中の透過的暗号化機能の概要について紹介しました。本機能では、暗号化、復号処理にかかるオーバヘッドを最小限に留めながら、鍵管理サーバとの連携より堅牢な鍵管理が可能です。ただし、管理者権限を持ったDBユーザによるデータののぞき見や、メモリダンプ取得による共有バッファ上のデータの取得等の脅威には対応していません。これらの脅威は、OS上の権限管理、監査などの他のセキュリティ機能で対応する必要があります。

本機能はすでにPostgreSQLコミュニティに提案中です。コミュニティの開発用メーリングリスト上や、様々なカンファレンスにて開発者と議論を行いながら、開発を進めています。直近では、2019年2月に開催されたFOSDEM PGDAY2019(FOSDEM 2019に併設されたPostgreSQLのカンファレンス)にて、NTT OSSセンタから文、澤田が本機能についてその概要と検証結果について発表を行いました。講演後は、ユーザや開発者の方々からポジティブな反応を多く頂きました。今後は、さらにコミュニティ内での議論を進めて、PostgreSQLへ正式に取り込まれるように活動していきたいと考えています。

私たちNTTは、グローバルなPostgreSQL開発コミュニティなど、オープンソースコミュニティで共に活動する仲間を募集しています。ぜひ弊社ソフトウェアイノベーションセンタ紹介ページや、採用情報ページをご覧ください。

--

--