本文介紹如何通過用戶端使用全密態資料庫功能。
前提條件
已開通全密態資料庫。更多資訊,請參見開通全密態資料庫。
已定義敏感性資料。具體操作,請參見定義敏感性資料。
擷取加密資料庫串連資訊。您首先需要擷取加密資料庫的串連資訊,如網域名稱(host)、連接埠(port)、資料庫執行個體名(dbname)、使用者名稱(username)、密碼(password)等。執行個體內外網地址擷取方式請參見查看或修改串連地址和連接埠。
本文中介紹的應用程式使用的開發語言為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小版本
服務端encdb外掛程式版本號碼
用戶端EncDB依賴包
20230830或以上版本
1.1.13或以上版本
Maven依賴配置。
說明本樣本以Maven構建Java專案為例。
通過如下命令將
EncJDBC
依賴包安裝至您的本地倉庫:mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<安裝的Jar包名> -Dversion=<安裝的Jar版本> -Dpackaging=jar -Dfile=<安裝的Jar包檔案名稱>
樣本:
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 does not support java 1.8 since 1.5.0 --> <version>1.4.0</version> </dependency> ... </dependencies>
通過全密態用戶端查詢(程式碼範例)
本樣本所展示的代碼僅用於示範配置方式,請勿在實際業務代碼中將password
、mek
以明文方式設定在代碼中,建議使用外部設定檔或環境變數等其他方式進行處理後,再在代碼中引用。
URL配置說明
您可以像使用任意一個JDBC一樣使用
EncJDBC
。但是您需要預先在EncJDBC
中配置和您資料安全相關的如下資訊。// 準備好網域名稱(hostname)、連接埠(port)、資料庫名稱(dbname)、使用者名稱(username)、密碼(password)等串連資訊 // 詳見資料安全相關參數 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)、資料庫名稱(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:%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 PostgreSQL小版本
服務端encdb外掛程式版本號碼
用戶端EncDB依賴包
20230830或以上版本
1.1.13或以上版本
Maven依賴配置。
說明本樣本以Maven構建Java專案為例。
通過如下命令將
EncDB SDK
依賴包安裝至您的本地倉庫:mvn install:install-file -DgroupId=com.alibaba.encdb -DartifactId=<安裝的Jar包名> -Dversion=<安裝的Jar版本> -Dpackaging=jar -Dfile=<安裝的Jar包檔案名稱>
樣本:
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),其他參數建議您使用預設預設配置。// 準備好網域名稱(hostname)、連接埠(port)、資料庫執行個體名(dbname)、使用者名稱(username)、密碼(password)等串連資訊 // 建立資料庫連接,任意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)、資料庫執行個體名(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(); // 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命令列執行SELECT * FROM example;
。
可以看到,id
、name
列是明文,price
、miles
、secret
列是密文。已被加密的資料在伺服器端無法查看,能夠有效防禦來自雲平台外部和內部的安全威脅,時刻保護使用者資料。
DMS控制台
全密態資料庫支援通過DMS等可視化互動工具直接查詢,例如DMS。
可以看到,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 option參數
--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED
將com.sun.crypto.provider匯出給Unnamed模組,以解決存取權限問題。