Java アプリケーションから列の暗号化で保護されたデータにアクセスするには、EncJDBC ドライバーを使用してデータベースに接続します。EncJDBC は、最小限の設定で暗号化された列からプレーンテキストを取得します。
マスター暗号化キーを提供すると、データ送信リンク全体が暗号化されます。EncJDBC クライアントは自動的にデータを復号し、アプリケーションが最小限のコード変更で表示できるプレーンテキストを返します。
前提条件
MEK の生成
値の範囲:長さが正確に 32 文字の 16 バイトの 16 進文字列。
列暗号化を設定したときに選択した [キータイプ] に応じて、KMSキー を使用するか、[ローカルキー] を生成して、MEK としてデータベースを復号化できます。
KMS キー
KMS キーを使用する場合、KMS サービスが利用可能であることを確認してください。そうでない場合、常時機密クライアントドライバーである EncJDBC は機能しません。
データベースの列の暗号化設定で選択した [KMS キー] を所有する KMS インスタンスのエンドポイント、およびクライアントからこの KMS キーを読み取るための Alibaba Cloud アカウントまたは RAM ユーザー (KMS 復号権限が必要です) の AccessKey ID と AccessKey シークレットを取得してください。次の手順に従ってください:
コンソールに Alibaba Cloud アカウント または RAM ユーザー を使用してログインします。
ローカルキー
データベースの列の暗号化設定の 暗号化方式 が ローカルキー に設定されている場合は、MEK を生成してください。例:00112233445566778899aabbccddeeff。
一般的な生成方法には、パスワードジェネレーターやプログラミング言語のランダム関数などがあります。
例:
Linux では、
openssl rand -hex 16を実行して、組み込みの OpenSSL ツールを使用してキーを生成します。Windows では、OpenSSL ソフトウェアパッケージをインストールしてください。
クライアント統合手順
Java には JDK 1.8 以降を使用してください。
クライアント側で、データベース接続ドライバーを EncJDBC に切り替え、データベース接続 URL を更新し、MEK を指定して、暗号化されたデータベース列からプレーンテキストにアクセスします。
1. 依存関係のインストール
次の依存関係を Maven プロジェクトの設定ファイル pom.xml に追加します。
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-enc-jdbc</artifactId>
<version>1.0.10-3</version>
</dependency>2. MEK を設定してデータベースに接続
以下の方法では、MEK の設定方法について説明します:JDBC プロパティ設定、ファイル設定、URL 設定。複数の方法を同時に設定した場合の優先順位は、JDBC プロパティ設定 > ファイル設定 > URL 設定です。
URL 設定では、複数のパラメーターを
&で区切ります。以下のすべての設定および接続方法において、
MEKはクライアント上でローカルに処理され、MEKの漏洩を防ぐためにエンベロープ暗号化を使用してサーバーに安全に送信されます。
データベースの列の暗号化設定の [暗号化方式] に基づいて、ローカルキーまたは KMS キーを使用してデータベースに接続することを選択してください。
KMS キーを使用したデータベースへの接続
STS 一時的な認証情報を使用して KMS で管理された MEK を取得する場合は、STS SDK を使用して一時的な認証情報である STS トークンを取得してください。STS SDK の例については、「STS SDK の概要」をご参照ください。
アクセス認証情報 (AccessKey ID と AccessKey シークレット) をアプリケーションコードに直接ハードコードしないでください。この例では、システム環境変数を使用してアクセス認証情報を管理します。詳細については、「Linux、macOS、Windows での環境変数の設定」をご参照ください。
JDBC プロパティ設定
標準の JDBC では、接続時に Properties を使用してカスタムプロパティを設定できます。次の例は、JDBC プロパティを設定して JDBC を実行する方法を示しています:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// 環境変数からアクセス認証情報 (AccessKey ID と AccessKey シークレット) を取得します。
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// STS 一時的な認証情報を使用して KMS キーを読み取る場合は、取得した STS トークンも指定します。
// String stsToken = "yourSecurityToken";
// KMS インスタンスのエンドポイント。パブリックネットワークアクセスが有効な場合はパブリックエンドポイントを使用します。VPC アクセスの場合は VPC エンドポイントを使用します。
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_ID", accessKeyId);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET", accessKeySecret);
props.setProperty("ALIBABA_CLOUD_KMS_ENDPOINT", kmsEndpoint);
// props.setProperty("ALIBABA_CLOUD_STS_TOKEN", "stsToken");
// MySQL の接続 URL 形式: "jdbc:mysql:encdb://%s:%s/%s"
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// MySQL 用の EncJDBC ドライバーをロードします。
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// データベース接続を取得します。
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... クエリを実行 ...URL 設定
以下に示すように、KMS キーを取得するためのパラメーターを URL に直接埋め込むことができます:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// 環境変数からアクセス認証情報 (AccessKey ID と AccessKey シークレット) を取得します。
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// STS 一時的な認証情報を使用して KMS キーを読み取る場合は、取得した STS トークンも指定します。
// String stsToken = "yourSecurityToken";
// KMS インスタンスのエンドポイント。パブリックネットワークアクセスが有効な場合はパブリックエンドポイントを使用します。VPC アクセスの場合は VPC エンドポイントを使用します。
String kmsEndpoint = "kms.cn-hangzhou.aliyuncs.com";
// MySQL の接続 URL 形式。
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint);
// STS トークンを使用する場合。
// String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s&ALIBABA_CLOUD_STS_TOKEN=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint, stsToken);
// MySQL 用の EncJDBC ドライバーをロードします。
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// データベース接続を取得します。
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... クエリを実行 ...ローカルキーを使用したデータベースへの接続
JDBC プロパティ設定
標準の JDBC では、接続時に Properties を使用してカスタムプロパティを設定できます。次の例は、JDBC プロパティを設定して JDBC を実行する方法を示しています:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// マスター暗号化キー。
String mek = "00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
// MySQL の接続 URL 形式: "jdbc:mysql:encdb://%s:%s/%s"。PostgreSQL の場合は、"jdbc:postgresql:encdb://%s:%s/%s" を使用します。
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// MySQL 用の EncJDBC ドライバーをロードします。PostgreSQL の場合は、「com.aliyun.encdb.postgresql.jdbc.EncDriver」を使用します。
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// データベース接続を取得します。
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... クエリを実行 ...ファイル設定
設定ファイルを通じて、必要な MEK などのパラメーターをインポートできます。
ファイル設定は、ローカルキーの MEK にのみ適用されます。
プロジェクトに encJdbcConfigFile という名前の プロパティ を設定し、その値を設定ファイルのパスに設定できます (デフォルトでは、ファイル encjdbc.conf が使用されます)。設定ファイルの内容は次のとおりです:
MEK=00112233445566778899aabbccddeeff設定ファイルは、次の 2 つの場所のいずれかに配置できます:
プロジェクトのリソースディレクトリにファイルを配置します。以下に示します:
src main java resources encjdbc.confプロジェクトのルートディレクトリ (プログラムのランタイムディレクトリ) にファイルを配置します。
ファイル設定を行うと、以下に示すように、コードに追加の設定は不要です:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// MySQL の接続 URL 形式: "jdbc:mysql:encdb://%s:%s/%s"。PostgreSQL の場合は、"jdbc:postgresql:encdb://%s:%s/%s" を使用します。
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// MySQL 用の EncJDBC ドライバーをロードします。PostgreSQL の場合は、「com.aliyun.encdb.postgresql.jdbc.EncDriver」を使用します。
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// データベース接続を取得します。
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... クエリを実行 ...URL 設定
以下に示すように、MEK などのパラメーターを URL に直接埋め込むことができます:
// ホスト名、ポート、データベース名、ユーザー名、パスワードなどの接続情報を準備します。
// ...
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// マスター暗号化キー。
String mek = "00112233445566778899aabbccddeeff";
// MySQL の接続 URL 形式: "jdbc:mysql:encdb://%s:%s/%s?MEK=%s"。PostgreSQL の場合は、"jdbc:postgresql:encdb://%s:%s/%s?MEK=%s" を使用します。
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
// MySQL 用の EncJDBC ドライバーをロードします。PostgreSQL の場合は、「com.aliyun.encdb.postgresql.jdbc.EncDriver」を使用します。
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// データベース接続を取得します。
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... クエリを実行 ...3. 暗号化列からのプレーンテキストデータのクエリ
データベースへの接続に成功したら、標準の JDBC クエリと同様に操作できます。EncJDBC は暗号化列を自動的に復号し、プレーンテキストデータを返します。
サンプルコード:
// クエリを実行します。
// クエリステートメントを作成します。
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
// 結果セットを走査します。
while (resultSet.next()) {
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}トラブルシューティング
IllegalAccessError: cannot access class com.sun.crypto.provider.SunJCE
このエラーは、新しいバージョンの JDK ではデフォルトでモジュール間のアクセスが制限されているために発生します。プログラムの実行時に、以下の VM オプションを追加してください。
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED
failed in mek provision: gcmEncrypt error
これは Oracle JDK の既知の問題です。以下のいずれかの修正を適用してください。
-
Amazon Corretto への切り替え — この問題が発生しない、ドロップインの OpenJDK ディストリビューションです。
-
Oracle JDK への BouncyCastle セキュリティプロバイダーの追加:
-
JDK のインストールディレクトリを見つけます。
-
<jdk-path>/conf/security/java.securityを開きます。 -
List of providers and their preference ordersセクションに、security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProviderを追加します。
-