このトピックでは、クライアントからApsaraDB RDS for PostgreSQLインスタンスに常に機密データベース機能を使用する方法について説明します。
前提条件
常に機密データベース機能が有効になっています。 詳細については、「常に機密データベース機能の有効化」をご参照ください。
機密データが定義される。 詳細については、「機密データの定義」をご参照ください。
Always機密データベースへの接続に使用される情報が取得されます。 クライアントから常に機密データベース機能を使用する前に、ドメイン名 (ホスト) 、ポート番号 (ポート) 、データベース名 (dbname) 、ユーザー名 (ユーザー名) 、パスワード (パスワード) など、常に機密データベースに関する接続情報を取得する必要があります。 RDSインスタンスの内部エンドポイントとパブリックエンドポイントを取得する方法の詳細については、「ApsaraDB RDS For PostgreSQLインスタンスのエンドポイントとポート番号の表示と変更」をご参照ください。
このトピックでは、Javaアプリケーションを例として使用します。 Java開発環境がインストールされていることを確認してください。 Java
1.8
以降、Maven3.9.2
、およびIntelliJ IDEA Community Edition 2022.3.2
を使用することを推奨します。
使用上の注意
マスター暗号化キー (MEK)
を保存し、機密を保持する必要があります。
例
この機能は、クエリ結果の機密データを暗号化します。 アプリケーションでこの機能を使用するには、次の種類のクライアントからこの機能を使用できます。
接続方法 | 説明 | ビジネスコードの変更が必要 | |
アプリケーション | EncJDBC | EncJDBCは、暗号化するデータ型を自動的に識別し、データを暗号化または復号します。 | いいえ。 この方法をお勧めします。 |
EncDB SDK | クライアント上のデータを暗号化または復号化するには、EncDB SDKによって提供される暗号化または復号化関数を呼び出す必要があります。 | はい。 | |
psql | psqlツールは、データベース内のデータをクエリできるコマンドラインツールです。 psqlは暗号文データのみを取得します。 | いいえ。 psqlはクエリにのみ使用されるため、ビジネスコードを変更する必要はありません。 | |
データ管理 (DMS) コンソールなどのビジュアルツールとインタラクティブツール |
EncJDBC
ドライバーのダウンロードと依存関係の設定
EncJDBCドライバをダウンロードします。
EncJDBC
は、コミュニティが提供するPostgreSQLドライバーに依存します。RDSインスタンスのマイナーエンジンバージョン
RDSインスタンス上のEncDBのバージョン
クライアントのEncDB依存関係パッケージ
20230830以降
1.1.13以降
Mavenの依存関係を設定します。
説明このセクションでは、Mavenを使用してクライアントを構成します。
次のコマンドを実行して、
EncJDBC
依存関係パッケージをオンプレミスリポジトリにインストールします。mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<Name of the installed JAR package> -Dversion=<Version of the installed JAR package> -Dpackaging=jar -Dfile=<File name of the installed JAR package>
例:
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バージョンを使用している場合は、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 does not support java 1.8 since 1.5.0 --> <version>1.4.0</version> </dependency> ... </dependencies>
クライアントからのデータの照会 (サンプルコード)
このセクションでは、デモ用のサンプルコードを示します。 実際のビジネスコードでは、password
およびmek
パラメーターをプレーンテキストの値に設定しないでください。 コードでパラメーターを参照する前に、外部設定ファイルや環境変数などのメソッドを使用してパラメーターを設定することをお勧めします。
URL設定の説明
EncJDBC
は、Java Database Connectivity (JDBC) と同じ方法で使用できます。EncJDBC
を使用する前に、データセキュリティを確保するために次の設定を実行する必要があります。// The connection information such as the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). // For more information, see the "Data security-related parameters" section. 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); // ... Initiate a query. ...
説明複数のパラメーターを連結するには、アンパサンド (
&
) を使用できます。mek
などのパラメータはクライアント側で設定され、エンベロープ暗号化を使用してサーバー側に送信されます。 この処理では、mek
の値の機密性が保証される。
完全なサンプルコード
// The connection information such as the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). Specify the parameters based on your business requirements. String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; String mek="00112233445566778899aabbccddeeff"; // This is an example value. We recommend that you use a more complex MEK. String encAlgo="SM4_128_CBC"; String dbUrl = String.format("encjdbc:postgresql://%s:%d/%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); // create table 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))"); // insert data 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(); // check plaintext data String sqlCmd = "SELECT * FROM example WHERE price > ?"; PreparedStatement 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); int price = rs.getInt(3); float miles = rs.getFloat(4); String 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インスタンスのマイナーエンジンバージョン
RDSインスタンス上のEncDBのバージョン
クライアントのEncDB依存関係パッケージ
20230830以降
1.1.13以降
Mavenの依存関係を設定します。
説明このセクションでは、Mavenを使用してクライアントを構成します。
次のコマンドを実行して、
EncDB SDK
依存関係パッケージをオンプレミスリポジトリにインストールします。mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<Name of the installed JAR package> -Dversion=<Version of the installed JAR package> -Dpackaging=jar -Dfile=<File name of the installed JAR package>
例:
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バージョンを使用している場合は、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オブジェクトを初期化するときにデータセキュリティに関連するパラメーターを設定するために必要なAPI操作を提供します。 ほとんどの場合、setMekで指定されたMEKとsetEncAlgoで指定された必要な暗号化アルゴリズムのみを設定する必要があります。 他のパラメーターにはデフォルト設定を使用することを推奨します。// Obtain the connection information such as the domain name (hostname), port number (port), database name (dbname), username (username), and password (password). // Establish a database connection. All JDBC versions are supported. 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); // Initialize the SDK. String mek=...; Constants.EncAlgo encAlgo=...; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(dbConnection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // Call the API operation for data encryption or decryption. // byte[] cipherBytes = cryptor.encrypt(...); // XXX value = cryptor.decryptXXX(...): // ... Initiate a query. ...
説明mek
などのパラメータはクライアント側で設定され、エンベロープ暗号化を使用してサーバー側に送信されます。 この処理では、mek
の値の機密性が保証される。完全なサンプルコード
// Update the connection information such as the domain name (hostname), port number (port), database name (dbname), username (username), and password (password) to your instance information. String hostname = "hostname"; String port = "port"; String dbname = "db"; String username = "user"; String password = "password"; // Establish a database connection. 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); // Initialize the SDK. String mek="00112233445566778899aabbccddeeff"; // This is an example value. We recommend that you use a more complex MEK. Constants.EncAlgo encAlgo=Constants.EncAlgo.SM4_128_CBC; EncdbSDK sdk = EncdbSDKBuilder.newInstance() .setDbConnection(dbConnection) .setMek(mek) .setEncAlgo(encAlgo) .build(); Cryptor cryptor = sdk.getCryptor(); // create table 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))"); // insert data 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(); // check plaintext data 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
参考情報
Java SDKモジュールの概要
EncDB SDK
には、次のJava機能モジュールが含まれています。
psql
psqlを使用して、常に機密データベースのデータを照会できます。 たとえば、psqlを使用してSELECT * FROM example;
ステートメントを実行できます。
上記の出力では、id
とname
はプレーンテキスト列、price
、miles
、secret
は暗号文列です。 暗号化されたデータはRDSインスタンスで表示できません。 これにより、クラウド内外のセキュリティ上の脅威から常にデータを保護できます。
DMSコンソール
DMSコンソールなどの視覚的およびインタラクティブなツールを使用して、常に機密データベースのデータを照会できます。
上の図では、id
とname
はプレーンテキスト列、price
、miles
、secret
は暗号文列です。
よくある質問
データベースに接続するときに
org.postgresql.util.PSQLException: ERROR: db_process_msg_api: process message failure - returned 0xf707000 0
というエラーメッセージが表示された場合はどうすればよいですか?エラーコード0xf7070000は、MEKをインポートできないことを示します。 一方のMEKで暗号化されたデータは、他方のMEKではアクセスできない。 同じアカウントで、異なるMEKを使用して同じAlways機密データベースに接続すると、このエラーが発生する可能性があります。 Always機密データベースに接続する場合は、常に同じMEKを使用することをお勧めします。
私は何をしますか?
スレッド "main" java.lang.IllegalAccessErrorの例外: clas s com.alibaba.encdb.com mon.SymCrypto (無名モジュール @ 0x5c0369c4) は、モジュールjava.baseがcom.sun.cryptoを無名モジュール @ 0x5c0369c4にエクスポートしないため、クラスcom.sun.crypto.provider.SunJCE (モジュールjava.base) にアクセスできません
プログラムを実行するとエラーメッセージが表示されますか?このエラーメッセージは、JDKバージョンが必要なバージョンよりも新しい場合に発生するモジュール間のアクセス許可の問題が原因で表示されることがあります。 このエラーを解決するには、プログラムを実行してcom.sun.crypto.providerをUNNAMEDモジュールにエクスポートするときに、VMオプション
-- add-exports=java.base/com.sun.crypto.provider=ALL-Unnamed
を追加する必要があります。