すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:EncJDBC

最終更新日:Dec 12, 2024

常時機密データベース機能を使用してテーブル内の特定のデータ列のデータを暗号化し、Javaアプリケーションを使用して必要なデータベースに接続する場合は、EncJDBCを使用できます。 これにより、データベース接続が容易になり、常時機密データベース機能の使用が簡素化されます。 このトピックでは、EncJDBCを使用して常に機密のデータベースに接続する方法について説明します。

必要なマスター暗号化キー (MEK) がある場合、EncJDBCは暗号文データを自動的に復号し、平文データを返すことができます。 このプロセスはアプリケーションに対して透過的であり、アプリケーションコードをいくつか変更することで、アプリケーションを常に機密のデータベースに接続できます。 これにより、常に機密のデータベース機能の使用が簡素化されます。

前提条件

  • ApsaraDB RDS for MySQLインスタンスでは、常に機密のデータベース機能が有効になっています。 詳細については、「常に機密のデータベース機能の有効化」をご参照ください。

  • 常時機密データベース機能が有効になっているRDSインスタンスに関する接続情報が取得されます。 接続情報には、ドメイン名 (ホスト) 、ポート番号 (ポート) 、インスタンス名 (dbname) 、ユーザー名 (ユーザー名) 、パスワード (パスワード) が含まれます。

  • データ保護ルールが設定されています。 詳細については、「データ保護ルールの設定」をご参照ください。

使用上の注意

  • MEKを保存し、機密保持する必要があります。

  • JDK 1.8以降が使用されます。

    説明

    このトピックでは、Mavenのバージョンは3.9.2で、開発ツールはIntelliJ IDEA Community Edition 2022.3.2です。

手順

ステップ1: Maven依存関係の追加

Mavenのプロジェクトのpom.xmlファイルに次の依存関係を追加します。

<dependencies>
  <dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-encdb-mysql-jdbc</artifactId>
    <version>1.0.9-1</version>
  </dependency>
</dependencies> 

手順2: サンプルコードに基づくEncJDBCの設定

JDBCと同じ方法でEncJDBCを使用できます。 EncJDBCを使用する前に、データセキュリティのためにEncJDBCでMEKENC_ALGOなどの必要なパラメーターを設定する必要があります。 MEKはマスター暗号化キーを指定し、ENC_ALGOは暗号化アルゴリズムを指定する。

次の表に、パラメーターと値の例を示します。

パラメーター

例 (文字列型)

説明

MEK

00112233445566778899aabbccddeeff

データ所有者によって指定されたMEK。

MEK生成: OpenSSLやopenssl rand -hex 16などのパスワード生成ツールを使用したり、プログラミング言語でランダム関数を呼び出したり、Key Management Service (KMS) からキーを取得したりできます。

有効値: 長さが32文字の16バイトの16進文字列。

警告

MEKは、暗号化されたデータへのアクセスに使用するルート資格です。 セキュリティ上の理由から、常時機密データベース機能が有効になっているRDSインスタンスは、MEKを生成、保存、またはバックアップしません。 MEKを生成し、機密を保持する必要があります。 MEKを紛失した場合、MEKを使用して暗号化されたデータにアクセスできなくなります。 MEKをバックアップすることをお勧めします。

ENC_ALGO

SM4_128_CBC

データを保護するために使用される暗号化アルゴリズム。

有効な値:

  • 国際的に受け入れられているアルゴリズム:

    • AES_128_GCM

    • AES_128_CTR

    • AES_128_CBC

    • AES_128_ECB (非推奨)

  • SMアルゴリズム:

    • SM4_128_GCM (デフォルト)

    • SM4_128_CTR

    • SM4_128_CBC

    • SM4_128_ECB (非推奨)

説明
  • AES_128_ECBおよびSM4_128_ECB暗号化アルゴリズムは、高いセキュリティを提供できません。 AES_128_ECBおよびSM4_128_ECB暗号化アルゴリズムよりも高いセキュリティを提供する他の暗号化アルゴリズムを選択することを推奨します。

  • オプションです。 デフォルト値はSM4_128_GCMです。

MEKおよびENC_ALGOパラメーターの設定

次のセクションでは、MEKパラメーターとENC_ALGOパラメーターの設定に使用できる方法について説明します。 JDBCでパラメーターを設定するために2つ以上のメソッドを使用する場合は、JDBCプロパティの設定、設定ファイル、およびURLの設定の順序で優先されます。

説明
  • 複数のパラメーターを連結するには、アンパサンド (&) を使用できます。

  • 次の方法では、MEKはクライアント側のオンプレミスマシンで構成され、エンベロープ暗号化を使用してサーバーに配布され、MEKが漏洩しないようにします。

JDBCプロパティの設定

標準JDBCからRDSインスタンスに接続する場合、[プロパティ] 設定を構成する必要があります。 サンプルコード:

// Obtain the connection information such as the domain name (hostname), port number (port), instance name (dbname), username (username), and password (password).
// ...

String mek=...;
String encAlgo=...;

Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
props.setProperty("ENC_ALGO", encAlgo);

String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);

// ... Initiate a query. ...
構成ファイルの使用

設定ファイルを作成し、設定ファイルでMEKなどの必要なパラメーターを設定できます。 次に、プロジェクトでencJdbcConfigFileという名前のプロパティを指定し、プロパティの値を構成ファイルのディレクトリに設定できます。 ディレクトリを指定しない場合、デフォルトでencjdbc.confファイルが使用されます。

設定ファイルの内容:

MEK=
ENC_ALGO=

設定ファイルのディレクトリは、次の方法で指定できます。

  • 構成ファイルをプロジェクトのresourcesディレクトリに格納します。 image.png

  • 構成ファイルをプロジェクトのルートディレクトリに格納します。 ルートディレクトリは、実行時にアプリケーションによって使用されるディレクトリです。

ファイル設定が完了したら、アプリケーションで追加の設定を構成する必要はありません。

// Obtain the connection information such as the domain name (hostname), port number (port), instance name (dbname), username (username), and password (password).
// ...

String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... Initiate a query. ...
URLの設定

URLでMEKパラメーターとENC_ALGOパラメーターを設定できます。

// Obtain the connection information such as the domain name (hostname), port number (port), instance name (dbname), username (username), and password (password).
// ...

String mek=...;
String encAlgo=...;

String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?MEK=%s&ENC_ALGO=%s", hostname, port, dbname, mek, encAlgo);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, username, password);

// ... Initiate a query. ...

JDBCプロパティ設定の完全なサンプルコード

// Update the connection information such as the domain name (hostname), port number (port), instance 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";

String mek="00112233445566778899aabbccddeeff"; // This is an example value. We recommend that you use a more complex MEK.
String encAlgo="SM4_128_CBC";

Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
props.setProperty("ENC_ALGO", encAlgo);

String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
Connection connection = DriverManager.getConnection(dbUrl, props);

int[] intData = {1, 2, 3, 4, 5, 6};
String[] strData = {"abc", "bcd", "1", "def", "efg", "fgi"};

// create table
connection.createStatement().executeUpdate("drop table if exists test");
connection.createStatement().executeUpdate("create table test (a int, b text)");

// insert data
for (int i = 0; i < 6; i++) {
    PreparedStatement pstmt = connection.prepareStatement("insert into test values (?,?)");
    pstmt.setInt(1, intData[i]);
    pstmt.setString(2, strData[i]);
    pstmt.executeUpdate();
}

// check plaintext data
ResultSet rs = connection.createStatement().executeQuery("select * from test");
while (rs.next()) {
    for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
        System.out.print(rs.getString(i + 1));
        System.out.print("\t");
    }
    System.out.print("\n");
}

出力:

1	abc	
2	bcd	
3	cde	
4	def	
5	efg	
6	fgi	

よくある質問

  • 私は何をしますか?スレッド "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を追加する必要があります。

  • がmekの規定に失敗した場合の対処方法: mekの設定が正しくない可能性があります。 詳細: プログラムを実行するとgcmEncryptエラーメッセージが表示されますか?

    このエラーは、Oracle JDKの一般的なエラーです。 エラーを解決するには、次のいずれかの方法を使用します。

    • 代わりにAmazon Correttoを使用します。

    • Oracle JDKを使用する場合は、次の手順を実行してセキュリティプロバイダーを構成する必要があります。

      1. JDKのインストールパスを見つけます。

      2. インストールパス /conf/security/ ディレクトリで、java.securityファイルを見つけます。

      3. java.securityファイルを編集します。 [プロバイダーのリストとその優先順位 (上記参照)] セクションで、次のコンテンツを追加します。

        security.provider.14=org.bouncycastle.jce.provider.BouncyCastleProvider