Menggunakan Always Encrypted dengan Driver ODBC untuk SQL Server
Berlaku untuk
- Odbc Driver 13.1+ untuk SQL Server
Pendahuluan
Artikel ini menyediakan informasi tentang cara mengembangkan aplikasi ODBC menggunakan Always Encrypted (Mesin Database) atau Always Encrypted dengan enklave aman dan 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 fitur ini untuk mengaktifkan fungsionalitas yang lebih kaya pada data sensitif sambil menjaga kerahasiaan data.
Untuk informasi selengkapnya, lihat Always Encrypted (Mesin Database) dan Always Encrypted dengan enklave aman.
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 lainnya.
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 dalam konfigurasi DSN, menggunakan kunci dan nilai yang sama (yang akan ditimpa oleh pengaturan string koneksi, jika ada), atau secara terprogram dengan SQL_COPT_SS_COLUMN_ENCRYPTION
atribut pra-koneksi. 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 database VIEW ANY COLUMN MASTER KEY DEFINITION dan VIEW ANY COLUMN ENCRYPTION KEY DEFINITION , yang diperlukan untuk mengakses metadata tentang kunci Always Encrypted dalam database. Untuk detailnya, 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
Di Linux dan macOS, OpenSSL versi 1.0.1 atau yang lebih baru diperlukan untuk menggunakan Always Encrypted dengan enklave aman.
Dimulai dengan 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),
<attestation protocol>
harus .VBS-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),
<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 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=myPassword;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=myPassword;Encrypt=yes;ColumnEncryption=VBS-NONE"
Jika server dan layanan pengesahan dikonfigurasi dengan benar bersama dengan CMK dan CEK berkemampuan enklave untuk kolom terenkripsi, Anda dapat menjalankan kueri yang menggunakan enklave seperti enkripsi di tempat dan komputasi yang kaya, selain fungsionalitas yang ada yang 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. Untuk program Anda, seolah-olah kolom 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 sebagai array 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 Pasien. 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). Saat menggunakan parameter bersifat opsional saat mengirim nilai ke kolom yang tidak dienkripsi (meskipun sangat disarankan karena membantu mencegah injeksi SQL), nilai diperlukan untuk nilai yang menargetkan kolom terenkripsi. Jika nilai yang disisipkan dalam kolom SSN atau BirthDate diteruskan sebagai harfiah yang disematkan dalam pernyataan kueri, kueri akan gagal karena driver tidak mencoba mengenkripsi atau memproses literal dalam kueri. Akibatnya, server akan menolaknya sebagai tidak kompatibel dengan kolom terenkripsi.
Jenis parameter SQL yang dimasukkan ke dalam kolom SSN diatur ke SQL_CHAR, yang memetakan ke tipe data SQL Server karakter (
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 Programmer ODBC -- Lampiran D: Jenis Data untuk informasi tentang pemetaan jenis 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. Filter kueri di atas menurut LastName, yang tidak dienkripsi dalam database. 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
Dimulai dengan driver versi 17.7 dimungkinkan untuk menggunakan Always Encrypted 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 baik SQL_NUMERIC
atau SQL_DOUBLE
(presisi mungkin 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 dari
decimal
jenis data SQL Server dannumeric
sama dengan presisi dan skala yang dikonfigurasi untuk kolom target.Presisi parameter yang menargetkan kolom jenis
datetime2
data , ,datetimeoffset
atautime
SQL Server tidak lebih besar dari presisi untuk kolom target, dalam 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 menyambungkan dengan mengatur
SQL_COPT_SS_COLUMN_ENCRYPTION
atribut koneksi untuk koneksi tertentu, atauSQL_SOPT_SS_COLUMN_ENCRYPTION
atribut pernyataan untuk pernyataan tertentu).Anda menggunakan SQLBindParameter untuk mengirim data yang menargetkan kolom terenkripsi. Contoh di bawah ini memperlihatkan kueri yang salah memfilter menurut literal/konstanta pada kolom terenkripsi (SSN), alih-alih meneruskan literal 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 untuk memperbarui baris dalam resultset menggunakan buffer yang terikat dengan SQLBindCol dan ke dalam data baris mana yang sebelumnya diambil. Karena perilaku padding asimetris dari jenis panjang tetap terenkripsi, dimungkinkan untuk secara tidak terduga mengubah data kolom ini saat melakukan pembaruan pada kolom lain di baris. Dengan AE, nilai karakter panjang tetap akan diisi jika nilainya lebih kecil dari ukuran buffer.
Untuk mengurangi perilaku ini, gunakan SQL_COLUMN_IGNORE
bendera untuk mengabaikan kolom yang tidak akan diperbarui sebagai bagian SQLBulkOperations
dari dan 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 SQLMoreResults
sebelum 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
pernyataan 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.
Memanggil ke penyimpanan kunci master kolom untuk mengakses kunci master 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 per 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 |
Pernyataan baru menangani yang dibuat dari koneksi dengan Always Encrypted diaktifkan default ke SQL_CE_ENABLED. Menangani yang dibuat dari koneksi dengannya dinonaktifkan default ke SQL_CE_DISABLED (dan tidak dimungkinkan untuk mengaktifkan Always Encrypted pada koneksi tersebut.)
Jika sebagian besar kueri kolom terenkripsi akses aplikasi klien, poin berikut direkomendasikan:
Atur
ColumnEncryption
kata kunci string koneksi keEnabled
.Atur atribut ke
SQL_SOPT_SS_COLUMN_ENCRYPTION
SQL_CE_DISABLED
pada pernyataan yang tidak mengakses kolom terenkripsi apa pun. Pengaturan ini akan menonaktifkan panggilansys.sp_describe_parameter_encryption
dan upaya untuk mendekripsi nilai apa pun dalam tataan hasil.Atur atribut ke
SQL_SOPT_SS_COLUMN_ENCRYPTION
SQL_CE_RESULTSETONLY
pada pernyataan yang tidak memiliki parameter apa pun yang memerlukan enkripsi, tetapi ambil data dari kolom terenkripsi. Pengaturan ini akan menonaktifkan panggilansys.sp_describe_parameter_encryption
dan enkripsi parameter. Hasil yang berisi kolom terenkripsi akan terus didekripsi.Gunakan pernyataan yang disiapkan untuk kueri yang akan dijalankan lebih dari sekali; siapkan kueri dengan
SQLPrepare
dan simpan handel pernyataan, gunakan kembali setiapSQLExecute
kali 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
Paksa 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.
Penembolokan kunci enkripsi kolom
Untuk mengurangi jumlah panggilan ke penyimpanan kunci master kolom untuk mendekripsi kunci enkripsi kolom, driver menyimpan CEK teks biasa dalam 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 0, tidak ada CEK yang di-cache.
Jalur kunci tepercaya
Dimulai dengan Driver ODBC 17.1 untuk SQL Server, SQL_COPT_SS_TRUSTEDCMKPATHS
atribut koneksi memungkinkan aplikasi untuk mengharuskan operasi Always Encrypted hanya menggunakan daftar CMK tertentu, yang diidentifikasi oleh jalur kunci mereka. Secara default, atribut ini adalah NULL, yang berarti bahwa driver menerima jalur kunci apa pun. Untuk menggunakan fitur ini, atur SQL_COPT_SS_TRUSTEDCMKPATHS
untuk menunjuk ke string karakter lebar yang dibatasi null-delimited dan null-terminated yang mencantumkan jalur kunci yang diizinkan. Memori yang ditunjukkan oleh atribut ini harus tetap valid selama operasi enkripsi atau dekripsi menggunakan handel koneksi tempat diatur --- di mana driver akan memeriksa apakah jalur CMK seperti yang ditentukan oleh metadata server tidak peka huruf besar/kecil dalam daftar ini. 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 master kolom
Untuk mengenkripsi atau mendekripsi data, driver perlu mendapatkan 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 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 berkomunikasi dengan keystore menggunakan 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 pernyataan CREATE COLUMN MASTER KEY (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 sistem atau ditetapkan pengguna; untuk informasi selengkapnya, lihat Identitas Terkelola untuk sumber daya Azure.
Azure Key Vault Interactive (17.7+ driver Windows) - dengan metode ini, kredensial diautentikasi melalui ID Microsoft Entra dengan ID Masuk.
Untuk mengizinkan driver menggunakan CMK yang disimpan di AKV untuk enkripsi kolom, gunakan kata kunci khusus string koneksi berikut:
Jenis Informasi masuk | 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 string 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 (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 titik akhir AKV yang dipercayainya. Dimulai dengan driver versi 17.5.2, daftar ini dapat dikonfigurasi: atur AKVTrustedEndpoints
properti di driver atau ODBCINST DSN. INI atau ODBC. Kunci registri INI (Windows) atau odbcinst.ini
atau odbc.ini
bagian file (Linux/macOS) ke daftar yang dibatasi 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 default (per 17,5) adalah vault.azure.net;vault.azure.cn;vault.usgovcloudapi.net;vault.microsoftazure.de
. Dimulai dengan 17.7, daftar juga menyertakan managedhsm.azure.net;managedhsm.azure.cn;managedhsm.usgovcloudapi.net;managedhsm.microsoftazure.de
.
Catatan
Penyedia Azure Key Vault bawaan driver ODBC mendukung Vault dan HSM Terkelola 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_CEKEYSTOREPROVIDER
SQL_COPT_SS_CEKEYSTOREDATA
Yang pertama digunakan untuk memuat dan menghitung penyedia keystore yang dimuat, sementara yang terakhir memungkinkan komunikasi penyedia aplikasi. 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
SQL_COPT_SS_CEKEYSTOREPROVIDER
Mengatur atribut koneksi memungkinkan aplikasi klien memuat pustaka penyedia, yang tersedia untuk menggunakan penyedia keystore yang terkandung di sana.
SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
Argumen | Deskripsi |
---|---|
ConnectionHandle |
[Input] Handel koneksi. Harus merupakan handel koneksi yang valid, tetapi penyedia yang dimuat melalui satu handel koneksi dapat diakses dari pegangan koneksi lainnya dalam proses yang sama. |
Attribute |
[Input] Atribut yang akan diatur: konstanta SQL_COPT_SS_CEKEYSTOREPROVIDER . |
ValuePtr |
[Input] Penunjuk ke string karakter yang dihentikan 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 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] Handel koneksi. Harus merupakan handel koneksi yang valid, tetapi penyedia yang dimuat melalui satu handel koneksi dapat diakses dari pegangan koneksi lainnya dalam proses yang sama. |
Attribute |
[Input] Atribut untuk 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 karakter dan jumlah byte yang tersedia untuk dikembalikan lebih besar dari BufferLength dikurangi panjang karakter penghentian null, data dalam *ValuePtr dipotong menjadi BufferLength dikurangi panjang karakter null-termination dan dihentikan null oleh driver. |
Untuk memungkinkan pengambilan seluruh daftar, setiap operasi Get mengembalikan nama penyedia saat ini, dan menaikkan penghitung internal ke yang berikutnya. Setelah penghitung ini mencapai akhir daftar, string kosong ("") dikembalikan, dan penghitung diatur ulang; operasi Dapatkan berturut-turut kemudian lanjutkan lagi dari awal daftar.
Berkomunikasi dengan penyedia keystore
Atribut SQL_COPT_SS_CEKEYSTOREDATA
koneksi memungkinkan aplikasi klien untuk berkomunikasi dengan penyedia keystore yang dimuat untuk mengonfigurasi lebih banyak parameter, bahan 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 ODBC memanggil respons CEKeyStoreProvider (SQLGet/SetConnectAttr), antarmuka ODBC hanya mendukung pengaturan data pada resolusi 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 dihentikan null. |
dataSize |
[Input] Ukuran array data mengikuti struktur. |
data |
[InOut] Setelah Diatur, data yang akan dikirim ke penyedia. Data ini mungkin segan-segan; driver tidak membuat upaya untuk menafsirkannya. Setelah Get, buffer untuk menerima data yang dibaca dari penyedia. |
Menulis data ke penyedia
Panggilan SQLSetConnectAttr
menggunakan SQL_COPT_SS_CEKEYSTOREDATA
atribut menulis "paket" data ke penyedia keystore yang ditentukan.
SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
Argumen | Deskripsi |
---|---|
ConnectionHandle |
[Input] Handel koneksi. Harus merupakan handel koneksi yang valid, tetapi penyedia yang dimuat melalui satu handel koneksi dapat diakses dari pegangan koneksi lainnya 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 handel koneksi untuk mengaitkan data tertulis ke koneksi tertentu, jika diinginkan. 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
Panggilan untuk SQLGetConnectAttr
menggunakan SQL_COPT_SS_CEKEYSTOREDATA
atribut membaca "paket" data dari penyedia yang ditulis terakhir ke penyedia. Jika tidak ada, Kesalahan Urutan Fungsi terjadi. Pelaksana penyedia keystore didorong untuk mendukung "penulisan dummy" 0 byte sebagai cara memilih penyedia untuk operasi baca tanpa menyebabkan efek samping lainnya, jika masuk akal untuk melakukannya.
SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StringLengthPtr);
Argumen | Deskripsi |
---|---|
ConnectionHandle |
[Input] Handel koneksi. Harus merupakan handel koneksi yang valid, tetapi penyedia yang dimuat melalui satu handel koneksi dapat diakses dari pegangan koneksi lainnya dalam proses yang sama. |
Attribute |
[Input] Atribut untuk 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] Penunjuk ke buffer untuk mengembalikan BufferLength. Jika *ValuePtr adalah penunjuk null, tidak ada panjang yang dikembalikan. |
Pemanggil harus memastikan bahwa buffer dengan panjang yang cukup mengikuti struktur CEKEYSTOREDATA dialokasikan bagi penyedia untuk menulis. 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 untuk sys.sp_describe_parameter_encryption
menentukan metadata enkripsi untuk pernyataan memblokir dan akan menyebabkan driver menunggu server mengembalikan metadata sebelum mengembalikan SQL_STILL_EXECUTING
.
Mengambil data dalam bagian dengan SQLGetData
Sebelum Odbc Driver 17 untuk SQL Server, karakter terenkripsi dan kolom biner tidak dapat diambil di bagian 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 untuk SQL Server, data untuk penyisipan atau perbandingan tidak dapat dikirim dalam bagian 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
Uang terenkripsi atau kolom smallmoney tidak dapat ditargetkan oleh parameter, karena tidak ada jenis data ODBC tertentu yang memetakan ke jenis tersebut, yang mengakibatkan kesalahan Operand Type Clash.
Salinan massal kolom terenkripsi
Penggunaan fungsi SQL Bulk Copy dan utilitas bcp didukung dengan Always Encrypted sejak ODBC Driver 17 untuk SQL Server. Baik teks biasa (dienkripsi pada penyisipan dan didekripsi saat pengambilan) dan ciphertext (verbatim yang ditransfer) dapat dimasukkan dan diambil menggunakan API Salinan Massal (bcp_*) dan utilitas bcp .
Untuk mengambil ciphertext dalam bentuk varbinary(max) (misalnya, untuk pemuatan massal ke database yang berbeda), sambungkan tanpa
ColumnEncryption
opsi (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
ColumnEncryption
keEnabled
sudah cukup. Fungsionalitas API BCP tidak berubah.Untuk menyisipkan ciphertext dalam bentuk varbinary(max) (misalnya, seperti yang diambil di atas), atur
BCPMODIFYENCRYPTED
opsi ke TRUE dan lakukan operasi BCP IN. Agar data yang dihasilkan didekripsi, pastikan bahwa CEK kolom tujuan adalah CEK yang sama dengan CEK tempat ciphertext awalnya diperoleh.
Saat menggunakan utilitas bcp : Untuk mengontrol ColumnEncryption
pengaturan, gunakan opsi -D dan tentukan DSN yang berisi nilai yang diinginkan. Untuk menyisipkan ciphertext, pastikan ALLOW_ENCRYPTED_VALUE_MODIFICATIONS
pengaturan pengguna diaktifkan.
Tabel berikut ini menyediakan ringkasan tindakan saat beroperasi pada kolom terenkripsi:
ColumnEncryption |
Arah BCP | Deskripsi |
---|---|---|
Disabled |
OUT (ke klien) | Mengambil ciphertext. Jenis data yang diamati adalah varbinary(max). |
Enabled |
OUT (ke klien) | Mengambil teks biasa. Driver akan mendekripsi data kolom. |
Disabled |
IN (ke server) | Menyisipkan ciphertext. Pengaturan ini ditujukan untuk memindahkan data terenkripsi secara buram tanpa mengharuskannya didekripsi. Operasi akan gagal jika ALLOW_ENCRYPTED_VALUE_MODIFICATIONS opsi tidak diatur pada pengguna, atau BCPMODIFYENCRYPTED tidak diatur pada handel 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 BCPMODIFYENCRYPTED
opsi 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 untuk melakukan beberapa pemeriksaan baca-saja dari data yang disisipkan setelah penyisipan massal dan sebelum digunakan lebih lanjut.
Untuk informasi selengkapnya, lihat Memigrasikan Data Sensitif yang Dilindungi oleh Always Encrypted.
Ringkasan ALWAYS Encrypted API
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 pengesahan, URL pengesahan - (versi 17.4 dan yang lebih baru) memungkinkan Always Encrypted dengan enklave aman menggunakan protokol pengesahan yang ditentukan dan URL pengesahan. 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 KeyStoreAuthetication = KeyVaultClientSecret mengatur nilai ini ke ID klien aplikasi Microsoft Entra yang valid Ketika KeyStoreAuthetication = 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 |
Pra-sambung | SQL_COLUMN_ENCRYPTION_DISABLE (0) - Nonaktifkan Always Encrypted SQL_COLUMN_ENCRYPTION_ENABLE (1) - Aktifkan Always Encryptedpointer ke *attestation protocol*,*attestation URL* string - (versi 17.4 dan yang lebih baru) aktifkan dengan enklave aman |
SQL_COPT_SS_CEKEYSTOREPROVIDER |
Pasca-sambungan | [Set] - Mencoba memuat CEKeystoreProvider [Get] - Mengembalikan nama CEKeystoreProvider |
SQL_COPT_SS_CEKEYSTOREDATA |
Pasca-sambungan | [Set] - Menulis data ke CEKeystoreProvider [Get] - Membaca data dari CEKeystoreProvider |
SQL_COPT_SS_CEKCACHETTL |
Pasca-sambungan | [Set] - Atur TTL cache CEK [Get] - Dapatkan TTL cache CEK saat ini |
SQL_COPT_SS_TRUSTEDCMKPATHS |
Pasca-sambungan | [Set] - Atur penunjuk jalur CMK tepercaya [Get] - Dapatkan penunjuk jalur CMK tepercaya saat ini |
Atribut 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 Default | 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 nonzero: jika metadata enkripsi tersedia untuk parameter ini, metadata enkripsi 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 Default | Deskripsi |
---|---|---|
BCPMODIFYENCRYPTED (21) |
SALAH | Ketika TRUE, memungkinkan nilai varbinary(max) dimasukkan ke dalam kolom terenkripsi. Ketika FALSE, mencegah penyisipan kecuali jenis yang benar dan metadata enkripsi disediakan. |
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.
ColumnEncryption
diaktifkan dalam atribut DSN, string koneksi, atau 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. |