Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Berlaku untuk
- Odbc Driver 13.1+ untuk SQL Server
Pendahuluan
Artikel ini memberikan informasi tentang cara mengembangkan aplikasi ODBC dengan menggunakan Always Encrypted (Mesin Database) atau Always Encrypted dengan enklave aman serta Driver ODBC untuk SQL Server.
Always Encrypted memungkinkan aplikasi klien mengenkripsi data sensitif dan tidak pernah mengungkapkan data atau kunci enkripsi ke SQL Server atau Azure SQL Database. Driver yang diaktifkan Always Encrypted, seperti Driver ODBC untuk SQL Server, mencapai keamanan ini dengan mengenkripsi dan mendekripsi data sensitif secara transparan dalam aplikasi klien. Driver secara otomatis menentukan parameter kueri mana yang sesuai dengan kolom database sensitif (dilindungi menggunakan Always Encrypted), dan mengenkripsi nilai parameter tersebut sebelum meneruskan data ke SQL Server atau Azure SQL Database. Demikian pula, driver secara transparan mendekripsi data yang diambil dari kolom database terenkripsi dalam hasil kueri. Always Encrypted dengan enklave aman memperluas kemampuan fitur ini untuk memungkinkan fungsionalitas yang lebih kaya pada data sensitif, sembari menjaga kerahasiaan data.
Untuk informasi selengkapnya, lihat Always Encrypted (Database Engine) dan Always Encrypted with secure enclaves.
Prasyarat
Konfigurasikan Always Encrypted di database Anda. Proses ini melibatkan penyediaan kunci Always Encrypted dan menyiapkan enkripsi untuk kolom database yang dipilih. Jika Anda belum memiliki database dengan Always Encrypted yang dikonfigurasi, ikuti petunjuk dalam Tutorial: Memulai Always Encrypted. Secara khusus, database Anda harus berisi definisi metadata untuk Kunci Master Kolom (CMK), Kunci Enkripsi Kolom (CEK), dan tabel yang berisi satu atau beberapa kolom yang dienkripsi menggunakan CEK tersebut.
Jika Anda menggunakan Always Encrypted dengan enklave aman, lihat Mengembangkan aplikasi menggunakan Always Encrypted dengan enklave aman untuk prasyarat tambahan.
Mengaktifkan Always Encrypted dalam aplikasi ODBC
Cara term mudah untuk mengaktifkan enkripsi parameter dan dekripsi kolom terenkripsi resultset adalah dengan mengatur nilai ColumnEncryption kata kunci string koneksi ke Diaktifkan. Kode berikut adalah contoh string koneksi yang memungkinkan Always Encrypted:
SQLWCHAR *connString = L"Driver={ODBC Driver 18 for SQL Server};Server={myServer};Encrypt=yes;Trusted_Connection=yes;ColumnEncryption=Enabled;";
Always Encrypted juga dapat diaktifkan pada konfigurasi DSN, menggunakan kunci dan nilai yang sama (yang akan ditimpa oleh pengaturan string koneksi, jika ada), atau secara terprogram dengan atribut pra-koneksi SQL_COPT_SS_COLUMN_ENCRYPTION. Mengaturnya dengan cara ini mengambil alih nilai yang ditetapkan dalam string koneksi atau DSN:
SQLSetConnectAttr(hdbc, SQL_COPT_SS_COLUMN_ENCRYPTION, (SQLPOINTER)SQL_COLUMN_ENCRYPTION_ENABLE, 0);
Setelah diaktifkan untuk koneksi, perilaku Always Encrypted dapat disesuaikan untuk kueri individual. Untuk informasi selengkapnya, lihat Mengontrol Dampak Performa Always Encrypted di bawah ini.
Mengaktifkan Always Encrypted tidak cukup untuk enkripsi atau dekripsi agar berhasil; Anda juga perlu memastikan bahwa:
Aplikasi ini memiliki izin basis data VIEW ANY COLUMN MASTER KEY DEFINITION dan VIEW ANY COLUMN ENCRYPTION KEY DEFINITION, yang diperlukan untuk mengakses metadata tentang kunci Always Encrypted di basis data. Untuk detail selengkapnya, lihat Izin Database.
Aplikasi dapat mengakses CMK yang melindungi CEK untuk kolom terenkripsi yang dikueri. Perilaku ini tergantung pada penyedia keystore yang menyimpan CMK. Untuk informasi selengkapnya, lihat Bekerja dengan Penyimpanan Kunci Master Kolom.
Mengaktifkan Always Encrypted dengan enklave aman
Catatan
Pada Linux dan macOS, OpenSSL versi 1.0.1 atau yang lebih baru diperlukan untuk menggunakan Always Encrypted dengan enklave aman.
Mulai versi 17.4, driver mendukung Always Encrypted dengan enklave aman. Untuk mengaktifkan penggunaan enklave saat menyambungkan ke database, atur ColumnEncryption kunci DSN, kata kunci string koneksi, atau atribut koneksi ke nilai berikut: <attestation protocol>,<attestation URL>, di mana:
<attestation protocol>- menentukan protokol yang digunakan untuk pengesahan enklave.- Jika Anda menggunakan SQL Server dan Host Guardian Service (HGS), maka
<attestation protocol>harusVBS-HGS. - Jika Anda menggunakan Azure SQL Database dan Microsoft Azure Attestation,
<attestation protocol>harusSGX-AAS. - Jika Anda tidak memerlukan pengesahan,
<attestation-protocol>harusVBS-NONE. (Versi 18.1+)
- Jika Anda menggunakan SQL Server dan Host Guardian Service (HGS), maka
<attestation URL>- menentukan URL pengesahan (titik akhir layanan pengesahan). Anda perlu mendapatkan URL pengesahan untuk lingkungan Anda dari administrator layanan pengesahan Anda.- Jika Anda menggunakan SQL Server dan Host Guardian Service (HGS), lihat Menentukan dan membagikan URL pengesahan HGS.
- Jika Anda menggunakan Azure SQL Database dan Microsoft Azure Attestation, lihat Menentukan URL pengesahan untuk kebijakan pengesahan Anda.
- Jika Anda tidak memerlukan pengesahan, jangan tentukan URL pengesahan (atau koma sebelumnya). (Versi 18.1+)
Contoh string koneksi yang mengaktifkan komputasi enklave untuk koneksi database:
SQL Server:
"Driver=ODBC Driver 18 for SQL Server;Server=myServer.myDomain;Encrypt=yes;Database=myDataBase;Trusted_Connection=Yes;ColumnEncryption=VBS-HGS,http://myHGSServer.myDomain/Attestation"Azure SQL Database:
"Driver=ODBC Driver 18 for SQL Server;Server=myServer.database.windows.net;Database=myDataBase;Uid=myUsername;Pwd=<password>;Encrypt=yes;ColumnEncryption=SGX-AAS,https://myAttestationProvider.uks.attest.azure.net/"Tidak ada pengesahan (v18.1+):
"Driver=ODBC Driver 18 for SQL Server;Server=myServer.database.windows.net;Database=myDataBase;Uid=myUsername;Pwd=<password>;Encrypt=yes;ColumnEncryption=VBS-NONE"
Jika server dan layanan pengesahan dikonfigurasi dengan benar, bersama CMK dan CEK yang mendukung enklave untuk kolom yang dienkripsi, Anda dapat menjalankan kueri yang menggunakan enklave, seperti enkripsi langsung di tempat dan komputasi tingkat lanjut, selain fungsionalitas yang sudah disediakan oleh Always Encrypted. Untuk informasi selengkapnya, lihat Mengonfigurasi Always Encrypted dengan enklave aman.
Mengambil dan memodifikasi data dalam kolom terenkripsi
Setelah mengaktifkan Always Encrypted pada koneksi, Anda dapat menggunakan API ODBC standar. API ODBC dapat mengambil atau memodifikasi data dalam kolom database terenkripsi. Item dokumentasi berikut mungkin berguna:
Aplikasi Anda harus memiliki izin database yang diperlukan, dan harus dapat mengakses kunci master kolom. Kemudian driver mengenkripsi parameter kueri apa pun yang menargetkan kolom terenkripsi. Driver juga mendekripsi data yang diambil dari kolom terenkripsi. Driver melakukan semua enkripsi dan dekripsi ini tanpa bantuan dari kode sumber Anda. Bagi program Anda, seolah-olah kolom-kolom tersebut tidak dienkripsi.
Jika Always Encrypted tidak diaktifkan, kueri dengan parameter yang menargetkan kolom terenkripsi akan gagal. Data masih dapat diambil dari kolom terenkripsi, selama kueri tidak memiliki parameter yang menargetkan kolom terenkripsi. Namun, driver tidak akan mencoba dekripsi apa pun dan aplikasi akan menerima data terenkripsi biner (sebagai array byte).
Tabel di bawah ini meringkas perilaku kueri, tergantung pada apakah Always Encrypted diaktifkan atau tidak:
| Karakteristik kueri | Always Encrypted diaktifkan dan aplikasi dapat mengakses kunci dan metadata kunci | Always Encrypted diaktifkan dan aplikasi tidak dapat mengakses kunci atau metadata kunci | Always Encrypted dinonaktifkan |
|---|---|---|---|
| Parameter yang menargetkan kolom terenkripsi. | Nilai parameter dienkripsi secara transparan. | Kesalahan | Kesalahan |
| Mengambil data dari kolom terenkripsi, tanpa parameter yang menargetkan kolom terenkripsi. | Hasil dari kolom terenkripsi didekripsi secara transparan. Aplikasi menerima nilai kolom teks biasa. | Kesalahan | Hasil dari kolom terenkripsi tidak didekripsi. Aplikasi menerima nilai terenkripsi dalam bentuk larik byte. |
Contoh berikut mengilustrasikan pengambilan dan modifikasi data dalam kolom terenkripsi. Contoh mengasumsikan tabel dengan skema berikut. Kolom SSN dan BirthDate dienkripsi.
CREATE TABLE [dbo].[Patients](
[PatientId] [int] IDENTITY(1,1),
[SSN] [char](11) COLLATE Latin1_General_BIN2
ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
COLUMN_ENCRYPTION_KEY = CEK1) NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[BirthDate] [date]
ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256',
COLUMN_ENCRYPTION_KEY = CEK1) NOT NULL
PRIMARY KEY CLUSTERED ([PatientId] ASC) ON [PRIMARY] )
GO
Contoh penyisipan data
Contoh ini menyisipkan baris ke dalam tabel Patients. Perhatikan detail berikut:
Tidak ada yang khusus untuk enkripsi dalam kode sampel. Driver secara otomatis mendeteksi dan mengenkripsi nilai parameter SSN dan tanggal, yang menargetkan kolom terenkripsi. Perilaku ini membuat enkripsi transparan ke aplikasi.
Nilai yang disisipkan ke dalam kolom database, termasuk kolom terenkripsi, diteruskan sebagai parameter terikat (lihat Fungsi SQLBindParameter). Meskipun penggunaan parameter bersifat opsional saat mengirim nilai ke kolom yang tidak dienkripsi (meskipun sangat disarankan karena membantu mencegah injeksi SQL), parameter wajib digunakan untuk nilai yang ditujukan ke kolom terenkripsi. Jika nilai yang dimasukkan ke dalam kolom SSN atau BirthDate dikirimkan sebagai nilai literal yang disisipkan langsung dalam pernyataan kueri, kueri akan gagal karena driver tidak mencoba mengenkripsi atau memproses nilai literal dalam kueri. Akibatnya, server akan menolaknya sebagai tidak kompatibel dengan kolom terenkripsi.
Tipe SQL dari parameter yang disisipkan ke kolom SSN diatur ke SQL_CHAR, yang dipetakan ke tipe data SQL Server char (
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 11, 0, (SQLPOINTER)SSN, 0, &cbSSN);). Jika jenis parameter diatur ke SQL_WCHAR, yang memetakan ke nchar, kueri akan gagal, karena Always Encrypted tidak mendukung konversi sisi server dari nilai nchar terenkripsi ke nilai karakter terenkripsi. Lihat Referensi Pemrogram ODBC -- Lampiran D: Tipe Data untuk informasi mengenai pemetaan tipe data.
SQL_DATE_STRUCT date;
SQLLEN cbdate; // size of date structure
SQLCHAR SSN[12];
strcpy_s((char*)SSN, _countof(SSN), "795-73-9838");
SQLWCHAR* firstName = L"Catherine";
SQLWCHAR* lastName = L"Abel";
SQLINTEGER cbSSN = SQL_NTS, cbFirstName = SQL_NTS, cbLastName = SQL_NTS;
// Initialize the date structure
date.day = 10;
date.month = 9;
date.year = 1996;
// Size of structures
cbdate = sizeof(SQL_DATE_STRUCT);
SQLRETURN rc = 0;
string queryText = "INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (?, ?, ?, ?) ";
rc = SQLPrepare(hstmt, (SQLCHAR *)queryText.c_str(), SQL_NTS);
//SSN
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 11, 0, (SQLPOINTER)SSN, 0, &cbSSN);
//FirstName
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 50, 0, (SQLPOINTER)firstName, 0, &cbFirstName);
//LastName
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 50, 0, (SQLPOINTER)lastName, 0, &cbLastName);
//BirthDate
rc = SQLBindParameter(hstmt, 4, SQL_PARAM_INPUT, SQL_C_TYPE_DATE, SQL_TYPE_DATE, 10, 0, (SQLPOINTER)&date, 0, &cbdate);
rc = SQLExecute(hstmt);
Contoh pengambilan data teks biasa
Contoh berikut menunjukkan pemfilteran data berdasarkan nilai terenkripsi, dan mengambil data teks biasa dari kolom terenkripsi. Perhatikan detail berikut:
Nilai yang digunakan dalam klausul WHERE untuk memfilter pada kolom SSN perlu diteruskan menggunakan SQLBindParameter, sehingga driver dapat mengenkripsinya secara transparan sebelum mengirimkannya ke server.
Semua nilai yang dicetak oleh program akan berada dalam teks biasa, karena driver akan secara transparan mendekripsi data yang diambil dari kolom SSN dan BirthDate.
Catatan
Kueri dapat melakukan perbandingan kesetaraan pada kolom terenkripsi hanya jika enkripsi deterministik, atau jika enklave aman diaktifkan.
SQLCHAR SSN[12];
strcpy_s((char*)SSN, _countof(SSN), "795-73-9838");
SQLWCHAR* firstName = L"Catherine";
SQLWCHAR* lastName = L"Abel";
SQLINTEGER cbSSN = SQL_NTS, cbFirstName = SQL_NTS, cbLastName = SQL_NTS;
SQLRETURN rc = 0;
string empty = "";
string queryText = "SELECT [SSN], [FirstName], [LastName], [BirthDate] " + empty +
"FROM [dbo].[Patients]" +
"WHERE " +
"[SSN] = ? ";
rc = SQLPrepare(hstmt, (SQLCHAR *)queryText.c_str(), SQL_NTS);
//SSN
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 11, 0, (SQLPOINTER)SSN, 0, &cbSSN);
rc = SQLExecute(hstmt);
HandleDiagnosticRecord(hstmt, SQL_HANDLE_STMT, rc);
SQL_DATE_STRUCT dateVal;
SQLWCHAR firstNameVal[50];
SQLWCHAR lastNameVal[50];
SQLCHAR SSNVal[12];
SQLLEN cbdate; // size of date structure
int rowcount = 0;
while (SQL_SUCCEEDED(SQLFetch(hstmt)))
{
rowcount++;
SQLGetData(hstmt, 1, SQL_C_CHAR, &SSNVal, 11, &cbSSN);
SQLGetData(hstmt, 2, SQL_C_WCHAR, &firstNameVal, 50, &cbFirstName);
SQLGetData(hstmt, 3, SQL_C_WCHAR, &lastNameVal, 50, &cbLastName);
SQLGetData(hstmt, 4, SQL_C_TYPE_DATE, &dateVal, 10, &cbdate);
}
Contoh pengambilan data Ciphertext
Jika Always Encrypted tidak diaktifkan, kueri masih dapat mengambil data dari kolom terenkripsi, selama kueri tidak memiliki parameter yang menargetkan kolom terenkripsi.
Contoh berikut mengilustrasikan pengambilan data terenkripsi biner dari kolom terenkripsi. Perhatikan detail berikut:
- Karena Always Encrypted tidak diaktifkan dalam string koneksi, kueri akan mengembalikan nilai terenkripsi SSN dan BirthDate sebagai array byte (program mengonversi nilai menjadi string).
- Kueri yang mengambil data dari kolom terenkripsi dengan Always Encrypted dinonaktifkan dapat memiliki parameter, selama tidak ada parameter yang menargetkan kolom terenkripsi. Kueri di atas memfilter berdasarkan LastName, yang tidak dienkripsi di dalam basis data. Jika kueri difilter oleh SSN atau BirthDate, kueri akan gagal.
SQLCHAR SSN[12];
strcpy_s((char*)SSN, _countof(SSN), "795-73-9838");
SQLWCHAR* firstName = L"Catherine";
SQLWCHAR* lastName = L"Abel";
SQLINTEGER cbSSN = SQL_NTS, cbFirstName = SQL_NTS, cbLastName = SQL_NTS;
SQLRETURN rc = 0;
string empty = "";
string queryText = "SELECT [SSN], [FirstName], [LastName], [BirthDate] " + empty +
"FROM [dbo].[Patients]" +
"WHERE " +
"[LastName] = ?";
rc = SQLPrepare(hstmt, (SQLCHAR *)queryText.c_str(), SQL_NTS);
//LastName
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_WCHAR, SQL_WCHAR, 50, 0, (SQLPOINTER)lastName, 0, &cbLastName);
rc = SQLExecute(hstmt);
HandleDiagnosticRecord(hstmt, SQL_HANDLE_STMT, rc);
SQL_DATE_STRUCT dateVal;
SQLWCHAR firstNameVal[50];
SQLWCHAR lastNameVal[50];
SQLCHAR SSNVal[12];
SQLLEN cbdate; // size of date structure
int rowcount = 0;
while (SQL_SUCCEEDED(SQLFetch(hstmt)))
{
rowcount++;
SQLGetData(hstmt, 1, SQL_C_CHAR, &SSNVal, 11, &cbSSN);
SQLGetData(hstmt, 2, SQL_C_WCHAR, &firstNameVal, 50, &cbFirstName);
SQLGetData(hstmt, 3, SQL_C_WCHAR, &lastNameVal, 50, &cbLastName);
SQLGetData(hstmt, 4, SQL_C_TYPE_DATE, &dateVal, 10, &cbdate);
}
Enkripsi Uang/SmallMoney
Mulai versi driver 17.7, Always Encrypted dapat digunakan dengan MONEY dan SMALLMONEY. Namun ada beberapa langkah tambahan yang harus diambil. Saat menyisipkan ke dalam kolom MONEY atau SMALLMONEY terenkripsi, gunakan salah satu jenis C berikut:
SQL_C_CHAR
SQL_C_WCHAR
SQL_C_SHORT
SQL_C_LONG
SQL_C_FLOAT
SQL_C_DOUBLE
SQL_C_BIT
SQL_C_TINYINT
SQL_C_SBIGINT
SQL_C_NUMERIC
dan jenis SQL berupa SQL_NUMERIC atau SQL_DOUBLE (presisi dapat hilang saat menggunakan jenis ini).
Mengikat variabel
Setiap kali mengikat variabel MONEY/SMALLMONEY di kolom terenkripsi, bidang deskriptor berikut harus diatur:
// n is the descriptor record of the MONEY/SMALLMONEY parameter
// the type is assumed to be SMALLMONEY if isSmallMoney is true and MONEY otherwise
SQLHANDLE ipd = 0;
SQLGetStmtAttr(hStmt, SQL_ATTR_IMP_PARAM_DESC, (SQLPOINTER)&ipd, SQL_IS_POINTER, NULL);
SQLSetDescField(ipd, n, SQL_CA_SS_SERVER_TYPE, isSmallMoney ? (SQLPOINTER)SQL_SS_TYPE_SMALLMONEY :
(SQLPOINTER)SQL_SS_TYPE_MONEY, SQL_IS_INTEGER);
// If the variable is bound as SQL_NUMERIC, additional descriptor fields have to be set
// var is SQL_NUMERIC_STRUCT containing the value to be inserted
SQLHDESC hdesc = NULL;
SQLGetStmtAttr(hStmt, SQL_ATTR_APP_PARAM_DESC, &hdesc, 0, NULL);
SQLSetDescField(hdesc, n, SQL_DESC_PRECISION, (SQLPOINTER)(var.precision), 0);
SQLSetDescField(hdesc, n, SQL_DESC_SCALE, (SQLPOINTER)(var.scale), 0);
SQLSetDescField(hdesc, n, SQL_DESC_DATA_PTR, &var, 0);
Menghindari masalah umum saat mengkueri kolom terenkripsi
Bagian ini menjelaskan kategori kesalahan umum saat mengkueri kolom terenkripsi dari aplikasi ODBC dan beberapa panduan tentang cara menghindarinya.
Kesalahan konversi jenis data yang tidak didukung
Always Encrypted mendukung beberapa konversi untuk jenis data terenkripsi. Lihat Always Encrypted (Mesin Database) untuk daftar terperinci konversi jenis yang didukung. Untuk menghindari kesalahan konversi jenis data, pastikan Anda mengamati poin berikut saat menggunakan SQLBindParameter dengan parameter yang menargetkan kolom terenkripsi:
Jenis parameter SQL sama persis dengan jenis kolom yang ditargetkan, atau konversi dari jenis SQL ke jenis kolom didukung.
Presisi dan skala parameter yang menargetkan kolom dengan tipe data SQL Server
decimaldannumericsama dengan presisi dan skala yang dikonfigurasi untuk kolom target.Presisi parameter yang menargetkan kolom dengan tipe data SQL Server
datetime2,datetimeoffset, atautimetidak boleh lebih besar daripada presisi kolom target, pada kueri yang memodifikasi kolom target.
Kesalahan karena meneruskan teks biasa alih-alih nilai terenkripsi
Nilai apa pun yang menargetkan kolom terenkripsi perlu dienkripsi sebelum dikirim ke server. Upaya untuk menyisipkan, memodifikasi, atau memfilter berdasarkan nilai teks biasa pada kolom terenkripsi akan mengakibatkan kesalahan. Untuk mencegah kesalahan tersebut, pastikan bahwa:
Always Encrypted diaktifkan (di DSN, string koneksi, sebelum membuat koneksi dengan menetapkan atribut koneksi
SQL_COPT_SS_COLUMN_ENCRYPTIONuntuk koneksi tertentu, atau atribut statementSQL_SOPT_SS_COLUMN_ENCRYPTIONuntuk statement tertentu).Anda menggunakan SQLBindParameter untuk mengirim data yang menargetkan kolom terenkripsi. Contoh di bawah ini menunjukkan kueri yang secara keliru memfilter berdasarkan literal/konstanta pada kolom terenkripsi (SSN), alih-alih memberikan literal tersebut sebagai argumen ke SQLBindParameter.
string queryText = "SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN='795-73-9838'";
Tindakan pencegahan saat menggunakan SQLSetPos dan SQLMoreResults
SQLSetPos
SQLSetPos API memungkinkan aplikasi memperbarui baris dalam kumpulan hasil menggunakan buffer yang dikaitkan dengan SQLBindCol dan yang sebelumnya telah diisi dengan data baris yang diambil. Karena perilaku padding asimetris pada tipe panjang tetap yang terenkripsi, data pada kolom-kolom ini dapat berubah tanpa diduga ketika memperbarui kolom lain dalam baris yang sama. Dengan AE, nilai karakter dengan panjang tetap akan diisi dengan karakter pengisi jika nilainya lebih kecil daripada ukuran buffer.
Untuk memitigasi perilaku ini, gunakan flag SQL_COLUMN_IGNORE untuk mengabaikan kolom yang tidak akan diperbarui sebagai bagian dari SQLBulkOperations serta saat menggunakan SQLSetPos untuk pembaruan berbasis kursor. Semua kolom yang tidak dimodifikasi langsung oleh aplikasi harus diabaikan, baik untuk performa maupun untuk menghindari pemotongan kolom yang terikat ke buffer yang lebih kecil dari ukuran sebenarnya (DB). Untuk informasi selengkapnya, lihat Referensi Fungsi SQLSetPos.
SQLMoreResults & SQLDescribeCol
Program aplikasi dapat memanggil SQLDescribeCol untuk mengembalikan metadata tentang kolom dalam pernyataan yang disiapkan. Saat Always Encrypted diaktifkan, panggilan SQLMoreResultssebelum memanggil SQLDescribeCol menyebabkan sp_describe_first_result_set dipanggil, yang tidak mengembalikan metadata teks biasa dengan benar untuk kolom terenkripsi. Untuk menghindari masalah ini, panggil SQLDescribeCol pada statemen yang disiapkan sebelum memanggil SQLMoreResults.
Mengontrol dampak performa Always Encrypted
Karena Always Encrypted adalah teknologi enkripsi sisi klien, sebagian besar overhead performa diamati di sisi klien, bukan dalam database. Terlepas dari biaya operasi enkripsi dan dekripsi, sumber kinerja overhead lainnya di sisi klien adalah:
Perjalanan pulang pergi ekstra ke database untuk mengambil metadata untuk parameter kueri.
Panggilan ke penyimpanan kunci utama kolom untuk mengakses kunci utama kolom.
Bagian ini menjelaskan pengoptimalan performa bawaan di Driver ODBC untuk SQL Server dan bagaimana Anda dapat mengontrol dampak dari dua faktor di atas pada performa.
Mengontrol perjalanan pulang pergi untuk mengambil metadata untuk parameter kueri
Jika Always Encrypted diaktifkan untuk koneksi, driver akan, secara default, memanggil sys.sp_describe_parameter_encryption untuk setiap kueri berparameter, meneruskan pernyataan kueri (tanpa nilai parameter apa pun) ke SQL Server. Prosedur tersimpan ini menganalisis pernyataan kueri untuk mengetahui apakah ada parameter yang perlu dienkripsi, dan jika demikian, mengembalikan informasi terkait enkripsi untuk setiap parameter untuk memungkinkan driver mengenkripsinya. Perilaku di atas memastikan tingkat transparansi yang tinggi terhadap aplikasi klien: Aplikasi (dan pengembang aplikasi) tidak perlu mengetahui kueri mana yang mengakses kolom terenkripsi, selama nilai yang menargetkan kolom terenkripsi diteruskan ke driver dalam parameter.
Mulai versi 17.6, driver juga menyimpan metadata enkripsi untuk pernyataan yang disiapkan, meningkatkan performa dengan memungkinkan panggilan SQLExecute di masa mendatang untuk tidak memerlukan perjalanan pulang pergi tambahan untuk mengambil metadata enkripsi.
Perilaku Always Encrypted untuk setiap pernyataan
Untuk mengontrol dampak performa pengambilan metadata enkripsi untuk kueri berparameter, Anda dapat mengubah perilaku Always Encrypted untuk kueri individual jika telah diaktifkan pada koneksi. Dengan cara ini, Anda dapat memastikan bahwa sys.sp_describe_parameter_encryption hanya dipanggil untuk kueri yang Anda ketahui memiliki parameter yang menargetkan kolom terenkripsi. Namun, perhatikan bahwa dengan melakukannya, Anda mengurangi transparansi enkripsi: jika Anda mengenkripsi lebih banyak kolom dalam database, Anda mungkin perlu mengubah kode aplikasi Anda untuk menyelaraskannya dengan perubahan skema.
Untuk mengontrol perilaku pernyataan Always Encrypted, panggil SQLSetStmtAttr untuk mengatur SQL_SOPT_SS_COLUMN_ENCRYPTION atribut pernyataan ke salah satu nilai berikut:
| Nilai | Deskripsi |
|---|---|
SQL_CE_DISABLED (0) |
Always Encrypted dinonaktifkan untuk pernyataan |
SQL_CE_RESULTSETONLY (1) |
Dekripsi saja. Tataan hasil dan nilai pengembalian didekripsi, dan parameter tidak dienkripsi |
SQL_CE_ENABLED (3) |
Always Encrypted diaktifkan dan digunakan untuk parameter dan hasil |
Handel pernyataan baru yang dibuat dari koneksi dengan Always Encrypted yang diaktifkan secara default diatur ke SQL_CE_ENABLED. Handel yang dibuat dari koneksi dengan fitur tersebut dinonaktifkan secara default menjadi SQL_CE_DISABLED (dan Always Encrypted tidak dapat diaktifkan pada handel tersebut.)
Jika sebagian besar kueri dari aplikasi klien mengakses kolom terenkripsi, hal-hal berikut disarankan:
Atur
ColumnEncryptionkata kunci string koneksi keEnabled.Atur atribut ke
SQL_SOPT_SS_COLUMN_ENCRYPTIONSQL_CE_DISABLEDpada pernyataan yang tidak mengakses kolom terenkripsi apa pun. Pengaturan ini akan menonaktifkan panggilansys.sp_describe_parameter_encryptiondan upaya untuk mendekripsi nilai apa pun dalam tataan hasil.Atur atribut ke
SQL_SOPT_SS_COLUMN_ENCRYPTIONSQL_CE_RESULTSETONLYpada pernyataan yang tidak memiliki parameter apa pun yang memerlukan enkripsi, tetapi ambil data dari kolom terenkripsi. Pengaturan ini akan menonaktifkan panggilansys.sp_describe_parameter_encryptiondan enkripsi parameter. Hasil yang berisi kolom terenkripsi akan terus didekripsi.Gunakan prepared statement untuk kueri yang akan dijalankan lebih dari sekali; siapkan kueri dengan
SQLPreparedan simpan handle statement-nya, lalu gunakan kembali denganSQLExecutesetiap kali kueri tersebut dijalankan. Metode ini adalah pendekatan yang disukai untuk performa bahkan ketika tidak ada kolom terenkripsi, dan memungkinkan driver untuk memanfaatkan metadata yang di-cache.
Pengaturan keamanan Always Encrypted
Terapkan enkripsi kolom
Untuk menerapkan enkripsi parameter, atur SQL_CA_SS_FORCE_ENCRYPT bidang deskriptor parameter implementasi (IPD) melalui panggilan ke fungsi SQLSetDescField. Nilai bukan nol menyebabkan driver mengembalikan kesalahan ketika tidak ada metadata enkripsi yang dikembalikan untuk parameter terkait.
SQLHDESC ipd;
SQLGetStmtAttr(hStmt, SQL_ATTR_IMP_PARAM_DESC, &ipd, 0, 0);
SQLSetDescField(ipd, paramNum, SQL_CA_SS_FORCE_ENCRYPT, (SQLPOINTER)TRUE, SQL_IS_SMALLINT);
Jika SQL Server memberi tahu driver bahwa parameter tidak perlu dienkripsi, kueri yang menggunakan parameter tersebut akan gagal. Perilaku ini memberikan perlindungan ekstra terhadap serangan keamanan yang melibatkan SQL Server yang disusupi yang menyediakan metadata enkripsi yang salah kepada klien, yang dapat menyebabkan pengungkapan data.
Cache kunci enkripsi kolom
Untuk mengurangi jumlah panggilan ke penyimpanan kunci utama kolom untuk mendekripsikan kunci enkripsi kolom, driver menyimpan CEK dalam bentuk teks biasa di memori. Cache CEK bersifat global untuk driver dan tidak terkait dengan satu koneksi. Setelah menerima ECEK dari metadata database, driver pertama-tama mencoba menemukan CEK teks biasa yang sesuai dengan nilai kunci terenkripsi dalam cache. Driver memanggil penyimpanan kunci yang berisi CMK hanya jika tidak dapat menemukan CEK teks biasa yang sesuai di cache.
Catatan
Di Driver ODBC untuk SQL Server, entri dalam cache dikeluarkan setelah batas waktu dua jam. Perilaku ini berarti bahwa untuk ECEK tertentu, driver menghubungi penyimpanan kunci hanya sekali selama masa pakai aplikasi atau setiap dua jam, mana yang kurang.
Dimulai dengan Driver ODBC 17.1 untuk SQL Server, batas waktu cache CEK dapat disesuaikan menggunakan SQL_COPT_SS_CEKCACHETTL atribut koneksi, yang menentukan jumlah detik CEK akan tetap berada di cache. Karena sifat global cache, atribut ini dapat disesuaikan dari handel koneksi apa pun yang valid untuk driver. Ketika TTL cache diturunkan, CEK yang ada yang akan melebihi TTL baru juga dikeluarkan. Jika nilainya 0, tidak ada CEK yang disimpan dalam cache.
Jalur kunci tepercaya
Mulai dari Driver ODBC 17.1 untuk SQL Server, atribut koneksi SQL_COPT_SS_TRUSTEDCMKPATHS memungkinkan aplikasi mewajibkan agar operasi Always Encrypted hanya menggunakan daftar CMK tertentu, yang diidentifikasi berdasarkan jalur kuncinya. Secara default, atribut ini adalah NULL, yang berarti bahwa driver menerima jalur kunci apa pun. Untuk menggunakan fitur ini, atur SQL_COPT_SS_TRUSTEDCMKPATHS agar menunjuk ke string karakter lebar yang dipisahkan oleh null dan diakhiri dengan null, yang mencantumkan satu atau beberapa jalur kunci yang diizinkan. Memori yang ditunjuk oleh atribut ini harus tetap valid selama operasi enkripsi atau dekripsi menggunakan handle koneksi yang padanya atribut ini ditetapkan --- setelah itu driver akan memeriksa apakah jalur CMK sebagaimana ditentukan oleh metadata server ada dalam daftar ini tanpa membedakan huruf besar/kecil. Jika jalur CMK tidak ada dalam daftar, operasi gagal. Aplikasi dapat mengubah konten memori tempat atribut ini menunjuk, untuk mengubah daftar CMK tepercayanya, tanpa mengatur atribut lagi.
Bekerja dengan penyimpanan kunci utama kolom
Untuk mengenkripsi atau mendekripsi data, driver perlu memperoleh CEK yang dikonfigurasi untuk kolom target. CEK disimpan dalam bentuk terenkripsi (ECEK) dalam metadata database. Setiap CEK memiliki CMK yang sesuai yang digunakan untuk mengenkripsinya. metadata database tidak menyimpan CMK itu sendiri; metadata database hanya berisi nama keystore dan informasi yang dapat digunakan oleh keystore untuk menemukan CMK.
Untuk mendapatkan nilai teks biasa dari ECEK, driver terlebih dahulu mendapatkan metadata tentang CEK dan CMK yang sesuai, lalu menggunakan informasi ini untuk menghubungi keystore yang berisi CMK dan memintanya untuk mendekripsi ECEK. Driver tersebut berkomunikasi dengan keystore melalui penyedia keystore.
Penyedia keystore bawaan
Driver ODBC untuk SQL Server dilengkapi dengan penyedia keystore bawaan berikut:
| Nama | Deskripsi | Nama penyedia (metadata) | Ketersediaan |
|---|---|---|---|
| Azure Key Vault | Menyimpan CMK di Azure Key Vault | AZURE_KEY_VAULT |
Windows, macOS, Linux |
| Penyimpanan Sertifikat Windows | Menyimpan CMK secara lokal di keystore Windows | MSSQL_CERTIFICATE_STORE |
Windows |
Anda (atau DBA Anda) perlu memastikan bahwa nama penyedia, yang dikonfigurasi dalam metadata kunci master kolom, sudah benar dan jalur kunci master kolom mematuhi format jalur kunci untuk penyedia tertentu. Disarankan agar Anda mengonfigurasi kunci menggunakan alat seperti SQL Server Management Studio, yang secara otomatis menghasilkan nama penyedia dan jalur kunci yang valid saat mengeluarkan CREATE COLUMN MASTER KEY pernyataan (Transact-SQL).
Pastikan aplikasi Anda dapat mengakses kunci di keystore. Proses ini mungkin melibatkan pemberian akses aplikasi Anda ke kunci dan/atau keystore, tergantung pada keystore, atau melakukan langkah-langkah konfigurasi khusus keystore lainnya. Misalnya, untuk mengakses Azure Key Vault, Anda harus memberikan kredensial yang benar ke keystore.
Menggunakan penyedia Azure Key Vault
Azure Key Vault (AKV) adalah opsi mudah untuk menyimpan dan mengelola kunci master kolom untuk Always Encrypted (terutama jika aplikasi Anda dihosting di Azure). Driver ODBC untuk SQL Server di Linux, macOS, dan Windows menyertakan penyedia penyimpanan kunci master kolom bawaan untuk Azure Key Vault. Untuk informasi selengkapnya tentang mengonfigurasi Azure Key Vault untuk Always Encrypted, lihat Azure Key Vault - Langkah demi Langkah, Memulai Key Vault, dan Membuat Kunci Master Kolom di Azure Key Vault.
Catatan
Driver ODBC hanya mendukung autentikasi AKV secara langsung terhadap ID Microsoft Entra (sebelumnya Azure Active Directory). Jika Anda menggunakan autentikasi Microsoft Entra ke AKV dan konfigurasi Anda memerlukan autentikasi terhadap titik akhir Layanan Federasi Direktori Aktif, autentikasi mungkin gagal.
Di Linux dan macOS, untuk driver versi 17.2 dan yang lebih baru, libcurl diperlukan untuk menggunakan penyedia ini, tetapi bukan dependensi eksplisit karena operasi lain dengan driver tidak memerlukannya. Jika Anda mengalami kesalahan mengenai libcurl, pastikan itu diinstal.
Driver mendukung autentikasi ke Azure Key Vault menggunakan jenis kredensial berikut:
Nama Pengguna/Kata Sandi - dengan metode ini, kredensial adalah nama pengguna Microsoft Entra dan kata sandinya.
ID Klien/Rahasia - dengan metode ini, kredensial adalah ID klien aplikasi dan rahasia aplikasi.
Identitas Terkelola (17.5.2+) - baik yang ditetapkan sistem maupun yang ditetapkan pengguna; untuk informasi selengkapnya, lihat Identitas Terkelola untuk sumber daya Azure.
Azure Key Vault Interactive (driver Windows 17.7+) - dengan metode ini, kredensial diautentikasi melalui Microsoft Entra ID dengan ID masuk.
Untuk mengizinkan driver menggunakan CMK yang disimpan di AKV untuk enkripsi kolom, gunakan kata kunci khusus string koneksi berikut:
| Jenis Kredensial | KeyStoreAuthentication |
KeyStorePrincipalId |
KeyStoreSecret |
|---|---|---|---|
| Nama pengguna/kata sandi | KeyVaultPassword |
Nama Utama Pengguna | Kata sandi |
| ID/rahasia klien | KeyVaultClientSecret |
ID klien | Rahasia |
| Identitas Terkelola | KeyVaultManagedIdentity |
ID Objek (opsional, hanya untuk pengguna yang ditetapkan) | (tidak ditentukan) |
| Interaktif AKV | KeyVaultInteractive |
(tidak diatur) | (tidak diatur) |
Mulai dari v17.8, KeystoreAuthentication dan KeystorePrincipalId dapat diedit menggunakan UI konfigurasi DSN di Administrator Sumber Data ODBC.
Contoh rangkaian koneksi
String koneksi berikut menunjukkan cara mengautentikasi ke Azure Key Vault dengan dua jenis kredensial:
ClientID/Secret
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultClientSecret;KeyStorePrincipalId=<clientId>;KeyStoreSecret=<secret>"
Nama Pengguna/Kata Sandi
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultPassword;KeyStorePrincipalId=<username>;KeyStoreSecret=<password>"
Identitas Terkelola (yang ditetapkan sistem)
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultManagedIdentity"
Identitas Terkelola (ditetapkan pengguna)
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultManagedIdentity;KeyStorePrincipalId=<objectID>"
Interaktif AKV
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultInteractive;UID=<userID>;PWD=<password>"
Tidak ada perubahan aplikasi ODBC lainnya yang diperlukan untuk menggunakan AKV untuk penyimpanan CMK.
Catatan
Driver berisi daftar endpoint AKV yang dipercaya. Mulai dari driver versi 17.5.2, daftar ini dapat dikonfigurasi: atur properti AKVTrustedEndpoints pada kunci registri ODBCINST.INI atau ODBC.INI milik driver atau DSN (Windows), atau pada bagian file odbcinst.ini atau odbc.ini (Linux/macOS), menjadi daftar yang dipisahkan dengan titik koma. Mengaturnya di DSN lebih diutamakan daripada pengaturan di driver. Jika nilai dimulai dengan titik koma, nilai akan memperluas daftar default; jika tidak, itu menggantikan daftar default. Daftar bawaan (pada versi 17.5) adalah vault.azure.net;vault.azure.cn;vault.usgovcloudapi.net;vault.microsoftazure.de. Mulai versi 17.7, daftar ini juga mencakup managedhsm.azure.net;managedhsm.azure.cn;managedhsm.usgovcloudapi.net;managedhsm.microsoftazure.de.
Catatan
Penyedia Azure Key Vault yang terintegrasi dalam driver ODBC mendukung baik Vault maupun Managed HSM di Azure Key Vault.
Menggunakan penyedia Windows Certificate Store
Driver ODBC untuk SQL Server di Windows menyertakan penyedia penyimpanan kunci master kolom bawaan untuk Windows Certificate Store, bernama MSSQL_CERTIFICATE_STORE. (Penyedia ini tidak tersedia di macOS atau Linux.) Dengan penyedia ini, CMK disimpan secara lokal di komputer klien dan tidak ada konfigurasi tambahan oleh aplikasi yang diperlukan untuk menggunakannya dengan driver. Namun, aplikasi harus memiliki akses ke sertifikat dan kunci privatnya di penyimpanan. Untuk informasi selengkapnya, lihat Membuat dan Menyimpan Kunci Master Kolom (Always Encrypted).
Menggunakan penyedia keystore kustom
Driver ODBC untuk SQL Server juga mendukung penyedia keystore pihak ketiga kustom menggunakan antarmuka CEKeystoreProvider. Fitur ini memungkinkan aplikasi memuat, mengkueri, dan mengonfigurasi penyedia keystore sehingga dapat digunakan oleh driver untuk mengakses kolom terenkripsi. Aplikasi juga dapat berinteraksi langsung dengan penyedia keystore untuk mengenkripsi CEK untuk penyimpanan di SQL Server dan melakukan tugas di luar mengakses kolom terenkripsi dengan ODBC; untuk informasi selengkapnya, lihat Penyedia Keystore Kustom.
Dua atribut koneksi digunakan untuk berinteraksi dengan penyedia keystore kustom. Yaitu:
SQL_COPT_SS_CEKEYSTOREPROVIDERSQL_COPT_SS_CEKEYSTOREDATA
Yang pertama digunakan untuk memuat dan mencantumkan penyedia keystore yang telah dimuat, sedangkan yang terakhir memungkinkan komunikasi antara aplikasi dan penyedia. Atribut koneksi ini dapat digunakan kapan saja, sebelum atau sesudah membuat koneksi, karena interaksi penyedia aplikasi tidak melibatkan komunikasi dengan SQL Server. Namun, karena driver belum dimuat, mengatur dan mendapatkan atribut ini sebelum menyambungkan akan menyebabkannya diproses oleh Driver Manager, dan mungkin tidak menghasilkan hasil yang diharapkan.
Memuat penyedia keystore
Menetapkan atribut koneksi SQL_COPT_SS_CEKEYSTOREPROVIDER memungkinkan aplikasi klien memuat pustaka penyedia, sehingga penyedia keystore yang terdapat di dalamnya dapat digunakan.
SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
| Argumen | Deskripsi |
|---|---|
ConnectionHandle |
[Input] Handle koneksi. Harus berupa penangan koneksi yang valid, tetapi penyedia yang dimuat melalui satu penangan koneksi dapat diakses dari penangan koneksi lain mana pun di dalam proses yang sama. |
Attribute |
[Input] Atribut yang akan diatur: konstanta SQL_COPT_SS_CEKEYSTOREPROVIDER . |
ValuePtr |
[Input] Penunjuk ke string karakter yang diakhiri dengan null yang menentukan nama file pustaka penyedia. Untuk SQLSetConnectAttrA, nilai ini adalah string ANSI (multibyte). Untuk SQLSetConnectAttrW, nilai ini adalah string Unicode (wchar_t). |
StringLength |
[Input] Panjang string ValuePtr, atau SQL_NTS. |
Driver mencoba memuat pustaka yang diidentifikasi oleh parameter ValuePtr menggunakan mekanisme pemuatan pustaka dinamis yang ditentukan platform (dlopen() di Linux dan macOS, LoadLibrary() di Windows), dan menambahkan penyedia apa pun yang ditentukan di sana ke daftar penyedia yang diketahui oleh driver. Kesalahan berikut dapat terjadi:
| Kesalahan | Deskripsi |
|---|---|
CE203 |
Pustaka dinamis tidak dapat dimuat. |
CE203 |
Simbol "CEKeyStoreProvider" yang diekspor tidak ditemukan di pustaka. |
CE203 |
Satu atau beberapa penyedia di pustaka sudah dimuat. |
SQLSetConnectAttr mengembalikan nilai kesalahan atau keberhasilan yang biasa, dan informasi lebih lanjut tersedia untuk kesalahan apa pun yang terjadi melalui mekanisme diagnostik ODBC standar.
Catatan
Programmer aplikasi harus memastikan bahwa setiap penyedia kustom dimuat sebelum kueri yang mengharuskannya dikirim melalui koneksi apa pun. Kegagalan untuk melakukannya menghasilkan kesalahan:
| Kesalahan | Deskripsi |
|---|---|
CE200 |
Penyedia keystore %1 tidak ditemukan. Pastikan bahwa pustaka penyedia keystore yang sesuai telah dimuat. |
Catatan
Implementator penyedia keystore harus menghindari penggunaan MSSQL atas nama penyedia kustom mereka. Istilah ini dicadangkan secara eksklusif untuk penggunaan Microsoft dan dapat menyebabkan konflik dengan penyedia bawaan di masa mendatang. Menggunakan istilah ini atas nama penyedia kustom dapat mengakibatkan peringatan ODBC.
Mendapatkan daftar penyedia yang telah dimuat
Mendapatkan atribut koneksi ini memungkinkan aplikasi klien untuk menentukan penyedia keystore yang saat ini dimuat di driver (termasuk penyedia bawaan tersebut.) Proses ini hanya dapat dilakukan setelah menyambungkan.
SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StringLengthPtr);
| Argumen | Deskripsi |
|---|---|
ConnectionHandle |
[Input] Handle koneksi. Harus berupa penangan koneksi yang valid, tetapi penyedia yang dimuat melalui satu penangan koneksi dapat diakses dari penangan koneksi lain mana pun di dalam proses yang sama. |
Attribute |
[Input] Atribut yang akan diambil: konstanta SQL_COPT_SS_CEKEYSTOREPROVIDER. |
ValuePtr |
[Output] Pointer ke memori untuk mengembalikan nama penyedia yang dimuat berikutnya. |
BufferLength |
[Input] Panjang ValuePtr buffer. |
StringLengthPtr |
[Output] Penunjuk ke buffer untuk mengembalikan jumlah total byte (tidak termasuk karakter penghentian null) yang tersedia untuk dikembalikan dalam *ValuePtr. Jika ValuePtr adalah pointer null, tidak ada panjang yang dikembalikan. Jika nilai atribut adalah string dan jumlah byte yang tersedia untuk dikembalikan lebih besar daripada BufferLength dikurangi panjang karakter terminasi null, data dalam *ValuePtr dipotong menjadi BufferLength dikurangi panjang karakter terminasi null dan diakhiri dengan null oleh driver. |
Untuk memungkinkan pengambilan seluruh daftar, setiap operasi Get mengembalikan nama penyedia saat ini dan menaikkan penghitung internal ke nilai berikutnya. Setelah penghitung ini mencapai akhir daftar, string kosong ("") dikembalikan, dan penghitung diatur ulang; operasi Get berikutnya kemudian berlanjut lagi dari awal daftar.
Berkomunikasi dengan penyedia keystore
Atribut koneksi SQL_COPT_SS_CEKEYSTOREDATA memungkinkan aplikasi klien berkomunikasi dengan penyedia keystore yang dimuat untuk mengonfigurasi parameter tambahan, materi kunci, dan sebagainya. Komunikasi antara aplikasi klien dan penyedia mengikuti protokol respons permintaan sederhana, berdasarkan permintaan Dapatkan dan Atur menggunakan atribut koneksi ini. Komunikasi hanya dimulai oleh aplikasi klien.
Catatan
Karena sifat panggilan ODBC yang ditangani oleh CEKeyStoreProvider (SQLGet/SetConnectAttr), antarmuka ODBC hanya mendukung penyetelan data pada tingkat konteks koneksi.
Aplikasi berkomunikasi dengan penyedia keystore melalui driver melalui struktur CEKeystoreData:
typedef struct CEKeystoreData {
wchar_t *name;
unsigned int dataSize;
char data[];
} CEKEYSTOREDATA;
| Argumen | Deskripsi |
|---|---|
name |
[Input] Setelah Diatur, nama penyedia tempat data dikirim. Diabaikan pada Get. String karakter lebar yang diakhiri null. |
dataSize |
[Input] Ukuran array data mengikuti struktur. |
data |
[InOut] Setelah Diatur, data yang akan dikirim ke penyedia. Data ini mungkin bersifat acak; driver tidak berupaya menafsirkannya. Pada operasi Get, buffer untuk menerima data yang dibaca dari penyedia. |
Menulis data ke penyedia
Panggilan SQLSetConnectAttr yang menggunakan atribut SQL_COPT_SS_CEKEYSTOREDATA menuliskan "paket" data ke penyedia keystore yang ditentukan.
SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
| Argumen | Deskripsi |
|---|---|
ConnectionHandle |
[Input] Handle koneksi. Harus berupa penangan koneksi yang valid, tetapi penyedia yang dimuat melalui satu penangan koneksi dapat diakses dari penangan koneksi lain mana pun di dalam proses yang sama. |
Attribute |
[Input] Atribut yang akan diatur: konstanta SQL_COPT_SS_CEKEYSTOREDATA . |
ValuePtr |
[Input] Pointer ke struktur CEKeystoreData. Bidang nama struktur mengidentifikasi penyedia tempat data dimaksudkan. |
StringLength |
[Input] konstanta SQL_IS_POINTER |
Informasi kesalahan yang lebih rinci dapat diperoleh melalui SQLGetDiacRec.
Catatan
Penyedia dapat menggunakan handle koneksi untuk mengaitkan data yang ditulis dengan koneksi tertentu, jika menginginkannya. Fitur ini berguna untuk menerapkan konfigurasi per koneksi. Ini juga dapat mengabaikan konteks koneksi dan memperlakukan data secara identik terlepas dari koneksi yang digunakan untuk mengirim data. Untuk informasi selengkapnya, lihat Asosiasi Konteks.
Membaca data dari penyedia
Pemanggilan SQLGetConnectAttr menggunakan atribut SQL_COPT_SS_CEKEYSTOREDATA membaca satu "paket" data dari penyedia yang terakhir ditulisi. Jika tidak ada, Kesalahan Urutan Fungsi terjadi. Pengimplementasi penyedia keystore didorong untuk mendukung "penulisan dummy" sebesar 0 byte sebagai cara untuk memilih penyedia bagi operasi pembacaan tanpa menimbulkan efek samping lain, jika hal itu masuk akal.
SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StringLengthPtr);
| Argumen | Deskripsi |
|---|---|
ConnectionHandle |
[Input] Handle koneksi. Harus berupa penangan koneksi yang valid, tetapi penyedia yang dimuat melalui satu penangan koneksi dapat diakses dari penangan koneksi lain mana pun di dalam proses yang sama. |
Attribute |
[Input] Atribut yang akan diambil: konstanta SQL_COPT_SS_CEKEYSTOREDATA. |
ValuePtr |
[Output] Penunjuk ke struktur CEKeystoreData tempat data yang dibaca dari penyedia ditempatkan. |
BufferLength |
[Input] konstanta SQL_IS_POINTER |
StringLengthPtr |
[Output] Pointer ke buffer tempat BufferLength akan dikembalikan. Jika *ValuePtr adalah penunjuk null, tidak ada panjang yang dikembalikan. |
Pemanggil harus memastikan bahwa buffer dengan ukuran yang memadai setelah struktur CEKEYSTOREDATA dialokasikan agar penyedia dapat menulis ke dalamnya. Setelah kembali, bidang dataSize-nya diperbarui dengan panjang data aktual yang dibaca dari penyedia. Informasi kesalahan yang lebih rinci dapat diperoleh melalui SQLGetDiacRec.
Antarmuka ini tidak menempatkan persyaratan tambahan pada format data yang ditransfer antara aplikasi dan penyedia keystore. Setiap penyedia dapat menentukan protokol/format datanya sendiri, tergantung pada kebutuhannya.
Untuk contoh penerapan penyedia keystore Anda sendiri, lihat Penyedia Keystore Kustom
Batasan driver ODBC saat menggunakan Always Encrypted
Operasi Asinkron
Meskipun driver ODBC akan memungkinkan penggunaan operasi asinkron dengan Always Encrypted, ada dampak performa pada operasi ketika Always Encrypted diaktifkan. Panggilan ke sys.sp_describe_parameter_encryption untuk menentukan metadata enkripsi bagi pernyataan tersebut bersifat memblokir dan akan menyebabkan driver menunggu hingga server mengembalikan metadata sebelum mengembalikan SQL_STILL_EXECUTING.
Mengambil data dalam bagian dengan SQLGetData
Pada versi sebelum ODBC Driver 17 untuk SQL Server, kolom karakter dan biner terenkripsi tidak dapat diambil sebagian-sebagian dengan SQLGetData. Hanya satu panggilan ke SQLGetData yang dapat dilakukan, dengan buffer dengan panjang yang cukup untuk berisi seluruh data kolom.
Mengirim data dalam bagian dengan SQLPutData
Sebelum ODBC Driver 17.3 for SQL Server, data yang akan disisipkan atau dibandingkan tidak dapat dikirim secara bertahap dengan SQLPutData. Hanya satu panggilan ke SQLPutData yang dapat dilakukan, dengan buffer yang berisi seluruh data. Untuk menyisipkan data panjang ke dalam kolom terenkripsi, gunakan API Salin Massal, yang dijelaskan di bagian berikutnya, dengan file data input.
Uang terenkripsi dan smallmoney
Kolom money atau smallmoney yang dienkripsi tidak dapat dijadikan target parameter, karena tidak ada tipe data ODBC spesifik yang dipetakan ke tipe tersebut, sehingga mengakibatkan error Operand Type Clash.
Salinan massal kolom terenkripsi
Penggunaan fungsi SQL Bulk Copy dan utilitas bcp didukung oleh Always Encrypted sejak ODBC Driver 17 for SQL Server. Baik plaintext (dienkripsi saat dimasukkan dan didekripsi saat diambil) maupun ciphertext (ditransfer apa adanya) dapat dimasukkan dan diambil menggunakan API Bulk Copy (bcp_*) dan utilitas bcp.
Untuk mengambil teks sandi dalam bentuk varbinary(max) (misalnya, untuk pemuatan massal ke basis data yang berbeda), buat koneksi tanpa opsi
ColumnEncryption(atau atur keDisabled) dan lakukan operasi BCP OUT.Untuk menyisipkan dan mengambil teks biasa, dan biarkan driver secara transparan melakukan enkripsi dan dekripsi sesuai kebutuhan, pengaturan
ColumnEncryptionkeEnabledsudah cukup. Fungsionalitas API BCP tidak berubah.Untuk menyisipkan ciphertext dalam bentuk varbinary(max) (misalnya, seperti yang diperoleh di atas), atur opsi
BCPMODIFYENCRYPTEDke TRUE dan lakukan operasi BCP IN. Agar data hasilnya dapat didekripsi, pastikan bahwa CEK kolom tujuan sama dengan CEK asal ciphertext tersebut awalnya diperoleh.
Saat menggunakan utilitas bcp: Untuk mengontrol pengaturan ColumnEncryption, gunakan opsi -D dan tentukan DSN yang berisi nilai yang diinginkan. Untuk menyisipkan teks sandi, pastikan pengaturan ALLOW_ENCRYPTED_VALUE_MODIFICATIONS pengguna diaktifkan.
Tabel berikut ini menyediakan ringkasan tindakan saat beroperasi pada kolom terenkripsi:
ColumnEncryption |
Arah BCP | Deskripsi |
|---|---|---|
Disabled |
OUT (ke klien) | Mengambil teks sandi. Jenis data yang diamati adalah varbinary(max). |
Enabled |
OUT (ke klien) | Mengambil teks biasa. Driver akan mendekripsi data kolom. |
Disabled |
IN (ke server) | Menyisipkan teks sandi. Pengaturan ini ditujukan untuk memindahkan data terenkripsi secara buram tanpa mengharuskannya didekripsi. Operasi akan gagal jika opsi ALLOW_ENCRYPTED_VALUE_MODIFICATIONS tidak ditetapkan untuk pengguna, atau BCPMODIFYENCRYPTED tidak ditetapkan pada handle koneksi. Untuk informasi selengkapnya, lihat di bawah ini. |
Enabled |
IN (ke server) | Sisipkan teks biasa. Driver akan mengenkripsi data kolom. |
Opsi BCPMODIFYENCRYPTED
Untuk mencegah kerusakan data, server biasanya tidak mengizinkan penyisipan ciphertext langsung ke kolom terenkripsi, dan dengan demikian upaya untuk melakukannya akan gagal; namun, untuk pemuatan massal data terenkripsi menggunakan API BCP, mengatur BCPMODIFYENCRYPTEDopsi bcp_control ke TRUE akan memungkinkan ciphertext dimasukkan secara langsung, dan mengurangi risiko kerusakan data terenkripsi melalui pengaturan ALLOW_ENCRYPTED_VALUE_MODIFICATIONS opsi pada akun pengguna. Meskipun demikian, kunci harus cocok dengan data, dan ada baiknya melakukan beberapa pemeriksaan dalam mode hanya-baca terhadap data yang disisipkan setelah penyisipan massal dan sebelum data tersebut digunakan lebih lanjut.
Untuk informasi selengkapnya, lihat Memigrasikan Data Sensitif yang Dilindungi oleh Always Encrypted.
Ringkasan API Always Encrypted
Kata kunci string koneksi
| Nama | Deskripsi |
|---|---|
ColumnEncryption |
Nilai yang diterima adalah Enabled/Disabled.Enabled - mengaktifkan fungsionalitas Always Encrypted untuk koneksi.Disabled - nonaktifkan fungsionalitas Always Encrypted untuk koneksi.protokol atestasi, URL atestasi - (versi 17.4 dan yang lebih baru) memungkinkan Always Encrypted dengan enklave aman menggunakan protokol atestasi yang ditentukan dan URL atestasi. Default adalah Disabled. |
KeyStoreAuthentication |
Nilai yang Valid: KeyVaultPassword, KeyVaultClientSecret, KeyVaultInteractive, KeyVaultManagedIdentity |
KeyStorePrincipalId |
Ketika KeyStoreAuthentication = KeyVaultPassword, atur nilai ini ke nama prinsipal pengguna Microsoft Entra yang valid. Saat KeyStoreAuthentication = KeyVaultClientSecret mengatur nilai ini ke ID klien aplikasi Microsoft Entra yang valid Ketika KeyStoreAuthentication = KeyVaultManagedIdentity, atur nilai ini ke ID objek identitas terkelola yang ditetapkan pengguna. Jika tidak ada nilai yang disediakan, identitas terkelola yang ditetapkan sistem akan digunakan. |
KeyStoreSecret |
Ketika KeyStoreAuthentication = KeyVaultPassword mengatur nilai ini ke kata sandi untuk nama pengguna yang sesuai. Saat KeyStoreAuthentication = KeyVaultClientSecret mengatur nilai ini ke rahasia aplikasi yang terkait dengan ID klien aplikasi Microsoft Entra yang valid |
Atribut koneksi
| Nama | Tipe | Deskripsi |
|---|---|---|
SQL_COPT_SS_COLUMN_ENCRYPTION |
Sambungkan sebelumnya |
SQL_COLUMN_ENCRYPTION_DISABLE (0) - Nonaktifkan Always Encrypted SQL_COLUMN_ENCRYPTION_ENABLE (1) - Aktifkan Always Encryptedpenunjuk ke string *attestation protocol*,*attestation URL* - (versi 17.4 atau yang lebih baru) aktifkan dengan Secure Enclave |
SQL_COPT_SS_CEKEYSTOREPROVIDER |
Setelah terhubung | [Set] - Mencoba memuat CEKeystoreProvider [Get] - Mengembalikan nama CEKeystoreProvider |
SQL_COPT_SS_CEKEYSTOREDATA |
Pasca-sambungan | [Set] - Menulis data ke CEKeystoreProvider [Get] - Baca data dari CEKeystoreProvider |
SQL_COPT_SS_CEKCACHETTL |
Pasca-sambungan | [Set] - Atur TTL cache CEK [Get] - Ambil TTL cache CEK saat ini |
SQL_COPT_SS_TRUSTEDCMKPATHS |
Setelah terhubung | [Set] - Atur penunjuk jalur CMK tepercaya [Get] - Dapatkan penunjuk jalur CMK tepercaya saat ini |
Atribut dari pernyataan
| Nama | Deskripsi |
|---|---|
SQL_SOPT_SS_COLUMN_ENCRYPTION |
SQL_CE_DISABLED (0) - Always Encrypted dinonaktifkan untuk pernyataan SQL_CE_RESULTSETONLY (1) - dekripsi saja. Tataan hasil dan nilai pengembalian didekripsi, dan parameter tidak dienkripsi SQL_CE_ENABLED (3) - Always Encrypted diaktifkan dan digunakan untuk parameter dan hasil |
Bidang deskriptor
| Bidang IPD | Ukuran/Jenis | Nilai Bawaan | Deskripsi |
|---|---|---|---|
SQL_CA_SS_FORCE_ENCRYPT (1236) |
WORD (2 byte) | 0 | Ketika 0 (default): keputusan untuk mengenkripsi parameter ini ditentukan oleh ketersediaan metadata enkripsi. Saat bernilai nonzero: jika metadata enkripsi tersedia untuk parameter ini, parameter ini akan dienkripsi. Jika tidak, permintaan gagal dengan kesalahan [CE300] [Microsoft][ODBC Driver 17 untuk SQL Server]Enkripsi wajib ditentukan untuk parameter tetapi tidak ada metadata enkripsi yang disediakan oleh server. |
opsi bcp_control
| Nama Opsi | Nilai Bawaan | Deskripsi |
|---|---|---|
BCPMODIFYENCRYPTED (21) |
SALAH | Ketika TRUE, memungkinkan nilai varbinary(max) dimasukkan ke dalam kolom terenkripsi. Saat bernilai FALSE, mencegah penyisipan kecuali jika tipe yang benar dan metadata enkripsi disertakan. |
Pemecahan Masalah
Saat mengalami kesulitan menggunakan Always Encrypted, mulailah dengan memeriksa poin-poin berikut:
CEK yang mengenkripsi kolom yang diinginkan ada dan dapat diakses di server.
CMK yang mengenkripsi CEK memiliki metadata yang dapat diakses di server dan juga dapat diakses dari klien.
ColumnEncryptiondiaktifkan di DSN, string koneksi, atau atribut koneksi, dan, jika menggunakan enklave aman, memiliki format yang benar.
Selain itu, saat menggunakan enklave aman, kegagalan pengesahan mengidentifikasi langkah dalam proses pengesahan di mana kegagalan terjadi, sesuai dengan tabel berikut:
| Langkah | Deskripsi |
|---|---|
| 0-99 | Respons pengesahan tidak valid, atau kesalahan verifikasi tanda tangan. |
| 100-199 | Kesalahan saat mengambil sertifikat dari URL pengesahan. Pastikan <attestation URL>/v2.0/signingCertificates valid dan dapat diakses. |
| 200-299 | Format identitas enklave yang tidak terduga atau salah. |
| 300-399 | Kesalahan saat membuat saluran aman dengan enklave. |