Uso di Always Encrypted con ODBC Driver for SQL Server

Scaricare il driver ODBC

Applicabile a

  • ODBC Driver 13.1+ for SQL Server

Introduzione

Questo articolo fornisce informazioni su come sviluppare applicazioni ODBC usando Always Encrypted (motore di database) o Always Encrypted con enclave sicure e ODBC Driver for SQL Server.

Always Encrypted consente alle applicazioni client di eseguire la crittografia dei dati sensibili senza mai rivelare i dati o le chiavi di crittografia a SQL Server o al database SQL di Azure. Un driver abilitato per Always Encrypted, come ODBC Driver for SQL Server, offre questo livello di sicurezza crittografando e decrittografando in modo trasparente i dati sensibili nell'applicazione client. Il driver determina automaticamente i parametri di query corrispondenti alle colonne di database con dati sensibili (protette mediante Always Encrypted) e crittografa i valori di tali parametri prima di passare i dati a SQL Server o al database SQL di Azure. Analogamente, il driver esegue in modo trasparente la decrittografia dei dati, recuperati dalle colonne di database crittografate nei risultati delle query. Always Encrypted con enclave sicuri estende la funzionalità esistente per abilitare funzionalità più avanzate per i dati sensibili, mantenendo i dati riservati.

Per altre informazioni, vedere Always Encrypted (motore di database) e Always Encrypted con enclave sicure.

Prerequisiti

Configurare Always Encrypted nel database. Questo processo implica il provisioning di chiavi Always Encrypted e la configurazione della crittografia per le colonne di database selezionate. Se non è presente un database in cui è configurato Always Encrypted, seguire le istruzioni fornite nella Esercitazione: attività iniziali con Always Encrypted. In particolare, il database deve contenere le definizioni dei metadati per una chiave master della colonna, una chiave di crittografia della colonna e una tabella contenente una o più colonne crittografate con tale chiave di crittografia.

Se si usa Always Encrypted con enclave sicure, vedere Sviluppare applicazioni usando Always Encrypted con enclave sicure per altri prerequisiti.

Abilitazione di Always Encrypted in un'applicazione ODBC

Il modo più semplice per abilitare la crittografia dei parametri e la decrittografia delle colonne crittografate dei set di risultati consiste nell'impostare il valore della parola chiave della stringa di connessione ColumnEncryption su Abilitato. Il codice seguente rappresenta un esempio di stringa di connessione che abilita Always Encrypted:

SQLWCHAR *connString = L"Driver={ODBC Driver 18 for SQL Server};Server={myServer};Encrypt=yes;Trusted_Connection=yes;ColumnEncryption=Enabled;";

Always Encrypted può anche essere abilitato nella configurazione DSN, usando la stessa chiave e lo stesso valore (di cui verrà eseguito l'override dall'impostazione della stringa di connessione, se presente) o a livello di codice con l'attributo di pre-connessione SQL_COPT_SS_COLUMN_ENCRYPTION. Impostandolo in questo modo esegue l'override del valore impostato nella stringa di connessione o DSN:

 SQLSetConnectAttr(hdbc, SQL_COPT_SS_COLUMN_ENCRYPTION, (SQLPOINTER)SQL_COLUMN_ENCRYPTION_ENABLE, 0);

Una volta abilitato per la connessione, il comportamento di Always Encrypted può essere regolato per singole query. Per altre informazioni, vedere Controllo dell'impatto di Always Encrypted sulle prestazioni più avanti.

L'abilitazione di Always Encrypted non è sufficiente per l'esito positivo della crittografia o della decrittografia. È anche necessario verificare che:

  • L'applicazione abbia le autorizzazioni di database VIEW ANY COLUMN MASTER KEY DEFINITION e VIEW ANY COLUMN ENCRYPTION KEY DEFINITION , necessarie per accedere ai metadati sulle chiavi Always Encrypted nel database. Per informazioni dettagliate, vedere Autorizzazioni per il database.

  • L'applicazione possa accedere alla chiave master della colonna che protegge le chiavi di crittografia della colonna per le colonne crittografate sottoposte a query. Questo comportamento dipende dal provider dell'archivio chiavi in cui è archiviata la chiave master di colonna. Per altre informazioni, vedere Uso degli archivi delle chiavi master delle colonne.

Abilitazione di Always Encrypted con enclave sicuri

Nota

Per usare Always Encrypted con enclave sicure in Linux e macOS, è necessario OpenSSL versione 1.0.1 o successiva.

A partire dalla versione 17.4, il driver supporta Always Encrypted con enclave sicure. Per abilitare l'uso dell'enclave durante la connessione a un database, impostare la parola chiave della stringa di connessione, l'attributo di connessione o la chiave DSN ColumnEncryption sul valore seguente: <attestation protocol>,<attestation URL>, dove:

  • <attestation protocol>: specifica un protocollo usato per l'attestazione dell'enclave.

    • Se si usano SQL Server e il servizio Sorveglianza host (HGS), <attestation protocol> deve essere VBS-HGS.
    • Se si usano il database SQL di Azure e l'attestazione di Microsoft Azure, <attestation protocol> deve essere SGX-AAS.
    • Se non è necessaria l'attestazione, <attestation-protocol> deve essere VBS-NONE. (Versione 18.1+)
  • <attestation URL>: specifica un URL di attestazione (endpoint di servizio di attestazione). È necessario ottenere un URL di attestazione per l'ambiente dall'amministratore del servizio di attestazione.

Esempi di stringhe di connessione che consentono di abilitare i calcoli dell'enclave per una connessione al 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"
    
  • Database SQL di Azure:

    "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/"
    
  • Nessuna attestazione (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"
    

Se il server e il servizio di attestazione sono configurati correttamente, insieme alle chiavi master di colonna e alle chiavi di crittografia di colonna con supporto per le enclave per le colonne crittografate, è possibile eseguire query che usano l'enclave, ad esempio la crittografia sul posto e i calcoli avanzati, in aggiunta alla funzionalità esistente fornita da Always Encrypted. Per altre informazioni, vedere Configurare Always Encrypted con enclave sicure.

Recupero e modifica dei dati nelle colonne crittografate

Dopo aver abilitato Always Encrypted in una connessione è possibile usare le API ODBC standard. Le API ODBC possono recuperare o modificare i dati nelle colonne di database crittografate. Per altre informazioni, vedere la documentazione seguente:

L'applicazione deve avere le autorizzazioni database necessarie ed essere in grado di accedere alla chiave master della colonna. Il driver crittografa quindi tutti i parametri di query destinati alle colonne crittografate. Il driver decrittografa anche i dati recuperati dalle colonne crittografate. Il driver esegue tutte le operazioni di crittografia e decrittografia senza alcuna assistenza da parte del codice sorgente. Per il programma è come se le colonne non fossero crittografate.

Se Always Encrypted non è abilitato, le query con parametri destinati alle colonne crittografate avranno esito negativo. I dati possono essere comunque recuperati dalle colonne crittografate, a condizione che non presentino parametri destinati alle colonne crittografate. Il driver tuttavia non cerca di eseguire la decrittografia e l'applicazione riceve i dati binari crittografati, sotto forma di matrici di byte.

La tabella seguente riepiloga il comportamento delle query, a seconda che la funzionalità Always Encrypted sia abilitata o meno:

Caratteristica della query Always Encrypted è abilitato e l'applicazione può accedere alle chiavi e ai metadati delle chiavi Always Encrypted è abilitato e l'applicazione non può accedere alle chiavi o ai metadati delle chiavi Always Encrypted è disabilitato
Parametri destinati alle colonne crittografate. I valori dei parametri vengono crittografati in modo trasparente. Error Error
Recupero di dati dalle colonne crittografate, senza parametri destinati alle colonne crittografate. I risultati delle colonne vengono decrittografati in modo trasparente. L'applicazione riceve i valori di colonna in testo non crittografato. Error I risultati delle colonne crittografate non vengono decrittografati. L'applicazione riceve i valori crittografati come matrici di byte.

Gli esempi seguenti illustrano il recupero e la modifica dei dati nelle colonne crittografate. Negli esempi si presuppone una tabella con lo schema seguente. Le colonne SSN e BirthDate sono crittografate.

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

Esempio di inserimento dati

Questo esempio illustra come inserire una riga nella tabella Patients. Osservare i seguenti dettagli:

  • Il codice di esempio non contiene alcun elemento specifico per la crittografia. Il driver rileva automaticamente e crittografa i valori dei parametri SSN e data, che puntano a colonne crittografate. In questo modo la crittografia diventa trasparente per l'applicazione.

  • I valori inseriti nelle colonne di database, incluse quelle crittografate, vengono passati come parametri associati (vedere Funzione SQLBindParameter). I parametri sono facoltativi quando si inviano valori a colonne non crittografate (sebbene siano comunque consigliati per prevenire attacchi SQL injection), mentre sono obbligatori per i valori destinati a colonne crittografate. Se i valori inseriti nella colonna SSN o BirthDate sono stati passati come valori letterali incorporati nell'istruzione di query, la query avrà esito negativo perché il driver non prova a crittografare o a elaborare in altro modo i valori letterali nelle query. Di conseguenza, il server li rifiuterà come incompatibili con le colonne crittografate.

  • Il tipo SQL del parametro inserito nella colonna SSN è impostato su SQL_CHAR, che esegue il mapping al tipo di dati di SQL Server char (rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 11, 0, (SQLPOINTER)SSN, 0, &cbSSN);). Se il tipo del parametro è stato impostato su SQL_WCHAR, che esegue il mapping a nchar, la query avrà esito negativo perché Always Encrypted non supporta le conversioni sul lato server da valori nchar crittografati a valori char crittografati. Per informazioni sui mapping dei tipi di dati, vedere l'appendice D della guida di riferimento per programmatori ODBC sui tipi di dati.

    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);

Esempio di recupero dati in formato testo non crittografato

L'esempio seguente illustra come filtrare i dati in base ai valori crittografati e recuperare i dati in testo non crittografato dalle colonne crittografate. Osservare i seguenti dettagli:

  • Il valore usato nella clausola WHERE per filtrare la colonna SSN deve essere passato usando SQLBindParameter, in modo che il driver possa crittografarlo in modo trasparente prima dell'invio al server.

  • Tutti i valori stampati dal programma saranno in testo non crittografato, perché il driver decrittografa in modo trasparente i dati recuperati dalle colonne SSN e BirthDate.

Nota

Le query possono eseguire confronti di uguaglianza nelle colonne crittografate solo se la crittografia è deterministica, o se è attivata l'enclave sicura.

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);        
}

Esempio di recupero dati in formato testo crittografato

Se Always Encrypted non è abilitato, una query può comunque recuperare dati dalle colonne crittografate, a condizione che non presenti parametri destinati alle colonne crittografate.

L'esempio seguente illustra come recuperare dati crittografati binari da colonne crittografate. Osservare i seguenti dettagli:

  • Poiché la funzionalità Always Encrypted non è abilitata nella stringa di connessione, la query restituirà i valori crittografati di SSN e BirthDate come matrici di byte (il programma converte i valori in stringhe).
  • Una query che recupera dati dalle colonne crittografate con Always Encrypted disabilitato può avere parametri, a condizione che nessuno dei parametri sia destinato a una colonna crittografata. La query precedente filtra in base alla colonna LastName, non è crittografata nel database. Se la query avesse filtrato per SSN o data di nascita, avrebbe avuto esito negativo.
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);        
}

Crittografia di Money/SmallMoney

A partire dalla versione 17.7 del driver, è possibile usare Always Encrypted con MONEY e SMALLMONEY. È tuttavia necessario eseguire alcuni passaggi aggiuntivi. Quando si inseriscono valori in colonne MONEY o SMALLMONEY crittografate, usare uno dei tipi C seguenti:

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

e un tipo SQL SQL_NUMERIC o SQL_DOUBLE (la precisione può andare persa quando si usa questo tipo).

Associazione della variabile

Ogni volta che si associa una variabile MONEY/SMALLMONEY in una colonna crittografata, è necessario impostare i campi descrittori seguenti:

// 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);

Come evitare i problemi comuni quando si eseguono query su colonne crittografate

Questa sezione descrive categorie di errori comuni che si verificano quando si eseguono query su colonne crittografate da applicazioni ODBC e contiene alcune linee guida su come correggere tali errori.

Errori di conversione dei tipi di dati non supportati

Always Encrypted supporta alcune conversioni per i tipi di dati crittografati. Per l'elenco dettagliato delle conversioni dei tipi supportati, vedere Always Encrypted (motore di database). Per evitare errori di conversione dei tipi di dati, assicurarsi di osservare quanto riportato di seguito quando si usa la funzione SQLBindParameter con parametri destinati alle colonne crittografate:

  • Il tipo SQL del parametro è esattamente lo stesso del tipo della colonna di destinazione oppure è supportata la conversione dal tipo SQL al tipo della colonna.

  • La precisione e la scala dei parametri destinati alle colonne dei tipi di dati decimal e numeric di SQL Server sono uguali a quelle configurate per la colonna di destinazione.

  • La precisione dei parametri destinati alle colonne con tipo di dati datetime2, datetimeoffset o time di SQL Server non è maggiore della precisione per la colonna di destinazione nelle query che modificano la colonna di destinazione.

Errori causati dal passaggio di testo non crittografato anziché di valori crittografati

Qualsiasi valore destinato a una colonna crittografata deve essere crittografato prima di essere inviato al server. Il tentativo di inserire, modificare o filtrare in base a un valore di testo non crittografato in una colonna crittografata genererà un errore. Per evitare tali errori, verificare che:

  • Always Encrypted sia abilitato (nel DSN, nella stringa di connessione, prima della connessione impostando l'attributo di connessione SQL_COPT_SS_COLUMN_ENCRYPTION per una connessione specifica o l'attributo di istruzione SQL_SOPT_SS_COLUMN_ENCRYPTION per un'istruzione specifica).

  • Sia usato SQLBindParameter per inviare i dati destinati alle colonne crittografate. L'esempio seguente illustra una query che filtra in modo errato in base a un valore letterale o costante in una colonna crittografata (SSN), anziché passare il valore letterale come argomento a SQLBindParameter.

string queryText = "SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN='795-73-9838'";

Precauzioni quando si usano SQLSetPos e SQLMoreResults

SQLSetPos

L'API SQLSetPos consente a un'applicazione aggiornare le righe in un set di risultati usando buffer che sono stati associati con SQLBindCol e in cui precedentemente sono stati recuperati dati di riga. A causa del comportamento di riempimento asimmetrico dei tipi crittografati a lunghezza fissa, è possibile che i dati di queste colonne vengano modificati in modo imprevisto quando si eseguono aggiornamenti in altre colonne della riga. Con Always Encrypted, i valori dei caratteri a lunghezza fissa vengono riempiti se il valore è inferiore alle dimensioni del buffer.

Per mitigare questo comportamento, usare il flag SQL_COLUMN_IGNORE per ignorare le colonne che non verranno aggiornate come parte di SQLBulkOperations e quando si usa SQLSetPos per gli aggiornamenti basati sul cursore. Tutte le colonne che non vengono modificate direttamente dall'applicazione devono essere ignorate, sia per le prestazioni sia per evitare il troncamento delle colonne associate a un buffer inferiore alle dimensioni effettive (DB). Per altre informazioni, vedere la guida di riferimento della funzione SQLSetPos.

SQLMoreResults e SQLDescribeCol

I programmi applicativi possono chiamare SQLDescribeCol per restituire metadati sulle colonne nelle istruzioni preparate. Se la funzionalità Always Encrypted è abilitata, la chiamata di SQLMoreResultsprima della chiamata di SQLDescribeCol comporta l'esecuzione di una chiamata di sp_describe_first_result_set, che non restituisce correttamente i metadati in formato testo non crittografato per le colonne crittografate. Per evitare questo problema, chiamare SQLDescribeCol nelle istruzioni preparate prima di chiamare SQLMoreResults.

Controllo dell'impatto di Always Encrypted sulle prestazioni

Considerato che Always Encrypted è una tecnologia di crittografia lato client, la maggior parte del sovraccarico delle prestazioni si verifica sul lato client, non nel database. A parte il costo delle operazioni di crittografia e decrittografia, le altre origini di sovraccarico delle prestazioni sul lato client sono le seguenti:

  • Round trip aggiuntivi al database per recuperare metadati per i parametri di query.

  • Chiamate a un archivio delle chiavi master delle colonne per accedere alla chiave master di una colonna.

Questa sezione descrive le ottimizzazioni delle prestazioni predefinite in ODBC Driver for SQL Server e come controllare l'impatto sulle prestazioni esercitato dai due fattori descritti.

Controllo dei round trip per recuperare i metadati per i parametri di query

Se la funzionalità Always Encrypted è abilitata per una connessione, per impostazione predefinita il driver chiamerà sys.sp_describe_parameter_encryption per ogni query con parametri, passando l'istruzione di query (senza i valori dei parametri) a SQL Server. Questa stored procedure analizza l'istruzione di query per verificare se sono presenti parametri da crittografare e, in tal caso, restituisce le informazioni relative alla crittografia per ogni parametro in modo da consentire al driver di crittografarli. Il comportamento descritto in precedenza assicura all'applicazione client un elevato livello di trasparenza: non è necessario che l'applicazione e lo sviluppatore dell'applicazione sappiano quali query accedono alle colonne crittografate, a condizione che i valori destinati alle colonne crittografate vengano passati al driver nei parametri.

A partire dalla versione 17.6, il driver memorizza nella cache anche i metadati di crittografia per le istruzioni preparate, con un conseguente miglioramento delle prestazioni grazie al fatto che le chiamate successive di SQLExecute non richiedono un round trip aggiuntivo per recuperare i metadati di crittografia.

Comportamento di Always Encrypted per le singole istruzioni

Per controllare l'impatto sulle prestazioni del recupero dei metadati di crittografia per le query con parametri, è possibile modificare il comportamento di Always Encrypted per singole query se è stato abilitato per la connessione. In questo modo, è possibile assicurarsi che sys.sp_describe_parameter_encryption venga richiamato solo per le query con parametri destinati a colonne crittografate. Si noti, tuttavia, che in tal modo si riduce la trasparenza della crittografia. Se si esegue la crittografia di colonne aggiuntive nel database, può essere necessario modificare il codice dell'applicazione per allinearlo alle modifiche dello schema.

Per controllare il comportamento di Always Encrypted di un'istruzione, chiamare SQLSetStmtAttr per impostare l'attributo di istruzione SQL_SOPT_SS_COLUMN_ENCRYPTION su uno dei valori seguenti:

Valore Descrizione
SQL_CE_DISABLED (0) Always Encrypted è disabilitato per l'istruzione
SQL_CE_RESULTSETONLY (1) Solo decrittografia. I set di risultati e i valori restituiti sono decrittografati e i parametri non sono crittografati
SQL_CE_ENABLED (3) Always Encrypted è abilitato e usato sia per i parametri che per i risultati

I nuovi handle di istruzione creati da una connessione con Always Encrypted abilitato vengono impostati su SQL_CE_ENABLED per impostazione predefinita. Gli handle creati da una connessione con la funzionalità Always Encrypted disabilitata vengono impostati su SQL_CE_DISABLED per impostazione predefinita (e per questi handle non è possibile abilitare Always Encrypted).

Se la maggior parte delle query di un'applicazione client accede a colonne crittografate, è consigliabile applicare le indicazioni seguenti:

  • Impostare la parola chiave della stringa di connessione ColumnEncryption su Enabled.

  • Impostare l'attributo SQL_SOPT_SS_COLUMN_ENCRYPTION su SQL_CE_DISABLED nelle istruzioni che non accedono alle colonne crittografate. Questa impostazione disabilita sia la chiamata di sys.sp_describe_parameter_encryption sia i tentativi di decrittografare i valori nel set di risultati.

  • Impostare l'attributo SQL_SOPT_SS_COLUMN_ENCRYPTION su SQL_CE_RESULTSETONLY nelle istruzioni che non includono parametri che richiedono la crittografia, ma recuperano dati da colonne crittografate. Questa impostazione disabilita la chiamata di sys.sp_describe_parameter_encryption e la crittografia dei parametri. I risultati contenenti colonne crittografate continueranno a essere decrittografati.

  • Usare istruzioni preparate per le query che verranno eseguite più di una volta. Preparare la query con SQLPrepare e salvare l'handle di istruzione riutilizzandolo con SQLExecute ogni volta che viene eseguito. Questo metodo rappresenta l'approccio preferito per le prestazioni anche quando non sono presenti colonne crittografate e consente al driver di sfruttare i metadati memorizzati nella cache.

Impostazioni di sicurezza di Always Encrypted

Forzare la crittografia di colonna

Per applicare la crittografia di un parametro, impostare il campo del descrittore parametri di implementazione SQL_CA_SS_FORCE_ENCRYPT tramite una chiamata alla funzione SQLSetDescField. Un valore diverso da zero fa sì che il driver restituisca un errore quando non vengono restituiti metadati di crittografia per il parametro associato.

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);   

Se SQL Server indica al driver che non è necessario crittografare il parametro, le query che usano tale parametro avranno esito negativo. Questo comportamento fornisce protezione aggiuntiva contro attacchi alla sicurezza in cui un'istanza di SQL Server compromessa fornisce al client metadati di crittografia non corretti, causando la divulgazione dei dati.

Memorizzazione nella cache delle chiavi di crittografia della colonna

Per ridurre il numero di chiamate a un archivio chiavi master della colonna per decrittografare le chiavi di crittografia della colonna, il driver memorizza nella cache le chiavi di crittografia della colonna di testo non crittografato. La cache delle chiavi di crittografia della colonna è globale per il driver e non è associata ad alcuna connessione. Dopo aver ricevuto la chiave ECEK dai metadati del database, il driver prova prima di tutto a trovare la chiave di crittografia della colonna di testo non crittografato corrispondente al valore della chiave crittografata nella cache. Il driver chiama l'archivio chiavi contenente la chiave master di colonna solo se non riesce a trovare la chiave di crittografia di colonna in formato testo non crittografato corrispondente nella cache.

Nota

In ODBC Driver for SQL Server le voci nella cache vengono rimosse dopo un timeout di due ore. Questo comportamento significa che per una determinata chiave ECEK, il driver contatta l'archivio chiavi una sola volta nel corso della durata dell'applicazione o ogni due ore, a seconda di quale sia il valore più basso.

A partire da ODBC Driver 17.1 for SQL Server, il timeout della cache delle chiavi di crittografia della colonna può essere regolato usando l'attributo di connessione SQL_COPT_SS_CEKCACHETTL, che specifica il numero di secondi in cui una chiave di crittografia della colonna rimarrà nella cache. A causa della natura globale della cache, questo attributo può essere modificato da qualsiasi handle di connessione valido per il driver. Quando il valore TTL della cache viene ridotto, vengono rimosse anche le chiavi di crittografia di colonna esistenti che potrebbero superare il nuovo valore TTL. Se il valore è 0, le chiavi di crittografia di colonna non vengono memorizzate nella cache.

Percorsi delle chiavi attendibili

A partire da ODBC Driver 17.1 for SQL Server, l'attributo di connessione SQL_COPT_SS_TRUSTEDCMKPATHS consente a un'applicazione di richiedere che le operazioni Always Encrypted usino solo un elenco specificato di chiavi di crittografia della colonna, identificate dai relativi percorsi delle chiavi. Per impostazione predefinita, questo attributo è NULL, che significa che il driver accetta qualsiasi percorso della chiave. Per usare questa funzionalità, impostare SQL_COPT_SS_TRUSTEDCMKPATHS in modo che punti a una stringa di caratteri "wide" delimitati da Null e con terminazione Null che elenca i percorsi delle chiavi consentiti. La memoria a cui fa riferimento questo attributo deve rimanere valida durante le operazioni di crittografia o decrittografia usando l'handle di connessione in cui è impostato, in base a cui il driver controllerà se il percorso della chiave master di colonna come specificato dai metadati del server è presente in questo elenco, senza distinzione tra maiuscole e minuscole. Se il percorso della chiave master di colonna non è presente nell'elenco, l'operazione ha esito negativo. L'applicazione può modificare il contenuto della memoria a cui punta questo attributo, per modificare l'elenco di chiavi di crittografia della colonna attendibili, senza impostare nuovamente l'attributo.

Uso degli archivi delle chiavi master delle colonne

Per crittografare o decrittografare i dati, il driver deve ottenere una chiave di crittografia della colonna configurata per la colonna di destinazione. Le chiavi di crittografia di colonna vengono archiviate in formato crittografato (ECEK) nei metadati del database. Ogni chiave di crittografia della colonna ha una chiave master della colonna corrispondente che è stata usata per crittografarla. I metadati del database non archiviano la chiave master di colonna, ma includono solo il nome dell'archivio chiavi e le informazioni che l'archivio chiavi può usare per trovare la chiave master di colonna.

Per ottenere il valore di testo non crittografato di una chiave ECEK, il driver ottiene prima di tutto i metadati relativi sia alla chiave di crittografia della colonna che alla chiave master della colonna corrispondente e quindi usa queste informazioni per contattare l'archivio chiavi contenente la chiave master della colonna e richiede di decrittografare la chiave ECEK. Il driver comunica con un archivio chiavi usando un provider dell'archivio chiavi.

Provider di archivi chiavi predefiniti

ODBC Driver for SQL Server viene fornito con i provider di archivi chiavi predefiniti seguenti:

Nome Descrizione Nome del provider (metadati) Disponibilità
Azure Key Vault Archivia le chiavi master della colonna in un'istanza di Azure Key Vault AZURE_KEY_VAULT Windows, macOS, Linux
Archivio certificati Windows Archivia le chiavi master della colonna in locale nell'archivio chiavi Windows MSSQL_CERTIFICATE_STORE Finestre
  • È necessario che l'utente (o l'amministratore del database) verifichi che il nome del provider, configurato nei metadati della chiave master della colonna, sia corretto e che il percorso della chiave master sia conforme al formato del percorso della chiave per il provider specificato. È consigliabile configurare le chiavi usando strumenti come SQL Server Management Studio, che genera automaticamente nomi di provider e percorsi di chiave validi quando viene eseguita l'istruzione CREATE COLUMN MASTER KEY (Transact-SQL).

  • Verificare che l'applicazione possa accedere alla chiave nell'archivio chiavi. Per questo processo può essere necessario concedere all'applicazione l'accesso alla chiave e/o all'archivio chiavi, a seconda dell'archivio, oppure eseguire altri passaggi di configurazione specifici dell'archivio chiavi. Per accedere, ad esempio, a un'istanza di Azure Key Vault, è necessario fornire le credenziali corrette all'archivio chiavi.

Uso del provider Azure Key Vault

Azure Key Vault (AKV) rappresenta una scelta valida per archiviare e gestire le chiavi master delle colonne per Always Encrypted, soprattutto se le applicazioni sono ospitate in Azure. ODBC Driver for SQL Server in Linux, macOS e Windows include un provider di archivio chiavi master della colonna predefinito per Azure Key Vault. Per altre informazioni sulla configurazione di un'istanza di Azure Key Vault per Always Encrypted, vedere Azure Key Vault - Istruzioni dettagliate, Introduzione a Key Vault e Creazione di chiavi master di colonna in Azure Key Vault.

Nota

Il driver ODBC supporta solo l'autenticazione Azure Key Vault direttamente con Microsoft Entra ID (in precedenza, Azure Active Directory). Se si usa l'autenticazione di Microsoft Entra per Azure Key Vault e la configurazione di richiede l'autenticazione in un endpoint Active Directory Federation Services, l'autenticazione potrebbe non riuscire. In Linux e macOS, per la versione del driver 17.2 e versioni successive, libcurl è necessario per usare questo provider, ma non è una dipendenza esplicita poiché altre operazioni con il driver non lo richiedono. Se si verifica un errore relativo a libcurl, verificare che sia installato.

Il driver supporta l'autenticazione ad Azure Key Vault usando i seguenti tipi di credenziali:

  • Nome utente/Password: con questo metodo, le credenziali sono rappresentate dal nome di un utente di Microsoft Entra e dalla relativa password.

  • ID client/Segreto: con questo metodo, le credenziali sono rappresentate da un ID client dell'applicazione e un segreto dell'applicazione.

  • Identità gestita (17.5.2 +): assegnata dal sistema o dall'utente. Per altre informazioni, vedere Identità gestite per le risorse di Azure.

  • Azure Key Vault Interactive (driver Windows 17.7+): con questo metodo, le credenziali vengono autenticate tramite Microsoft Entra ID con ID di accesso.

Per consentire al driver di usare chiavi master della colonna archiviate in Azure Key Vault per la crittografia di colonna, usare le seguenti parole chiave costituite solo dalla stringa di connessione:

Tipo di credenziali KeyStoreAuthentication KeyStorePrincipalId KeyStoreSecret
Nome utente e password KeyVaultPassword Nome entità utente Password
ID client/Segreto KeyVaultClientSecret Client ID Segreto
Identità gestita KeyVaultManagedIdentity ID oggetto (facoltativo, solo per assegnata dall'utente) (non specificato)
Azure Key Vault Interactive KeyVaultInteractive (non impostato) (non impostato)

A partire dalla versione 17.8, è possibile modificare KeystoreAuthentication e KeystorePrincipalId usando l'interfaccia utente di configurazione DSN nello strumento di amministrazione dell'origine dati ODBC.

Esempi di stringhe di connessione

Le stringhe di connessione seguenti illustrano come eseguire l'autenticazione ad Azure Key Vault con i due tipi di credenziali:

ID client/segreto
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultClientSecret;KeyStorePrincipalId=<clientId>;KeyStoreSecret=<secret>"
Nome utente/password
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultPassword;KeyStorePrincipalId=<username>;KeyStoreSecret=<password>"
Identità gestita (assegnata dal sistema)
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultManagedIdentity"
Identità gestita (assegnata dall'utente)
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultManagedIdentity;KeyStorePrincipalId=<objectID>"
Azure Key Vault Interactive
"DRIVER=ODBC Driver 18 for SQL Server;SERVER=myServer;Encrypt=yes;Trusted_Connection=Yes;DATABASE=myDB;ColumnEncryption=Enabled;KeyStoreAuthentication=KeyVaultInteractive;UID=<userID>;PWD=<password>"

Non sono necessarie altre modifiche all'applicazione ODBC per usare Azure Key Vault per l'archiviazione di chiavi master della colonna.

Nota

Il driver contiene un elenco di endpoint AKV attendibili. A partire dalla versione del driver 17.5.2, questo elenco è configurabile: impostare la proprietà AKVTrustedEndpoints nel driver o nella chiave del Registro di sistema ODBCINST.INI o ODBC.INI di DSN (Windows) oppure nella sezione del file odbcinst.ini o odbc.ini (Linux/macOS) in un elenco delimitato da punti e virgola. L'impostazione nel sistema DSN ha la precedenza su un'impostazione nel driver. Se il valore inizia con un punto e virgola, estende l'elenco predefinito. In caso contrario, sostituisce l'elenco predefinito. L'elenco predefinito (fino alla versione 17.5) è vault.azure.net;vault.azure.cn;vault.usgovcloudapi.net;vault.microsoftazure.de. A partire dalla versione 17.7, l'elenco include anche managedhsm.azure.net;managedhsm.azure.cn;managedhsm.usgovcloudapi.net;managedhsm.microsoftazure.de.

Nota

Il provider di Azure Key Vault integrato nel driver ODBC supporta insiemi di credenziali e moduli HSM gestiti in Azure Key Vault.

Uso del provider per l'archivio certificati Windows

ODBC Driver for SQL Server in Windows include un provider di archivio chiavi master della colonna predefinito per l'archivio certificati Windows denominato MSSQL_CERTIFICATE_STORE. Questo provider non è disponibile in macOS o Linux. Con questo provider, la chiave master di colonna viene archiviata in locale nel computer client e non è necessaria alcuna configurazione aggiuntiva da parte dell'applicazione per usarla con il driver. Tuttavia, l'applicazione deve avere accesso al certificato e alla relativa chiave privata nell'archivio. Per altre informazioni, vedere Creare e archiviare chiavi master della colonna (Always Encrypted).

Uso di provider di archivi chiavi personalizzati

ODBC Driver for SQL Server supporta anche i provider di archivi chiavi personalizzati di terze parti tramite l'interfaccia CEKeystoreProvider. Questa funzionalità consente a un'applicazione di caricare e configurare i provider di archivi chiavi, nonché eseguire query su di essi, in modo che possano essere usati dal driver per accedere alle colonne crittografate. Le applicazioni possono anche interagire direttamente con un provider di archivi chiavi per crittografare le chiavi di crittografia di colonna per l'archiviazione in SQL Server ed eseguire attività che vanno oltre l'accesso alle colonne crittografate con ODBC. Per altre informazioni, vedere Provider di archivi chiavi personalizzati.

Due attributi di connessione vengono usati per interagire con i provider di archivi chiavi personalizzati, Sono:

  • SQL_COPT_SS_CEKEYSTOREPROVIDER

  • SQL_COPT_SS_CEKEYSTOREDATA

Il primo viene usato per caricare ed enumerare i provider di archivi chiavi caricati, mentre il secondo consente le comunicazioni tra il provider e l'applicazione. Questi attributi di connessione possono essere usati in qualsiasi momento, prima o dopo aver stabilito una connessione, in quanto l'interazione tra applicazione e provider non comporta la comunicazione con SQL Server. Tuttavia, poiché il driver non è stato ancora caricato, l'impostazione e il recupero di questi attributi prima della connessione ne causerà l'elaborazione da parte di Gestione driver e potrebbe non restituire i risultati previsti.

Caricamento di un provider di archivi chiavi

L'impostazione dell'attributo di connessione SQL_COPT_SS_CEKEYSTOREPROVIDER consente a un'applicazione client di caricare una libreria di provider, rendendo disponibili per l'uso i provider di archivi chiavi in essa contenuti.

SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
Argomento Descrizione
ConnectionHandle [Input] Handle di connessione. Deve essere un handle di connessione valido, ma i provider caricati tramite un handle di connessione sono accessibili da qualsiasi altro provider nello stesso processo.
Attribute [Input] Attributo da impostare: costante SQL_COPT_SS_CEKEYSTOREPROVIDER.
ValuePtr [Input] Puntatore a una stringa di caratteri con terminazione Null che specifica il nome file della libreria di provider. Per SQLSetConnectAttrA, questo valore è una stringa ANSI (multibyte). Per SQLSetConnectAttrW, questo valore è una stringa Unicode (wchar_t).
StringLength [Input] Lunghezza della stringa ValuePtr o SQL_NTS.

Il driver cerca di caricare la libreria identificata dal parametro ValuePtr usando il meccanismo di caricamento della libreria dinamica definito dalla piattaforma (dlopen() in Linux e macOS, LoadLibrary() in Windows) e aggiunge tutti i provider in essa definiti all'elenco di provider noti al driver. È possibile che si verifichino gli errori seguenti:

Errore Descrizione
CE203 Non è stato possibile caricare la libreria dinamica.
CE203 Il simbolo "CEKeyStoreProvider" esportato non è stato trovato nella libreria.
CE203 Uno o più provider nella libreria sono già caricati.

SQLSetConnectAttr restituisce i valori standard di esito negativo o positivo e sono disponibili informazioni aggiuntive per eventuali errori che si sono verificati tramite il meccanismo diagnostico ODBC standard.

Nota

Il programmatore dell'applicazione deve assicurarsi che tutti i provider personalizzati vengano caricati prima che una query che li richieda venga inviata tramite qualsiasi connessione. In caso contrario, viene generato l'errore seguente:

Errore Descrizione
CE200 Il provider dell'archivio chiavi %1 non è stato trovato. Assicurarsi che sia stata caricata la libreria del provider dell'archivio chiavi appropriata.

Nota

I responsabili dell'implementazione dei provider di archivi chiavi devono evitare l'uso di MSSQL nel nome dei propri provider personalizzati. Questo termine è riservato esclusivamente per l'uso da parte di Microsoft e può causare conflitti con i provider predefiniti futuri. L'uso di questo termine nel nome di un provider personalizzato può causare un avviso ODBC.

Recupero dell'elenco di provider caricati

Il recupero di questo attributo di connessione consente a un'applicazione client di determinare i provider di archivi chiavi attualmente caricati nel driver (inclusi quelli predefiniti). Questo processo può essere eseguito solo dopo la connessione.

SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StringLengthPtr);
Argomento Descrizione
ConnectionHandle [Input] Handle di connessione. Deve essere un handle di connessione valido, ma i provider caricati tramite un handle di connessione sono accessibili da qualsiasi altro provider nello stesso processo.
Attribute [Input] Attributo da recuperare: costante SQL_COPT_SS_CEKEYSTOREPROVIDER.
ValuePtr [Output] Puntatore alla memoria in cui restituire il successivo nome del provider caricato.
BufferLength [Input] Lunghezza del buffer ValuePtr.
StringLengthPtr [Output] Puntatore a un buffer in cui restituire il numero totale di byte (escluso il carattere di terminazione Null) disponibili da restituire in *ValuePtr. Se ValuePtr è un puntatore Null, non viene restituita alcuna lunghezza. Se il valore dell'attributo è una stringa di caratteri e il numero di byte disponibili da restituire è maggiore di BufferLength meno la lunghezza del carattere di terminazione Null, i dati in *ValuePtr vengono troncati a BufferLength meno la lunghezza del carattere di terminazione Null e il driver aggiunge una terminazione Null.

Per consentire il recupero dell'intero elenco, ogni operazione Get restituisce il nome del provider corrente e incrementa un contatore interno a quello successivo. Quando questo contatore raggiunge la fine dell'elenco, viene restituita una stringa vuota ("") e il contatore viene reimpostato. Le operazioni Get successive proseguono quindi nuovamente dall'inizio dell'elenco.

Comunicazione con i provider di archivi chiavi

L'attributo di connessione SQL_COPT_SS_CEKEYSTOREDATA consente a un'applicazione client di comunicare con i provider di archivi chiavi caricati per la configurazione di parametri aggiuntivi, materiale per le chiavi e così via. La comunicazione tra un'applicazione client e un provider segue un protocollo di richiesta-risposta semplice, basato su richieste Get e Set mediante questo attributo di connessione. La comunicazione viene avviata solo dall'applicazione client.

Nota

A causa della natura delle chiamate ODBC a cui risponde CEKeyStoreProvider (SQLGet/SetConnectAttr), l'interfaccia ODBC supporta solo l'impostazione dei dati alla risoluzione del contesto di connessione.

L'applicazione comunica con i provider di archivi chiavi tramite il driver tramite la struttura CEKeystoreData:

typedef struct CEKeystoreData {
wchar_t *name;
unsigned int dataSize;
char data[];
} CEKEYSTOREDATA;
Argomento Descrizione
name [Input] Dopo Set, il nome del provider a cui vengono inviati i dati. Ignorato dopo Get. Stringa di caratteri "wide" con terminazione Null.
dataSize [Input] Dimensioni della matrice di dati che segue la struttura.
data [InOut] Dopo Set, i dati da inviare al provider. Può trattarsi di dati arbitrari. Il driver non fa alcun tentativo di interpretarli. Dopo Get, il buffer per ricevere i dati letti dal provider.

Scrittura di dati in un provider

Una chiamata a SQLSetConnectAttr con l'attributo SQL_COPT_SS_CEKEYSTOREDATA scrive un "pacchetto" di dati nel provider dell'archivio chiavi specificato.

SQLRETURN SQLSetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
Argomento Descrizione
ConnectionHandle [Input] Handle di connessione. Deve essere un handle di connessione valido, ma i provider caricati tramite un handle di connessione sono accessibili da qualsiasi altro provider nello stesso processo.
Attribute [Input] Attributo da impostare: costante SQL_COPT_SS_CEKEYSTOREDATA.
ValuePtr [Input] Puntatore a una struttura CEKeystoreData. Il campo del nome della struttura identifica il provider a cui sono destinati i dati.
StringLength [Input] Costante SQL_IS_POINTER

Informazioni più dettagliate sugli errori possono essere ottenute tramite SQLGetDiacRec.

Nota

Il provider può usare l'handle di connessione per associare i dati scritti a una connessione specifica, se è opportuno. Questa funzionalità è utile per implementare la configurazione in base alla connessione. È possibile anche ignorare il contesto della connessione e trattare i dati in modo identico indipendentemente dalla connessione usata per inviare i dati. Per altre informazioni, vedere Associazione del contesto.

Lettura di dati da un provider

Una chiamata a SQLGetConnectAttr con l'attributo SQL_COPT_SS_CEKEYSTOREDATA legge un "pacchetto" di dati dall'ultimo provider in cui sono stati scritti dati. Se non è presente, si verifica un errore nella sequenza della funzione. Si consiglia ai responsabili dell'implementazione di provider di archivi chiavi di supportare "scritture fittizie" di 0 byte come modo per selezionare il provider per le operazioni di lettura senza causare altri effetti collaterali, se è opportuno farlo.

SQLRETURN SQLGetConnectAttr( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StringLengthPtr);
Argomento Descrizione
ConnectionHandle [Input] Handle di connessione. Deve essere un handle di connessione valido, ma i provider caricati tramite un handle di connessione sono accessibili da qualsiasi altro provider nello stesso processo.
Attribute [Input] Attributo da recuperare: costante SQL_COPT_SS_CEKEYSTOREDATA.
ValuePtr [Output] Puntatore a una struttura CEKeystoreData in cui vengono inseriti i dati letti dal provider.
BufferLength [Input] Costante SQL_IS_POINTER
StringLengthPtr [Output] Puntatore a un buffer in cui restituire BufferLength. Se *ValuePtr è un puntatore Null, non viene restituita alcuna lunghezza.

Il chiamante deve garantire che venga allocato un buffer di lunghezza sufficiente dopo la struttura CEKEYSTOREDATA per il provider in cui scrivere. Al momento della restituzione, il relativo campo dataSize viene aggiornato con la lunghezza effettiva dei dati letti dal provider. Informazioni più dettagliate sugli errori possono essere ottenute tramite SQLGetDiacRec.

Questa interfaccia non presenta requisiti aggiuntivi per il formato dei dati trasferiti tra un'applicazione e un provider di archivi chiavi. Ogni provider può definire il proprio protocollo/formato di dati, a seconda delle esigenze.

Per un esempio di implementazione di un proprio provider dell'archivio chiavi, vedere Provider di archivi chiavi personalizzati.

Limitazioni del driver ODBC quando si usa Always Encrypted

Operazioni asincrone

Sebbene il driver ODBC consenta l'uso di operazioni asincrone con Always Encrypted, l'abilitazione di questa funzionalità ha un impatto sulle prestazioni. La chiamata a sys.sp_describe_parameter_encryption per determinare i metadati di crittografia per l'istruzione viene bloccata facendo sì che il driver attenda che il server restituisca i metadati prima di restituire SQL_STILL_EXECUTING.

Recuperare i dati in parti con SQLGetData

Prima di ODBC Driver 17 for SQL Server non era possibile recuperare i caratteri crittografati e le colonne di dati binari in parti con SQLGetData. Ora è possibile eseguire una sola chiamata a SQLGetData, con un buffer di lunghezza sufficiente per contenere i dati dell'intera colonna.

Inviare i dati in parti con SQLPutData

Prima di ODBC Driver 17.3 for SQL Server i dati per l'inserimento o il confronto non possono essere inviati in parti con SQLPutData. È possibile eseguire una sola chiamata a SQLPutData, con un buffer che contiene tutti i dati. Per l'inserimento di dati Long in colonne crittografate, usare l'API della copia bulk, descritta nella sezione successiva, con un file di dati di input.

Smallmoney e money crittografati

I parametri non possono fare riferimento alle colonne money o smallmoney crittografate, in quanto non esiste un tipo di dati ODBC specifico che esegue il mapping a questi tipi e si verificano quindi errori di conflitto del tipo di operando.

Copia bulk di colonne crittografate

A partire da ODBC Driver 17 for SQL Server, è possibile usare le funzioni di copia bulk di SQL e l'utilità bcp supportata con Always Encrypted. Sia il testo non crittografato (crittografato in inserimento e decrittografato in recupero) sia il testo crittografato (verbatim trasferito) possono essere inseriti e recuperati usando le API di copia bulk (bcp_*) e l'utilità bcp.

  • Per recuperare il testo crittografato nel formato varbinary(max) (ad esempio per il caricamento bulk in un database diverso), connettersi senza l'opzione ColumnEncryption, oppure impostarla su Disabled, ed eseguire un'operazione BCP OUT.

  • Per inserire e recuperare testo non crittografato e consentire al driver di eseguire la crittografia e la decrittografia in modo trasparente, impostare semplicemente ColumnEncryption su Enabled. In caso contrario, la funzionalità dell'API BCP rimane invariata.

  • Per inserire testo crittografato nel formato varbinary(max) (ad esempio il testo recuperato in precedenza), impostare l'opzione BCPMODIFYENCRYPTED su TRUE ed eseguire un'operazione BCP IN. Affinché i dati risultanti possano essere decrittografati, assicurarsi che la chiave di crittografia di colonna di destinazione corrisponda a quella da cui è stato originariamente ottenuto il testo crittografato.

Quando si usa l'utilità bcp: per controllare l'impostazione ColumnEncryption usare l'opzione -D e specificare un DSN che contiene il valore desiderato. Per inserire testo crittografato, assicurarsi che sia abilitata l'impostazione ALLOW_ENCRYPTED_VALUE_MODIFICATIONS dell'utente.

La tabella seguente fornisce un riepilogo delle azioni da eseguire quando si usa una colonna crittografata:

ColumnEncryption Direzione BCP Descrizione
Disabled OUT (al client) Recupera testo crittografato. Il tipo di dati osservati è varbinary(max).
Enabled OUT (al client) Recupera testo non crittografato. Il driver decrittograferà i dati della colonna.
Disabled IN (al server) Inserisce testo crittografato. Questa impostazione consente di spostare in modo non trasparente i dati crittografati senza che sia necessario decrittografarli. L'operazione avrà esito negativo se l'opzione ALLOW_ENCRYPTED_VALUE_MODIFICATIONS non è impostata sull'utente o se l'opzione BCPMODIFYENCRYPTED non è impostata sull'handle di connessione. Per altre informazioni, vedere sotto.
Enabled IN (al server) Inserisce testo non crittografato. Il driver crittograferà i dati della colonna.

Opzione BCPMODIFYENCRYPTED

Per evitare il danneggiamento dei dati, il server in genere non consente l'inserimento di testo crittografato direttamente in una colonna crittografata e quindi i tentativi di eseguire questa operazione avranno esito negativo. Tuttavia, per il caricamento bulk dei dati crittografati con l'API BCP, se si imposta l'opzione BCPMODIFYENCRYPTEDbcp_control su TRUE è possibile inserire direttamente testo crittografato riducendo il rischio di danneggiare i dati crittografati tramite l'impostazione dell'opzione ALLOW_ENCRYPTED_VALUE_MODIFICATIONS nell'account utente. Ciononostante, le chiavi devono corrispondere ai dati ed è consigliabile eseguire alcuni controlli di sola lettura sui dati inseriti dopo l'inserimento bulk e prima di usarli per altre operazioni.

Per altre informazioni, vedere Migrare dati sensibili protetti da Always Encrypted.

Riepilogo dell'API Always Encrypted

Parole chiave per le stringhe di connessione

Nome Descrizione
ColumnEncryption I valori accettati sono Enabled/Disabled.
Enabled: abilita la funzionalità Always Encrypted per la connessione.
Disabled: disabilita la funzionalità Always Encrypted per la connessione.
attestation protocol, attestation URL (versione 17.4 e successive): abilita la funzionalità Always Encrypted con l'enclave sicura usando il protocollo di attestazione e l'URL di attestazione specificati.

Il valore predefinito è Disabled.
KeyStoreAuthentication Valori validi: KeyVaultPassword, KeyVaultClientSecret, KeyVaultInteractive, KeyVaultManagedIdentity
KeyStorePrincipalId Se KeyStoreAuthentication = KeyVaultPassword, impostare questo valore su un nome dell'entità utente valido di Microsoft Entra.
Se KeyStoreAuthetication = KeyVaultClientSecret, impostare questo valore su un ID client applicazione valido di Microsoft Entra
Se KeyStoreAuthetication = KeyVaultManagedIdentity, impostare questo valore sull'ID oggetto di identità gestita assegnata dall'utente. Se non è specificato alcun valore, viene usata l'identità gestita assegnata dal sistema.
KeyStoreSecret Quando KeyStoreAuthentication = KeyVaultPassword,impostare questo valore sulla password per il nome utente corrispondente.
Se KeyStoreAuthentication = KeyVaultClientSecret, impostare questo valore sul segreto dell'applicazione associato a un ID client valido dell'applicazione di Microsoft Entra

Attributi di connessione

Nome Tipo Descrizione
SQL_COPT_SS_COLUMN_ENCRYPTION Pre-connessione SQL_COLUMN_ENCRYPTION_DISABLE (0): disabilita la funzionalità Always Encrypted
SQL_COLUMN_ENCRYPTION_ENABLE (1): abilita la funzionalità Always Encrypted
Puntatore alla stringa *attestation protocol*,*attestation URL* (versione 17.4 e successive): abilita l'uso con l'enclave sicura
SQL_COPT_SS_CEKEYSTOREPROVIDER Post-connessione [Set] - Prova a caricare CEKeystoreProvider
[Get] - Restituisce un nome CEKeystoreProvider
SQL_COPT_SS_CEKEYSTOREDATA Post-connessione [Set] - Scrive i dati in CEKeystoreProvider
[Get] - Legge i dati da CEKeystoreProvider
SQL_COPT_SS_CEKCACHETTL Post-connessione [Set] - Imposta il valore TTL della cache delle chiavi di crittografia di colonna
[Get] - Ottiene il valore TTL della cache delle chiavi di crittografia di colonna corrente
SQL_COPT_SS_TRUSTEDCMKPATHS Post-connessione [Set] - Imposta il puntatore ai percorsi delle chiavi master di colonna attendibili
[Get] - Ottiene il puntatore ai percorsi delle chiavi master di colonna attendibili corrente

Attributi di istruzione

Nome Descrizione
SQL_SOPT_SS_COLUMN_ENCRYPTION SQL_CE_DISABLED (0): la funzionalità Always Encrypted è disabilitata per l'istruzione
SQL_CE_RESULTSETONLY (1): solo decrittografia. I set di risultati e i valori restituiti sono decrittografati e i parametri non sono crittografati
SQL_CE_ENABLED (3): la funzionalità Always Encrypted è abilitata e viene usata sia per i parametri che per i risultati

Campi descrittori

Campo descrittore parametri di implementazione Dimensioni/Tipo Valore predefinito Descrizione
SQL_CA_SS_FORCE_ENCRYPT (1236) WORD (2 byte) 0 Quando 0 (impostazione predefinita): la decisione di crittografare questo parametro è determinata dalla disponibilità dei metadati di crittografia.

Quando diverso da zero: se sono disponibili metadati di crittografia per questo parametro, viene crittografato. In caso contrario, la richiesta ha esito negativo con l'errore [CE300] [Microsoft][ODBC Driver 17 for SQL Server]La crittografia obbligatoria è stata specificata per un parametro ma non sono stati forniti metadati di crittografia dal server.

Opzioni bcp_control

Nome opzione Valore predefinito Descrizione
BCPMODIFYENCRYPTED (21) FALSE Quando TRUE, consente di inserire valori varbinary(max) in una colonna crittografata. Quando FALSE, impedisce l'inserimento a meno che non vengano forniti i metadati di crittografia e il tipo corretti.

Risoluzione dei problemi

Quando si riscontrano difficoltà nell'uso della funzionalità Always Encrypted, controllare prima di tutto gli aspetti seguenti:

  • La chiave di crittografia di colonna che esegue la crittografia della colonna desiderata è presente e accessibile sul server.

  • La chiave master di colonna che esegue la crittografia della chiave di crittografia di colonna dispone di metadati accessibili sul server ed è accessibile anche dal client.

  • L'opzione ColumnEncryption è abilitata nel DSN, nella stringa di connessione o nell'attributo di connessione e se si usa l'enclave sicura ha il formato appropriato.

Inoltre, quando si usa l'enclave sicura gli errori di attestazione identificano il passaggio del processo di attestazione in cui si è verificato l'errore, in base alla tabella seguente:

Procedi Descrizione
0-99 Risposta di attestazione non valida o errore di verifica della firma.
100-199 Errore durante il recupero dei certificati dall'URL di attestazione. Verificare che <attestation URL>/v2.0/signingCertificates sia valido e accessibile.
200-299 Formato dell'identità dell'enclave inatteso o errato.
300-399 Errore durante la creazione del canale sicuro con enclave.

Vedi anche