Bagikan melalui


Menggunakan Always Encrypted dengan Driver ODBC untuk SQL Server

Unduh driver ODBC

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> harus SGX-AAS.
    • Jika Anda tidak memerlukan pengesahan, <attestation-protocol> harus VBS-NONE. (Versi 18.1+)
  • <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 dan numeric sama dengan presisi dan skala yang dikonfigurasi untuk kolom target.

  • Presisi parameter yang menargetkan kolom jenis datetime2data , , datetimeoffsetatau time 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, atau SQL_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 ke Enabled.

  • Atur atribut ke SQL_SOPT_SS_COLUMN_ENCRYPTION SQL_CE_DISABLED pada pernyataan yang tidak mengakses kolom terenkripsi apa pun. Pengaturan ini akan menonaktifkan panggilan sys.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 panggilan sys.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 setiap SQLExecute 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 ke Disabled) dan lakukan operasi BCP OUT.

  • Untuk menyisipkan dan mengambil teks biasa, dan biarkan driver secara transparan melakukan enkripsi dan dekripsi sesuai kebutuhan, pengaturan ColumnEncryption ke Enabled 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 Encrypted
pointer 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.

  • ColumnEncryptiondiaktifkan 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.

Lihat juga