Azure Key Vault 範例版本 6.0.0
使用 Azure Key Vault 的範例應用程式
此應用程式可以使用 JDBC 驅動程式 6.0.0、Azure-Keyvault (0.9.7 版)、Adal4j (1.3.0 版) 與其相依性來執行。 將這些程式庫新增至專案的專案物件模型 (POM) 檔案,即可解析基礎相依性。 如需功能相依性的詳細資訊,請參閱 Microsoft JDBC Driver for SQL Server 的功能相依性 (部分機器翻譯)。
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionAzureKeyVaultProvider;
import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionKeyStoreProvider;
import com.microsoft.sqlserver.jdbc.SQLServerConnection;
import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.SQLServerKeyVaultAuthenticationCallback;
public class AKV_600 {
static String connectionUrl = "jdbc:sqlserver://localhost;integratedSecurity=true;encrypt=true;database=test;columnEncryptionSetting=enabled";
static String applicationClientID = "Your Client ID";
static String applicationKey = "Your Application Key";
static String keyID = "Your Key ID";
static String cmkName = "AKV_CMK_JDBC";
static String cekName = "AKV_CEK_JDBC";
static String akvTable = "akvTable";
static String createTableSQL = "create table " + akvTable + " ("
+ "PlainNvarcharMax nvarchar(max) null,"
+ "RandomizedNvarcharMax nvarchar(max) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = "
+ cekName + ") NULL,"
+ "DeterministicNvarcharMax nvarchar(max) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = "
+ cekName + ") NULL" + ");";
static ExecutorService service = Executors.newFixedThreadPool(2);
private static SQLServerColumnEncryptionAzureKeyVaultProvider tryAuthenticationCallback()
throws URISyntaxException, SQLServerException {
SQLServerKeyVaultAuthenticationCallback authenticationCallback = new SQLServerKeyVaultAuthenticationCallback() {
@Override
public String getAccessToken(String authority, String resource,
String scope) {
AuthenticationResult result = null;
try {
AuthenticationContext context = new AuthenticationContext(
authority, false, service);
ClientCredential cred = new ClientCredential(
applicationClientID, applicationKey);
Future<AuthenticationResult> future = context
.acquireToken(resource, cred, null);
result = future.get();
} catch (Exception e) {
e.printStackTrace();
}
return result.getAccessToken();
}
};
SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = new SQLServerColumnEncryptionAzureKeyVaultProvider(
authenticationCallback, service);
return akvProvider;
}
public static void main(String[] args)
throws ClassNotFoundException, Exception {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
try (Connection connection = DriverManager.getConnection(connectionUrl);
Statement statement = connection.createStatement()) {
statement.execute("DBCC FREEPROCCACHE");
SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = tryAuthenticationCallback();
setupKeyStoreProviders(akvProvider.getName(), akvProvider);
testAKV(akvProvider.getName(), akvProvider, connection, statement);
}
}
private static void testAKV(String CUSTOM_AKV_PROVIDER_NAME,
SQLServerColumnEncryptionKeyStoreProvider akvProvider,
Connection connection, Statement statement)
throws SQLException, SQLServerException, InterruptedException {
dropTable(statement);
dropKeys(statement);
System.out.println("createCMK");
createCMK(CUSTOM_AKV_PROVIDER_NAME, statement);
System.out.println("createCEK");
createCEK(akvProvider, statement);
System.out.println("create Table");
statement.execute(createTableSQL);
System.out.println("populate");
populateCharNormalCase(connection);
System.out.println("run the test");
testChar(statement);
}
private static void setupKeyStoreProviders(String CUSTOM_AKV_PROVIDER_NAME,
SQLServerColumnEncryptionKeyStoreProvider akvProvider)
throws SQLServerException {
Map<String, SQLServerColumnEncryptionKeyStoreProvider> map1 = new HashMap<String, SQLServerColumnEncryptionKeyStoreProvider>();
map1.put(CUSTOM_AKV_PROVIDER_NAME, akvProvider);
SQLServerConnection.registerColumnEncryptionKeyStoreProviders(map1);
}
private static void dropTable(Statement statement) throws SQLException {
statement.executeUpdate("if object_id('" + akvTable
+ "','U') is not null" + " drop table " + akvTable);
}
private static void dropKeys(Statement statement) throws SQLException {
statement.executeUpdate(
"if exists (SELECT name from sys.column_encryption_keys where name='"
+ cekName + "')" + " begin"
+ " drop column encryption key " + cekName + " end");
statement.executeUpdate(
"if exists (SELECT name from sys.column_master_keys where name='"
+ cmkName + "')" + " begin" + " drop column master key "
+ cmkName + " end");
}
private static void createCMK(String CUSTOM_AKV_PROVIDER_NAME,
Statement statement) throws SQLException {
String _createColumnMasterKeyTemplate = String.format(
"CREATE COLUMN MASTER KEY [%s] WITH ( KEY_STORE_PROVIDER_NAME = '%s', KEY_PATH = '%s');",
cmkName, CUSTOM_AKV_PROVIDER_NAME, keyID);
statement.execute(_createColumnMasterKeyTemplate);
}
private static void createCEK(
SQLServerColumnEncryptionKeyStoreProvider storeProvider,
Statement statement) throws SQLServerException, SQLException {
String letters = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] valuesDefault = letters.getBytes();
byte[] key = storeProvider.encryptColumnEncryptionKey(keyID, "RSA_OAEP",
valuesDefault);
String cekSql = "CREATE COLUMN ENCRYPTION KEY " + cekName
+ " WITH VALUES " + "(COLUMN_MASTER_KEY = " + cmkName
+ ", ALGORITHM = 'RSA_OAEP', ENCRYPTED_VALUE = 0x"
+ bytesToHexString(key, key.length) + ")" + ";";
statement.execute(cekSql);
}
final static char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
private static String bytesToHexString(byte[] b, int length) {
StringBuilder sb = new StringBuilder(length * 2);
for (int i = 0; i < length; i++) {
int hexVal = b[i] & 0xFF;
sb.append(hexChars[(hexVal & 0xF0) >> 4]);
sb.append(hexChars[(hexVal & 0x0F)]);
}
return sb.toString();
}
private static void populateCharNormalCase(Connection connection)
throws SQLException {
String sql = "insert into " + akvTable + " values(?,?,?)";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
for (int i = 1; i <= 3; i++) {
pstmt.setNString(i, "hello world");
}
pstmt.execute();
}
}
private static void testChar(Statement statement) throws SQLException {
try (ResultSet rs = statement
.executeQuery("select * from " + akvTable);) {
int numberOfColumns = rs.getMetaData().getColumnCount();
while (rs.next()) {
testGetString(rs, numberOfColumns);
}
}
}
private static void testGetString(ResultSet rs, int numberOfColumns)
throws SQLException {
for (int i = 1; i <= numberOfColumns; i = i + 3) {
String stringValue1 = "" + rs.getString(i);
String stringValue2 = "" + rs.getString(i + 1);
String stringValue3 = "" + rs.getString(i + 2);
System.out.println(stringValue1);
System.out.println(stringValue2);
System.out.println(stringValue3);
}
}
}
另請參閱
Azure Key Vault 範例 9.2 版
Azure Key Vault 範例版本 7.0
Azure Key Vault 範例版本 6.2.2