このガイドでは、クライアントアプリケーションから完全暗号化データベースに接続して使用する方法について説明します。
前提条件
完全暗号化データベースを有効化していること。詳細については、「完全暗号化データベースの有効化」をご参照ください。
機密データを含む列を定義していること。詳細については、「機密データの定義または変換」をご参照ください。
データベース接続の詳細 (ホスト名、ポート、データベース名、ユーザー名、パスワード) を取得していること。インスタンスのパブリックエンドポイントと内部エンドポイントを確認する方法については、「接続エンドポイントとポートの表示または変更」をご参照ください。
本記事で説明するアプリケーションは、Java を使用して開発されています。 Java 開発環境があることを確認してください。 Java バージョン
1.8以降、Maven バージョン3.9.2、および開発ツールとしてIntelliJ IDEA Community Edition 2022.3.2を使用することをお勧めします。
注意事項
マスターキー (MEK) を安全に保管してください。
クライアントの例
完全暗号化データベース機能は、クエリ結果に含まれる機密データを暗号化します。アプリケーションで暗号化データを処理できるようにするには、次のいずれかのクライアントアクセス方法を使用して接続します。
アクセス方法 | 説明 | コード変更 | |
アプリケーション | EncJDBC | 暗号化されたデータ型を自動的に検出し、暗号化と復号を処理します。 | (推奨) ビジネスロジックコードの変更はほとんど必要ありません。 |
EncDB SDK | プレーンテキストまたは暗号文を処理するには、EncDB SDK から暗号化および復号関数を呼び出す必要があります。 | 必須。 | |
psql コマンドラインツール | クエリのためにデータベースに直接接続します。暗号化された列の暗号文のみが表示されます。 | クエリ専用です。この方法はアプリケーション開発用ではないため、コードの変更は必要ありません。 | |
DMS コンソールなどのビジュアルインタラクションツール | |||
EncJDBC
ドライバーと依存関係のダウンロード
EncJDBC ドライバーをダウンロードします。
EncJDBCは、コミュニティ提供の PostgreSQL ドライバーに依存します。RDS PostgreSQL マイナーバージョン
サーバー側プラグインのバージョン
クライアントの依存関係
20230830 以降
1.1.13 以降
Maven の依存関係を設定します。
説明このガイドでは、Maven プロジェクトを例として使用します。
次のコマンドを実行して、
EncJDBC依存関係パッケージをローカルリポジトリにインストールします。mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<jar_name> -Dversion=<jar_version> -Dpackaging=jar -Dfile=<jar_filename>例:
mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=encjdbc -Dversion=1.0.6 -Dpackaging=jar -Dfile=D:\encdb\libs\encjdbc-1.0.6.jar説明この例では、EncDB 依存関係パッケージは
D:\encdb\libsディレクトリにあります。この例では、Maven バージョン
3.9.2を使用します。インストールでエラーが発生した場合は、Maven のバージョンをアップグレードして再試行してください。
ローカルリポジトリに
EncJDBC依存関係をインストールした後、Maven プロジェクトの pom.xml ファイルに次の依存関係を追加する必要があります。<dependencies> ... <dependency> <groupId>com.alibaba.encdb</groupId> <artifactId>encjdbc</artifactId> <version>1.0.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.62</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.62</version> </dependency> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.23</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>24.1.1-jre</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> <dependency> <groupId>org.jgrapht</groupId> <artifactId>jgrapht-core</artifactId> <!-- jgrapht は 1.5.0 以降、Java 1.8 をサポートしていません --> <version>1.4.0</version> </dependency> ... </dependencies>
クライアントクエリの例
この例に示されているコードは、デモンストレーションのみを目的としています。 本番コードでは、password または mek をプレーンテキストで設定しないでください。 外部設定ファイルや環境変数などの他の方法を使用してこれらの値を扱い、コードから参照することを推奨します。
URL の設定
EncJDBCは、他の JDBC と同様に使用できます。ただし、まずEncJDBCに、データセキュリティに関する以下の情報を設定する必要があります。// 接続詳細 (ホスト名、ポート、データベース名 (dbname)、ユーザー名、パスワード) を準備します。 // 詳細については、データセキュリティパラメータのセクションをご参照ください。 String mek=...; String encAlgo=...; String dbUrl = String.format("encjdbc:postgresql://%s:%s/%s?mek=%s&enc_algo=%s", hostname, port, dbname, mek, encAlgo); Class.forName("com.alibaba.encdb.encjdbc.EncDriver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // ... クエリを実行 ...説明URL 設定では、複数のパラメーターを
&で連結できます。mekとその他のパラメーターは、クライアントのローカルで処理され、エンベロープ暗号化を使用してサーバーに安全に配布されることで、mekが漏洩しないことが保証されます。
完全なコード例
// hostname、port、database name (dbname)、username、password をお使いのインスタンスの詳細に置き換えてください。 String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; String mek="00112233445566778899aabbccddeeff"; // これは一例です。本番環境では、より複雑なキーを使用してください。 String encAlgo="SM4_128_CBC"; String dbUrl = String.format("encjdbc:postgresql://%s:%s/%s?mek=%s&enc_algo=%s", hostname, port, dbname, mek, encAlgo); Class.forName("com.alibaba.encdb.encjdbc.EncDriver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // テーブルの作成 dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example"); dbConnection.createStatement().executeUpdate("CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"); // データの挿入 PreparedStatement stmt = dbConnection.prepareStatement("INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"); int price = 1234; float miles = 12.34f; String secret = "aliyun"; stmt.setInt(1, 1); stmt.setString(2, "name"); stmt.setInt(3, price); stmt.setFloat(4, miles); stmt.setString(5, secret); stmt.execute(); // プレーンテキストデータの確認 String sqlCmd = "SELECT * FROM example WHERE price > ?"; stmt = dbConnection.prepareStatement(sqlCmd); stmt.setInt(1, 100); ResultSet rs = stmt.executeQuery(); while (rs.next()){ int id = rs.getInt(1); String name = rs.getString(2); price = rs.getInt(3); miles = rs.getFloat(4); secret = rs.getString(5); System.out.println(id + ", " + name + ", " + price + ", " + miles + ", " + secret); }サンプル出力:
1, name, 1234, 12.34, aliyun
前述の EncJDBC コード例が示すように、変更が必要なのはドライバーの読み込みと URL 設定のみです。残りのプロセスは標準的なデータベースアクセスと同一です。ビジネス関連のコードを修正する必要はありません。
EncDB SDK
ドライバーと依存関係のダウンロード
EncDB SDK ドライバーをダウンロードします。
EncDB SDKは、コミュニティ提供の PostgreSQL ドライバーに依存します。RDS PostgreSQL マイナーバージョン
サーバー側プラグインのバージョン
クライアントの依存関係
20230830 以降
1.1.13 以降
Maven の依存関係を設定します。
説明このガイドでは、Maven プロジェクトを例として使用します。
次のコマンドを実行して、
EncDB SDK依存関係パッケージをローカルリポジトリにインストールします:mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<jar_name> -Dversion=<jar_version> -Dpackaging=jar -Dfile=<jar_filename>例:
mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=libencdb -Dversion=1.2.12 -Dpackaging=jar -Dfile=D:\encdb\libs\libencdb-1.2.12.jar説明この例では、EncDB 依存関係パッケージは
D:\encdb\libsパスにあります。この例では、Maven バージョン
3.9.2を使用します。インストールエラーが発生した場合は、Maven のバージョンをアップグレードして再試行してください。
ローカルリポジトリに
EncDB SDKの依存関係をインストールした後、Maven プロジェクトの pom.xml ファイルに、次の依存関係を追加する必要があります。<dependencies> ... <dependency> <groupId>com.alibaba.encdb</groupId> <artifactId>libencdb</artifactId> <version>1.2.12</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency> <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.23</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> </dependency> ... </dependencies>
クライアントクエリの例
この例のコードは、デモンストレーションのみを目的としています。本番コードでは、password や mek をプレーンテキストで設定しないでください。代わりに、外部設定ファイルや環境変数を使用し、コード内で参照してください。
SDK の設定
暗号文を送信または受信する前に、
EncDB SDKを使用してデータを暗号化および復号する必要があります。EncDB SDKは、SDK オブジェクトを初期化する際にデータセキュリティパラメーターを設定するためのインターフェースを提供します。通常、マスターキー (setMek) と目的の暗号化アルゴリズム (setEncAlgo) を設定するだけで済みます。その他すべてのパラメーターについては、デフォルト設定を使用することをお勧めします。// 接続詳細 (ホスト名、ポート、データベース名 (dbname)、ユーザー名、パスワード) を準備します。 // 任意の JDBC バージョンを使用してデータベース接続を確立します。 String dbUrl = String.format("jdbc:postgresql://%s:%s/%s?binaryTransfer=true", hostname, port, dbname); Class.forName("org.postgresql.Driver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // SDK を初期化します。 String mek=...; Constants.EncAlgo encAlgo=...; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(dbConnection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // 暗号化/復号インターフェイスを呼び出します。 // byte[] cipherBytes = cryptor.encrypt(...); // XXX value = cryptor.decryptXXX(...): // ... クエリを実行 ...説明mekおよびその他のパラメーターは、エンベロープ暗号化を使用してクライアント上でローカルに処理され、サーバーに安全に配布されます。これにより、mekが漏洩することはありません。完全なコード例
// hostname、port、database name (dbname)、username、password をお使いのインスタンスの詳細に置き換えてください。 String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; // データベース接続を確立します。 String dbUrl = String.format("jdbc:postgresql://%s:%s/%s?binaryTransfer=true", hostname, port, dbname); Class.forName("org.postgresql.Driver"); Connection dbConnection = DriverManager.getConnection(dbUrl, username, password); // SDK を初期化します。 String mek="00112233445566778899aabbccddeeff"; // これは一例です。本番環境では、より複雑なキーを使用してください。 Constants.EncAlgo encAlgo=Constants.EncAlgo.SM4_128_CBC; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(dbConnection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // テーブルの作成 dbConnection.createStatement().executeUpdate("DROP TABLE IF EXISTS example"); dbConnection.createStatement().executeUpdate("CREATE TABLE example (id INTEGER, name VARCHAR, price enc_int4, miles enc_float4, secret enc_text, PRIMARY KEY (id))"); // データの挿入 PreparedStatement stmt = dbConnection.prepareStatement("INSERT INTO example (id, name, price, miles, secret) VALUES(?,?,?,?,?)"); int price = 1234; float miles = 12.34f; String secret = "aliyun"; stmt.setInt(1, 1); stmt.setString(2, "name"); stmt.setBytes(3, cryptor.encrypt("example", "price", price)); stmt.setBytes(4, cryptor.encrypt("example", "miles", miles)); stmt.setBytes(5, cryptor.encrypt("example", "secret", secret)); stmt.execute(); // プレーンテキストデータの確認 String sqlCmd = "SELECT * FROM example WHERE price > ?"; stmt = dbConnection.prepareStatement(sqlCmd); stmt.setBytes(1, cryptor.encrypt("example", "price", 100)); ResultSet rs = stmt.executeQuery(); while (rs.next()) { int id = rs.getInt(1); String name = rs.getString(2); price = cryptor.decryptInt(rs.getBytes(3)); miles = cryptor.decryptFloat(rs.getBytes(4)); String text = cryptor.decryptString(rs.getBytes(5)); System.out.println(id + ", " + name + ", " + price + ", " + miles + ", " + text); }サンプル出力:
1, name, 1234, 12.34, aliyun
SDK リファレンス
Java SDK モジュールの概要
EncDB SDK は主に以下の Java 機能モジュールで構成されています:
psql CLI
完全暗号化データベースでは、psql コマンドラインを使用して SELECT * FROM example; を実行するなど、コマンドラインから直接クエリを実行できます。
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM example;
-[ RECORD 1 ]-----------------------------------------------------------
id | 1
name | name
price | \xac0900ecbd4efc9f36eaf1c17f1ef928a50c26c73d4ac35788f543a7dd0b2fc752459e
miles | \x931900f561358e7a92086b69d3b423fe453466a7ec556387639699153bef078857f99c
secret | \x1d3900a4ffe264f4dc6d0138106869bc09387a500ce150501d60744f404e22a5d9aa62
postgres=#ご覧のとおり、id と name カラムはプレーンテキストですが、price、miles、secret カラムは暗号文になっています。暗号化されたデータはサーバー上では表示できません。これにより、外部および内部のセキュリティ脅威から効果的に保護し、データを常に安全に保つことができます。
DMS コンソール
DMS コンソールなどのビジュアルインタラクションツールから、データベースを直接クエリできます。
SELECT * FROM example; クエリを実行します。結果は次のとおりです。
id | name | price | miles | secret
---+------+--------------------------------------------------------------------------+--------------------------------------------------------------------------+--------------------------------------------------------------------------
1 | name | \xac0900ecbd4efc9f36eaf1c17f1ef928a50c26c73d4ac35788f543a7dd0b2fc752459e | \x931900f561358e7a92086b69d3b423fe453466a7ec556387639699153bef078857f99c | \x1d3900a4ffe264f4dc6d0138106869bc09387a500ce150501d60744f404e22a5d9aa62ご覧のとおり、id 列と name 列は平文ですが、price、miles、および secret 列は暗号文です。
よくある質問
Q:データベースへの接続が次のエラーで失敗します:
org.postgresql.util.PSQLException: ERROR: db_process_msg_api: process message failure - returned 0xf7070000。A:エラーコード 0xf7070000 は MEK のインポート失敗を示します。これは、同じアカウントが異なる MEK を使用して同じ暗号化データベースに接続しようとした場合に発生する可能性があります。マスターキーを変更すると、元のキーで暗号化されたデータにアクセスできなくなります。データベースへの接続には、必ず元のキーを使用してください。
Q:プログラムを実行すると、
Exception in thread "main" java.lang.IllegalAccessError: class com.alibaba.encdb.common.SymCrypto (in unnamed module @0x5c0369c4) cannot access class com.sun.crypto.provider.SunJCE (in module java.base) because module java.base does not export com.sun.crypto.provider to unnamed module @0x5c0369c4というエラーが表示されます。どうすれば修正できますか?A: このエラーは、JDK のバージョンが高いことによるモジュール間の権限の問題が原因である可能性があります。アクセス権限の問題を解決するには、実行時に VM オプションパラメーター
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMEDを追加して、com.sun.crypto.provider を無名モジュールにエクスポートします。