Verwenden von Always Encrypted mit den PHP-Treibern für SQL ServerUsing Always Encrypted with the PHP Drivers for SQL Server

HerunterladenPHP-Treiber herunterladenDownloadDownload PHP Driver

Anwendbar aufApplicable to

  • Microsoft-Treiber 5.2 für PHP für SQL ServerMicrosoft Drivers 5.2 for PHP for SQL Server

EinführungIntroduction

Dieser Artikel enthält Informationen zum Entwickeln von PHP-Anwendungen mithilfe von Always Encrypted (Datenbank-Engine) und der Microsoft-Treiber für PHP für SQL Server.This article provides information on how to develop PHP applications using Always Encrypted (Database Engine) and the PHP Drivers for SQL Server.

Always Encrypted ermöglicht Clientanwendungen das Verschlüsseln von vertraulichen Daten in einer Weise, dass weder die Daten noch die Verschlüsselungsschlüssel zu irgendeinem Zeitpunkt gegenüber SQL Server oder Azure SQL-Datenbank offengelegt werden.Always Encrypted allows client applications to encrypt sensitive data and never reveal the data or the encryption keys to SQL Server or Azure SQL Database. Ein Treiber, bei dem Always Encrypted aktiviert ist, z. B. ODBC Driver for SQL Server, ver- und entschlüsselt sensible Daten in der Clientanwendung.An Always Encrypted enabled driver, such as the ODBC Driver for SQL Server, transparently encrypts and decrypts sensitive data in the client application. Der Treiber ermittelt automatisch, welche Abfrageparameter vertraulichen Datenbankspalten (mit Always Encrypted geschützt) entsprechen. Die Werte dieser Parameter werden dann vor der Übergabe an SQL Server oder Azure SQL-Datenbank verschlüsselt.The driver automatically determines which query parameters correspond to sensitive database columns (protected using Always Encrypted), and encrypts the values of those parameters before passing the data to SQL Server or Azure SQL Database. Auf ähnliche Weise entschlüsselt der Treiber die Daten transparent, die von verschlüsselten Datenbankspalten in Abfrageergebnissen empfangen werden.Similarly, the driver transparently decrypts data retrieved from encrypted database columns in query results. Weitere Informationen finden Sie unter Immer verschlüsselt (Datenbank-Engine).For more information, see Always Encrypted (Database Engine). Die PHP-Treiber für SQL Server verwenden den ODBC-Treiber für die SQL Server, um sensible Daten zu verschlüsseln.The PHP Drivers for SQL Server utilize the ODBC Driver for SQL Server to encrypt sensitive data.

VoraussetzungenPrerequisites

  • Konfigurieren Sie Always Encrypted in Ihrer Datenbank.Configure Always Encrypted in your database. Diese Konfiguration umfasst die Bereitstellung von Always Encrypted-Schlüsseln und die Einrichtung der Verschlüsselung für ausgewählte Datenbankspalten.This configuration involves provisioning Always Encrypted keys and setting up encryption for selected database columns. Wenn Sie nicht bereits über eine Datenbank verfügen, für die Always Encrypted konfiguriert ist, befolgen Sie die Anweisungen in Erste Schritte mit Always Encrypted.If you do not already have a database with Always Encrypted configured, follow the directions in Getting Started with Always Encrypted. Insbesondere sollte Ihre Datenbank die Metadatendefinitionen für einen Spaltenhauptschlüssel (Column Master Key, CMK), einen Spaltenverschlüsselungsschlüssel (Column Encryption Key, CEK) und eine Tabelle mit mindestens einer Spalte enthalten, die mit diesem CEK verschlüsselt ist.In particular, your database should contain the metadata definitions for a Column Master Key (CMK), a Column Encryption Key (CEK), and a table containing one or more columns encrypted using that CEK.
  • Stellen Sie sicher, dass der ODBC-Treiber für SQL Server Version 17 oder höher auf dem Entwicklungs Computer installiert ist.Make sure ODBC Driver for SQL Server version 17 or higher is installed on your development machine. Weitere Informationen finden Sie unter ODBC Driver for SQL Server.For details, see ODBC Driver for SQL Server.

Aktivieren von Always Encrypted in einer PHP-AnwendungEnabling Always Encrypted in a PHP Application

Die einfachste Möglichkeit zum Aktivieren der Verschlüsselung von Parametern, die auf verschlüsselte Spalten ausgerichtet sind, und der Entschlüsselung von Abfrageergebnissen besteht im Festlegen des Werts für die Verbindungszeichenfolge ColumnEncryption auf Enabled.The easiest way to enable the encryption of parameters targeting the encrypted columns and the decryption of query results is by setting the value of the ColumnEncryption connection string keyword to Enabled. Im folgenden finden Sie Beispiele für das Aktivieren von Always Encrypted in den sqlsrv-und PDO_SQLSRV-Treibern:The following are examples of enabling Always Encrypted in the SQLSRV and PDO_SQLSRV drivers:

SQLSRV:SQLSRV:

$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd, "ColumnEncryption"=>"Enabled");
$conn = sqlsrv_connect($server, $connectionInfo);

PDO_SQLSRV:PDO_SQLSRV:

$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled;";
$conn = new PDO("sqlsrv:server = $server; $connectionInfo", $uid, $pwd);

Das Aktivieren von Always Encrypted für eine erfolgreiche Verschlüsselung oder Entschlüsselung ist nicht ausreichend. Sie müssen außerdem Folgendes sicherstellen:Enabling Always Encrypted is not sufficient for encryption or decryption to succeed; you also need to make sure that:

  • Die Anwendung verfügt über die Datenbankberechtigungen VIEW ANY COLUMN MASTER KEY DEFINITION und VIEW ANY COLUMN ENCRYPTION KEY DEFINITION, die für den Zugriff auf die Metadaten in der Datenbank über Always Encrypted-Schlüssel erforderlich sind.The application has the VIEW ANY COLUMN MASTER KEY DEFINITION and VIEW ANY COLUMN ENCRYPTION KEY DEFINITION database permissions, required to access the metadata about Always Encrypted keys in the database. Einzelheiten hierzu finden Sie unter Datenbankberechtigungen.For details, see Database Permission.
  • Die Anwendung muss auf den CMK zugreifen können, der die CEKs für die abgefragten verschlüsselten Spalten schützt.The application can access the CMK that protects the CEKs for the queried encrypted columns. Diese Anforderung ist abhängig vom Schlüsselspeicher Anbieter, der den CMK speichert.This requirement is dependent on the key store provider that stores the CMK. Weitere Informationen finden Sie im Abschnitt Arbeiten mit Spaltenhauptschlüsselspeichern.For more information, see Working with Column Master Key Stores.

Abrufen und Ändern von Daten in verschlüsselten SpaltenRetrieving and Modifying Data in Encrypted Columns

Nachdem Sie Always Encrypted für eine Verbindung aktiviert haben, können Sie standardmäßige sqlsrv-APIs (siehe Referenz zur sqlsrv-Treiber-API) oder PDO_SQLSRV-APIs (siehe PDO_SQLSRV Driver-API-Referenz) verwenden, um Daten in verschlüsselten Daten Bank Spalten abzurufen oder zu ändern.Once you enable Always Encrypted on a connection, you can use standard SQLSRV APIs (see SQLSRV Driver API Reference) or PDO_SQLSRV APIs (see PDO_SQLSRV Driver API Reference) to retrieve or modify data in encrypted database columns. Wenn Ihre Anwendung über die erforderlichen Datenberechtigungen verfügt und auf den Spaltenhauptschlüssel zugreifen kann, verschlüsselt der Treiber alle Abfrageparameter für verschlüsselte Spalten und entschlüsselt Daten, die aus verschlüsselten Spalten abgefragt wurden. Dieser Vorgang erfolgt in der Anwendung transparent, als ob die Spalten nicht verschlüsselt wären.Assuming your application has the required database permissions and can access the column master key, the driver encrypts any query parameters that target encrypted columns and decrypt data retrieved from encrypted columns, behaving transparently to the application as if the columns were not encrypted.

Wenn Always Encrypted nicht aktiviert ist, tritt bei Abfragen mit Parametern, die auf verschlüsselte Spalten ausgerichtet sind, ein Fehler auf.If Always Encrypted is not enabled, queries with parameters that target encrypted columns fail. Daten können weiterhin aus verschlüsselten Spalten abgerufen werden, solange die Abfrage keine Parameter für verschlüsselte Spalten enthält.Data can still be retrieved from encrypted columns, as long as the query has no parameters targeting encrypted columns. Der Treiber versucht jedoch nicht, die Daten zu entschlüsseln. Daher erhält die Anwendung die verschlüsselten Binärdaten (als Bytearrays).However, the driver does not attempt any decryption and the application receives the binary encrypted data (as byte arrays).

Die folgende Tabelle fasst das Verhalten von Abfragen in Abhängigkeit davon zusammen, ob Always Encrypted aktiviert ist:The following table summarizes the behavior of queries, depending on whether Always Encrypted is enabled or not:

AbfragemerkmalQuery characteristic Always Encrypted ist aktiviert und die Anwendung kann auf die Schlüssel und Schlüsselmetadaten zugreifen.Always Encrypted is enabled and application can access the keys and key metadata Always Encrypted ist aktiviert und die Anwendung kann nicht auf die Schlüssel oder Schlüsselmetadaten zugreifen.Always Encrypted is enabled and application cannot access the keys or key metadata Always Encrypted ist deaktiviertAlways Encrypted is disabled
Parameter für verschlüsselte SpaltenParameters targeting encrypted columns. Parameterwerte werden transparent verschlüsselt.Parameter values are transparently encrypted. FehlerError FehlerError
Daten von verschlüsselten Spalten ohne Parameter abrufen, die auf verschlüsselte Spalten ausgerichtet sind.Retrieving data from encrypted columns, without parameters targeting encrypted columns. Ergebnisse von verschlüsselten Spalten werden transparent entschlüsselt.Results from encrypted columns are transparently decrypted. Die Anwendung erhält Klartextspaltenwerte.The application receives plaintext column values. FehlerError Ergebnisse von verschlüsselten Spalten werden nicht entschlüsselt.Results from encrypted columns are not decrypted. Die Anwendung erhält verschlüsselte Werte als Bytearrays.The application receives encrypted values as byte arrays.

Die folgenden Beispiele veranschaulichen das Abrufen und Ändern von Daten in verschlüsselten Spalten.The following examples illustrate retrieving and modifying data in encrypted columns. Dabei wird eine Tabelle mit dem folgenden Schema angenommen:The examples assume a table with the following schema. Die Spalten „SSN“ und „BirthDate“ werden verschlüsselt.The SSN and BirthDate columns are encrypted.

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

Beispiel für das Einfügen von DatenData Insertion Example

In den folgenden Beispielen wird veranschaulicht, wie die sqlsrv-und PDO_SQLSRV-Treiber verwendet werden, um eine Zeile in die Patienten Tabelle einzufügen.The following examples demonstrate how to use the SQLSRV and PDO_SQLSRV drivers to insert a row into the Patient table. Beachten Sie die folgenden Punkte:Note the following points:

  • Es erfolgt keine spezielle Verschlüsselung im Beispielcode.There is nothing specific to encryption in the sample code. Der Treiber erkennt und verschlüsselt automatisch die Werte der Parameter „SSN“ und „BirthDate“ für verschlüsselte Spalten.The driver automatically detects and encrypts the values of the SSN and BirthDate parameters, which target encrypted columns. Durch diesen Mechanismus wird die Verschlüsselung für die Anwendung transparent.This mechanism makes encryption transparent to the application.
  • Die in die Datenbankspalten eingefügten Werte, einschließlich der verschlüsselten Spalten, werden als gebundene Parameter übergeben.The values inserted into database columns, including the encrypted columns, are passed as bound parameters. Während die Verwendung von Parametern optional ist, wenn Werte an nicht verschlüsselte Spalten gesendet werden (obwohl es dringend empfohlen wird, da es dabei hilft, eine Einschleusung von SQL-Befehlen zu verhindern), ist sie für Werte erforderlich, die auf verschlüsselte Spalten ausgerichtet sind.While using parameters is optional when sending values to non-encrypted columns (although it is highly recommended because it helps prevent SQL injection), it is required for values targeting encrypted columns. Werden die in die Spalten „SSN“ oder „BirthDate“ eingefügten Werte als Literale übergeben, die in die Abfrageanweisung eingebettet sind, tritt ein Fehler auf, da der Treiber nicht versucht, Literale in Abfragen zu verschlüsseln oder anderweitig zu verarbeiten.If the values inserted in the SSN or BirthDate columns were passed as literals embedded in the query statement, the query would fail because the driver does not attempt to encrypt or otherwise process literals in queries. Daher würde der Server sie zurückweisen, da sie mit den verschlüsselten Spalten inkompatibel sind.As a result, the server would reject them as incompatible with the encrypted columns.
  • Beim Einfügen von Werten mithilfe von Bindungs Parametern muss ein SQL-Typ, der mit dem Datentyp der Ziel Spalte identisch ist oder dessen Konvertierung in den Datentyp der Ziel Spalte unterstützt wird, an die Datenbank übermittelt werden.When inserting values using bind parameters, a SQL type that is identical to the data type of the target column or whose conversion to the data type of the target column is supported must be passed to the database. Diese Anforderung liegt daran, dass Always Encrypted wenige Typkonvertierungen unterstützt (Weitere Informationen finden Sie unter Always encrypted (Datenbank-Engine)).This requirement is because Always Encrypted supports few type conversions (for details, see Always Encrypted (Database Engine)). Die beiden PHP-Treiber sqlsrv und PDO_SQLSRV verfügen jeweils über einen Mechanismus, mit dessen Hilfe der Benutzer den SQL-Typ des Werts bestimmen kann.The two PHP drivers, SQLSRV and PDO_SQLSRV, each has a mechanism to help the user determine the SQL type of the value. Daher muss der Benutzer den SQL-Typ nicht explizit angeben.Therefore, the user does not have to provide the SQL type explicitly.
  • Für den sqlsrv-Treiber verfügt der Benutzer über zwei Optionen:For the SQLSRV driver, the user has two options:
  • Setzen Sie den PHP-Treiber ein, um den richtigen SQL-Typ zu ermitteln und festzulegen.Rely on the PHP driver to determine and set the right SQL type. In diesem Fall muss der Benutzer sqlsrv_prepare und sqlsrv_execute verwenden, um eine parametrisierte Abfrage auszuführen.In this case, the user must use sqlsrv_prepare and sqlsrv_execute to execute a parameterized query.
  • Legen Sie den SQL-Typ explizit fest.Set the SQL type explicitly.
  • Für den PDO_SQLSRV-Treiber ist es nicht möglich, den SQL-Typ eines Parameters explizit festzulegen.For the PDO_SQLSRV driver, the user does not have the option to explicitly set the SQL type of a parameter. Der PDO_SQLSRV Treiber unterstützt den Benutzer beim Binden eines Parameters automatisch beim Festlegen des SQL-Typs.The PDO_SQLSRV driver automatically helps the user determine the SQL type when binding a parameter.
  • Damit die Treiber den SQL-Typ bestimmen können, gelten einige Einschränkungen:For the drivers to determine the SQL type, some limitations apply:
  • SQLSRV-Treiber:SQLSRV Driver:
  • Wenn der Benutzer möchte, dass der Treiber die SQL-Typen für die verschlüsselten Spalten bestimmt, muss der Benutzer sqlsrv_prepare und sqlsrv_executeverwenden.If the user wants the driver to determine the SQL types for the encrypted columns, the user must use sqlsrv_prepare and sqlsrv_execute.
  • Wenn sqlsrv_query bevorzugt wird, ist der Benutzer für die Angabe der SQL-Typen für alle Parameter verantwortlich.If sqlsrv_query is preferred, the user is responsible for specifying the SQL types for all parameters. Der angegebene SQL-Typ muss die Zeichen folgen Länge für Zeichen folgen Typen sowie die Skalierung und Genauigkeit für Dezimal Typen enthalten.The specified SQL type must include the string length for string types, and the scale and precision for decimal types.
  • PDO_SQLSRV-Treiber:PDO_SQLSRV Driver:
  • Das Anweisungs Attribut PDO::SQLSRV_ATTR_DIRECT_QUERY wird in einer parametrisierten Abfrage nicht unterstützt.The statement attribute PDO::SQLSRV_ATTR_DIRECT_QUERY is not supported in a parameterized query.
  • Das Anweisungs Attribut PDO::ATTR_EMULATE_PREPARES wird in einer parametrisierten Abfrage nicht unterstützt.The statement attribute PDO::ATTR_EMULATE_PREPARES is not supported in a parameterized query.

SQLSRV-Treiber und sqlsrv_prepare:SQLSRV driver and sqlsrv_prepare:

// insertion into encrypted columns must use a parameterized query
$query = "INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (?, ?, ?, ?)";
$ssn = "795-73-9838";
$firstName = "Catherine";
$lastName = "Abel;
$birthDate = "1996-10-19";
$params = array($ssn, $firstName, $lastName, $birthDate);
// during sqlsrv_prepare, the driver determines the SQL types for each parameter and pass them to SQL server
$stmt = sqlsrv_prepare($conn, $query, $params);
sqlsrv_execute($stmt);

SQLSRV-Treiber und sqlsrv_query:SQLSRV driver and sqlsrv_query:

// insertion into encrypted columns must use a parameterized query
$query = "INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (?, ?, ?, ?)";
$ssn = "795-73-9838";
$firstName = "Catherine";
$lastName = "Abel";
$birthDate = "1996-10-19";
// need to provide the SQL types for ALL parameters  
// note the SQL types (including the string length) have to be the same at the column definition
$params = array(array(&$ssn, null, null, SQLSRV_SQLTYPE_CHAR(11)),
                array(&$firstName, null, null, SQLSRV_SQLTYPE_NVARCHAR(50)),
                array(&$lastName, null, null, SQLSRV_SQLTYPE_NVARCHAR(50)),
                array(&$birthDate, null, null, SQLSRV_SQLTYPE_DATE));
sqlsrv_query($conn, $query, $params);

PDO_SQLSRV Treiber und PDO::p repare:PDO_SQLSRV driver and PDO::prepare:

// insertion into encrypted columns must use a parameterized query
$query = "INSERT INTO [dbo].[Patients] ([SSN], [FirstName], [LastName], [BirthDate]) VALUES (?, ?, ?, ?)";
$ssn = "795-73-9838";
$firstName = "Catherine";
$lastName = "Able";
$birthDate = "1996-10-19";
// during PDO::prepare, the driver determines the SQL types for each parameter and pass them to SQL server
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $ssn);
$stmt->bindParam(2, $firstName);
$stmt->bindParam(3, $lastName);
$stmt->bindParam(4, $birthDate);
$stmt->execute();

Beispiel für das Abrufen von KlartextdatenPlaintext Data Retrieval Example

In den folgenden Beispielen wird das Filtern von Daten auf der Grundlage verschlüsselter Werte und das Abrufen von Klartext-Daten aus verschlüsselten Spalten mithilfe der sqlsrv-und PDO_SQLSRV-Treiber veranschaulicht.The following examples demonstrate filtering data based on encrypted values, and retrieving plaintext data from encrypted columns using the SQLSRV and PDO_SQLSRV drivers. Beachten Sie die folgenden Punkte:Note the following points:

  • Der in der WHERE-Klausel zum Filtern der Spalte „SSN“ verwendete Wert muss mit dem bind-Parameter übergeben werden, damit ihn der Treiber vor dem Senden an die Datenbank transparent verschlüsseln kann.The value used in the WHERE clause to filter on the SSN column needs to be passed using bind parameter, so that the driver can transparently encrypt it before sending it to the server.
  • Beim Ausführen einer Abfrage mit gebundenen Parametern bestimmt der PHP-Treiber automatisch den SQL-Typ für den Benutzer, es sei denn, der Benutzer gibt den SQL-Typ explizit an, wenn der sqlsrv-Treiber verwendet wird.When executing a query with bound parameters, the PHP drivers automatically determines the SQL type for the user unless the user explicitly specifies the SQL type when using the SQLSRV driver.
  • Alle Werte werden vom Programm als Klartext ausgegeben, da der Treiber die aus den Spalten „SSN“ und „BirthDate“ abgerufenen Daten transparent entschlüsselt.All values printed by the program are in plaintext, since the driver transparently decrypts the data retrieved from the SSN and BirthDate columns.

Hinweis: Abfragen können Übereinstimmungsvergleiche für verschlüsselte Spalten nur bei deterministischer Verschlüsselung ausführen.Note: Queries can perform equality comparisons on encrypted columns only if the encryption is deterministic. Weitere Informationen finden Sie im Abschnitt Auswählen der deterministischen oder zufälligen Verschlüsselung.For more information, see Selecting Deterministic or Randomized encryption.

SQLSRV:SQLSRV:

// since SSN is an encrypted column, need to pass the value in the WHERE clause through bind parameter
$query = "SELECT [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [SSN] = ?";
$ssn = "795-73-9838";
$stmt = sqlsrv_prepare($conn, $query, array(&$ssn));
// during sqlsrv_execute, the driver encrypts the ssn value and passes it to the database
sqlsrv_execute($stmt);
// fetch like usual
$row = sqlsrv_fetch_array($stmt);

PDO_SQLSRV:PDO_SQLSRV:

// since SSN is an encrypted column, need to pass the value in the WHERE clause through bind parameter
$query = "SELET [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [SSN] = ?";
$ssn = "795-73-9838";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $ssn);
// during PDOStatement::execute, the driver encrypts the ssn value and passes it to the database
$stmt->execute();
// fetch like usual
$row = $stmt->fetch();

Beispiel für das Abrufen von ChiffretextdatenCiphertext Data Retrieval Example

Wenn Always Encrypted nicht aktiviert ist, können Abfragen weiterhin Daten aus verschlüsselten Spalten abrufen, so lange die Abfrage keine Parameter für verschlüsselte Spalten enthält.If Always Encrypted is not enabled, a query can still retrieve data from encrypted columns, as long as the query has no parameters targeting encrypted columns.

In den folgenden Beispielen wird das Abrufen von Binär verschlüsselten Daten aus verschlüsselten Spalten mithilfe der sqlsrv-und PDO_SQLSRV-Treiber veranschaulicht.The following examples illustrate retrieving binary encrypted data from encrypted columns using the SQLSRV and PDO_SQLSRV drivers. Beachten Sie die folgenden Punkte:Note the following points:

  • Da Always Encrypted in der Verbindungszeichenfolge nicht aktiviert ist, gibt die Abfrage verschlüsselte Werte von „SSN“ und „BirthDate“ als Bytearrays zurück (das Programm konvertiert die Werte in Zeichenfolgen).As Always Encrypted is not enabled in the connection string, the query returns encrypted values of SSN and BirthDate as byte arrays (the program converts the values to strings).
  • Eine Abfrage, die Daten aus verschlüsselten Spalten mit deaktiviertem Always Encrypted abruft, kann Parameter aufweisen, so lange keiner der Parameter auf eine verschlüsselte Spalte ausgerichtet ist.A query retrieving data from encrypted columns with Always Encrypted disabled can have parameters, as long as none of the parameters target an encrypted column. In der folgenden Abfrage wird nach der Spalte „LastName“ gefiltert, die in der Datenbank nicht verschlüsselt ist.The following query filters by LastName, which is not encrypted in the database. Wenn in der Abfrage nach „SSN“ oder „BirthDate“ gefiltert wird, würde ein Fehler auftreten.If the query filters by SSN or BirthDate, the query would fail.

SQLSRV:SQLSRV:

$query = "SELET [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [LastName] = ?";
$lastName = "Abel";
$stmt = sqlsrv_prepare($conn, $query, array(&$lastName));
sqlsrv_execute($stmt);
$row = sqlsrv_fetch_array($stmt);

PDO_SQLSRV:PDO_SQLSRV:

$query = "SELET [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE [LastName] = ?";
$lastName = "Abel";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $lastName);
$stmt->execute();
$row = $stmt->fetch();

Vermeiden allgemeiner Probleme beim Abfragen von verschlüsselter SpaltenAvoiding Common Problems when Querying Encrypted Columns

In diesem Abschnitt werden die allgemeinen Fehlerkategorien bei der Abfrage verschlüsselter Spalten über PHP-Anwendungen sowie einige Grundsätze zum Vermeiden dieser Fehler.This section describes common categories of errors when querying encrypted columns from PHP applications and a few guidelines on how to avoid them.

Konvertierungsfehler durch nicht unterstützte DatentypenUnsupported data type conversion errors

Always Encrypted unterstützt einige Konvertierungen für verschlüsselte Datentypen.Always Encrypted supports few conversions for encrypted data types. Eine ausführliche Liste der unterstützten Typkonvertierungen finden Sie unter Always Encrypted (Datenbank-Engine).See Always Encrypted (Database Engine) for the detailed list of supported type conversions. Gehen Sie wie folgt vor, um Fehler bei Konvertierung des Datentyps zu vermeiden:Do the following to avoid data type conversion errors:

  • Wenn Sie den sqlsrv-Treiber mit sqlsrv_prepare verwenden und den SQL-Typ sqlsrv_execute, wird zusammen mit der Spaltengröße und der Anzahl der Dezimalziffern des Parameters automatisch festgelegt.When using the SQLSRV driver with sqlsrv_prepare and sqlsrv_execute the SQL type, along with the column size and the number of decimal digits of the parameter is automatically determined.
  • Wenn Sie den PDO_SQLSRV-Treiber verwenden, um eine Abfrage auszuführen, wird der SQL-Typ mit der Spaltengröße und der Anzahl der Dezimalziffern des Parameters ebenfalls automatisch festgelegt.When using the PDO_SQLSRV driver to execute a query, the SQL type with the column size and the number of decimal digits of the parameter is also automatically determined
  • Wenn Sie den sqlsrv-Treiber mit sqlsrv_query verwenden, um eine Abfrage auszuführen:When using the SQLSRV driver with sqlsrv_query to execute a query:
  • Entweder ist der SQL-Typ des Parameters identisch mit dem Typ der Zielspalte oder die Konvertierung vom SQL-Typ in den Typ der Spalte wird unterstützt.The SQL type of the parameter is either exactly the same as the type of the targeted column, or the conversion from the SQL type to the type of the column is supported.
  • Die Genauigkeit und Dezimalstellenanzahl von Parametern, die auf Spalten der SQL Server-Datentypen decimal und numeric ausgerichtet sind, ist mit der für die Zielspalte konfigurierten Genauigkeit und Dezimalstellenanzahl identisch.The precision and scale of the parameters targeting columns of the decimal and numeric SQL Server data types is the same as the precision and scale configure for the target column.
  • Die Genauigkeit von Parametern, die auf Spalten der SQL Server-Datentypen datetime2, datetimeoffset oder time ausgerichtet sind, ist in Abfragen, in denen die Zielspalte geändert wird, nicht größer als die Genauigkeit für die Zielspalte.The precision of parameters targeting columns of datetime2, datetimeoffset, or time SQL Server data types is not greater than the precision for the target column, in queries that modify the target column.
  • Verwenden Sie keine PDO_SQLSRV Anweisungs Attribute PDO::SQLSRV_ATTR_DIRECT_QUERY oder PDO::ATTR_EMULATE_PREPARES in einer parametrisierten Abfrage.Do not use PDO_SQLSRV statement attributes PDO::SQLSRV_ATTR_DIRECT_QUERY or PDO::ATTR_EMULATE_PREPARES in a parameterized query

Fehler aufgrund der Übergabe von Klartext anstelle von verschlüsselten WertenErrors due to passing plaintext instead of encrypted values

Jeder Wert für verschlüsselte Spalten muss vor dem Senden an den Server verschlüsselt werden.Any value that targets an encrypted column needs to be encrypted before being sent to the server. Ein Versuch, einen Klartextwert einzufügen, zu ändern oder nach einem Klartextwert für eine verschlüsselte Spalte zu filtern, führt zu einem Fehler.An attempt to insert, modify, or filter by a plaintext value on an encrypted column results in an error. Stellen Sie Folgendes sicher, um solche Fehler zu vermeiden:To prevent such errors, make sure that:

  • Always Encrypted aktiviert ist (legen Sie in der Verbindungs Zeichenfolge das ColumnEncryption-Schlüsselwort auf Enabled) fest.Always Encrypted is enabled (in the connection string, set the ColumnEncryption keyword to Enabled).
  • Sie verwenden Bind-Parameter zum Senden von Daten, die auf verschlüsselte Spalten ausgerichtet sind.You use bind parameter to send data targeting encrypted columns. Das folgende Beispiel zeigt eine Abfrage, die fälschlicherweise nach einem literalen/Konstanten in einer verschlüsselten Spalte (SSN) filtert:The following example shows a query that incorrectly filters by a literal/constant on an encrypted column (SSN):
$query = "SELET [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN='795-73-9838'";

Kontrollieren der Auswirkungen von Always Encrypted auf die LeistungControlling Performance Impact of Always Encrypted

Da Always Encrypted eine clientseitige Verschlüsselungstechnologie ist, werden die meisten Leistungseinbußen auf der Clientseite und nicht in der Datenbank beobachtet.Because Always Encrypted is a client-side encryption technology, most of the performance overhead is observed on the client side, not in the database. Neben den Kosten für Verschlüsselungs- und Entschlüsselungsvorgänge ergeben sich die folgenden anderen Quellen für Leistungseinbußen auf der Clientseite:Apart from the cost of encryption and decryption operations, the other sources of performance overhead on the client side are:

  • Zusätzliche Roundtrips zur Datenbank zum Abrufen von Metadaten für Abfrageparameter.Additional round-trips to the database to retrieve metadata for query parameters.
  • Aufrufe an einen Spaltenhauptschlüsselspeicher für den Zugriff auf einen Spaltenhauptschlüssel.Calls to a column master key store to access a column master key.

Roundtrips zum Abrufen von Metadaten für AbfrageparameterRound-trips to Retrieve Metadata for Query Parameters

Wenn Always Encrypted für eine Verbindung aktiviert ist, ruft der ODBC-Treiber standardmäßig sys.sp_describe_parameter_encryption für jede parametrisierte Abfrage auf, wobei die Abfrageanweisung (ohne Parameterwerte) an SQL Server übergeben wird.If Always Encrypted is enabled for a connection, the ODBC Driver will, by default, call sys.sp_describe_parameter_encryption for each parameterized query, passing the query statement (without any parameter values) to SQL Server. Die Abfrageanweisung wird von dieser gespeicherten Prozedur analysiert, um zu ermitteln, ob Parameter verschlüsselt werden müssen. In diesem Fall werden verschlüsselungsbezogene Informationen für jeden Parameter zurückgegeben, die der Treiber dann verschlüsseln kann.This stored procedure analyzes the query statement to find out if any parameters need to be encrypted, and if so, returns the encryption-related information for each parameter to allow the driver to encrypt them.

Da der Benutzer mit den PHP-Treibern einen Parameter in einer vorbereiteten Anweisung ohne Angabe des SQL-Typs binden kann, werden beim Binden eines Parameters in einer Always Encrypted aktivierten Verbindung die PHP-Treiber SQLDescribeParam für den-Parameter aufrufen, um den SQL-Typ, die Spaltengröße und Dezimalziffern abzurufen.Since the PHP drivers allow the user to bind a parameter in a prepared statement without providing the SQL type, when binding a parameter in an Always Encrypted enabled connection, the PHP Drivers call SQLDescribeParam on the parameter to get the SQL type, column size, and decimal digits. Die Metadaten werden dann zum Aufrufen von SQLBindParameterverwendet.The metadata is then used to call SQLBindParameter. Diese zusätzlichen SQLDescribeParam Aufrufe erfordern keine zusätzlichen Roundtrips zur Datenbank, da der ODBC-Treiber die Informationen bereits auf der Clientseite gespeichert hat, als sys.sp_describe_parameter_encryption aufgerufen wurde.These extra SQLDescribeParam calls do not require extra round-trips to the database as the ODBC Driver has already stored the information on the client side when sys.sp_describe_parameter_encryption was called.

Das oben beschriebene Verhalten stellt einen hohen Grad an Transparenz für die Clientanwendung sicher. Außerdem muss der Anwendungsentwickler nicht beachten, welche Abfragen auf verschlüsselte Spalten zugreifen, so lange die Werte für verschlüsselte Spalten in Parametern an den Treiber übergeben werden.The preceding behaviors ensure a high level of transparency to the client application (and the application developer) does not need to be aware of which queries access encrypted columns, as long as the values targeting encrypted columns are passed to the driver in parameters.

Im Gegensatz zum ODBC-Treiber für SQL Server wird das Aktivieren von Always Encrypted auf der Anweisung/Abfrage Ebene in den PHP-Treibern noch nicht unterstützt.Unlike the ODBC Driver for SQL Server, enabling Always Encrypted at the statement/query-level is not yet supported in the PHP drivers.

Zwischenspeicherung von SpaltenverschlüsselungsschlüsselnColumn Encryption Key Caching

Der Treiber speichert die Spaltenverschlüsselungsschlüssel (CEKs) unverschlüsselt im Zwischenspeicher, um die Anzahl der Aufrufe an einen Spaltenhauptschlüsselspeicher zum Entschlüsseln von CEKs zu verringern.To reduce the number of calls to a column master key store to decrypt column encryption keys (CEK), the driver caches the plaintext CEKs in memory. Nach dem Erhalt des verschlüsselten CEK (ECEK) aus den Datenbankmetadaten versucht der Treiber zunächst, den unverschlüsselten CEK zu finden, der dem verschlüsselten Schlüsselwert im Cache entspricht.After receiving the encrypted CEK (ECEK) from database metadata, the ODBC driver first tries to find the plaintext CEK corresponding to the encrypted key value in the cache. Der Treiber ruft den Schlüsselspeicher, der den CMK enthält, nur auf, wenn der entsprechende CEK im Klartext im Cache nicht gefunden werden kann.The driver calls the key store containing the CMK only if it cannot find the corresponding plaintext CEK in the cache.

Hinweis: Beim ODBC-Treiber für SQL Server werden die Einträge im Cache nach einem Zeitlimit von zwei Stunden entfernt.Note: In the ODBC Driver for SQL Server, the entries in the cache are evicted after a two-hour timeout. Dieses Verhalten bedeutet, dass der Treiber den Schlüsselspeicher für einen bestimmten ECEK während der Lebensdauer der Anwendung oder alle zwei Stunden (je nachdem, welches Intervall kürzer ist) nur einmal kontaktiert.This behavior means that for a given ECEK, the driver contacts the key store only once during the lifetime of the application or every two hours, whichever is less.

Arbeiten mit SpaltenhauptschlüsselspeichernWorking with Column Master Key Stores

Der Treiber benötigt zum Verschlüsseln oder Entschlüsseln von Daten einen CEK, der für die Zielspalte konfiguriert ist.To encrypt or decrypt data, the driver needs to obtain a CEK that is configured for the target column. CEKs werden in verschlüsselter Form (als ECEKs) in den Datenbankmetadaten gespeichert.CEKs are stored in encrypted form (ECEKs) in the database metadata. Jeder CEK besitzt einen entsprechenden CMK, mit dem er verschlüsselt wurde.Each CEK has a corresponding CMK that was used to encrypt it. In den Datenbankmetadaten wird nicht der CMK selbst gespeichert, sondern nur der Name des Schlüsselspeichers sowie Informationen zur Suche nach dem CMK.The database metadata does not store the CMK itself; it only contains the name of the key store and information that the key store can use to locate the CMK.

Wenn der Treiber den Klartextwert eines ECEK abrufen möchten, benötigt er zunächst die Metadaten für den CEK und den entsprechenden CMK. Mit diesen Informationen kontaktiert er den Schlüsselspeicher, der den CMK enthält, und fordert die Entschlüsselung des ECEK an.To obtain the plaintext value of an ECEK, the driver first obtains the metadata about both the CEK and its corresponding CMK, and then it uses this information to contact the key store containing the CMK and requests it to decrypt the ECEK. Die Kommunikation zwischen Treiber und Schlüsselspeicher erfolgt über einen Schlüsselspeicheranbieter.The driver communicates with a key store using a key store provider.

Für Microsoft Driver 5.3.0 for PHP for SQL Server werden nur der Windows-Zertifikat Speicher Anbieter und Azure Key Vault unterstützt.For Microsoft Driver 5.3.0 for PHP for SQL Server, only Windows Certificate Store Provider and Azure Key Vault are supported. Der andere Keystore-Anbieter, der vom ODBC-Treiber (Custom Keystore-Anbieter) unterstützt wird, wird noch nicht unterstützt.The other Keystore Provider supported by the ODBC Driver (Custom Keystore Provider) is not yet supported.

Verwenden des Windows-ZertifikatspeicheranbietersUsing the Windows Certificate Store Provider

Unter Windows enthält ODBC Driver for SQL Server einen integrierten CMK-Speicheranbieter für den Windows-Zertifikatspeicher namens MSSQL_CERTIFICATE_STORE.The ODBC Driver for SQL Server on Windows includes a built-in column master key store provider for the Windows Certificate Store, named MSSQL_CERTIFICATE_STORE. (Dieser Anbieter ist nicht unter macOS oder Linux verfügbar.) Mit diesem Anbieter wird der CMK lokal auf dem Clientcomputer gespeichert, und es ist keine weitere Konfiguration durch die Anwendung erforderlich, um ihn mit dem Treiber zu verwenden.(This provider is not available on macOS or Linux.) With this provider, the CMK is stored locally on the client machine and no additional configuration by the application is necessary to use it with the driver. Die Anwendung muss jedoch auf das Zertifikat und den privaten Schlüssel im Speicher zugreifen können.However, the application must have access to the certificate and its private key in the store. Weitere Informationen finden Sie unter Create and Store Column Master Keys (Always Encrypted)(Erstellen und Speichern von Spaltenhauptschlüsseln (Always Encrypted)).For more information, see Create and Store Column Master Keys (Always Encrypted).

Verwenden von Azure Key VaultUsing Azure Key Vault

Azure Key Vault bietet eine Möglichkeit zum Speichern von Verschlüsselungsschlüsseln, Kenn Wörtern und anderen Geheimnissen mit Azure und kann zum Speichern von Schlüsseln für Always Encrypted verwendet werden.Azure Key Vault offers a way to store encryption keys, passwords, and other secrets using Azure and can be used to store keys for Always Encrypted. Der ODBC-Treiber für SQL Server (Version 17 und höher) enthält einen integrierten Hauptschlüssel Speicher Anbieter für Azure Key Vault.The ODBC Driver for SQL Server (version 17 and higher) includes a built-in master key store provider for Azure Key Vault. Die folgenden Verbindungsoptionen behandeln Azure Key Vault Konfiguration: KeyStoreAuthentication, KeyStorePrincipalIdund KeyStoreSecret.The following connection options handle Azure Key Vault configuration: KeyStoreAuthentication, KeyStorePrincipalId, and KeyStoreSecret.

  • KeyStoreAuthentication kann einen von zwei möglichen Zeichen folgen Werten annehmen: KeyVaultPassword und KeyVaultClientSecret.KeyStoreAuthentication can take one of two possible string values: KeyVaultPassword and KeyVaultClientSecret. Diese Werte steuern, welche Art von Authentifizierungs Anmelde Informationen mit den anderen beiden Schlüsselwörtern verwendet werden.These values control what kind of authentication credentials are used with the other two keywords.
  • KeyStorePrincipalId nimmt eine Zeichenfolge an, die einen Bezeichner für das Konto darstellt, das auf den Azure Key Vault zugreifen möchte.KeyStorePrincipalId takes a string representing an identifier for the account seeking to access the Azure Key Vault.
    • Wenn KeyStoreAuthentication auf KeyVaultPasswordfestgelegt ist, muss KeyStorePrincipalId der Name eines Azure ActiveDirectory-Benutzers sein.If KeyStoreAuthentication is set to KeyVaultPassword, then KeyStorePrincipalId must be the name of an Azure ActiveDirectory user.
    • Wenn KeyStoreAuthentication auf KeyVaultClientSecretfestgelegt ist, muss KeyStorePrincipalId eine Anwendungs Client-ID sein.If KeyStoreAuthentication is set to KeyVaultClientSecret, then KeyStorePrincipalId must be an application client ID.
  • KeyStoreSecret eine Zeichenfolge mit einem geheimen Anmelde Informations Schlüssel annimmt.KeyStoreSecret takes a string representing a credential secret.
    • Wenn KeyStoreAuthentication auf KeyVaultPasswordfestgelegt ist, muss KeyStoreSecret das Kennwort des Benutzers sein.If KeyStoreAuthentication is set to KeyVaultPassword, then KeyStoreSecret must be the user's password.
    • Wenn KeyStoreAuthentication auf KeyVaultClientSecretfestgelegt ist, muss KeyStoreSecret der Anwendungs Schlüssel sein, der der Anwendungs Client-ID zugeordnet ist.If KeyStoreAuthentication is set to KeyVaultClientSecret, then KeyStoreSecret must be the application secret associated with the application client ID.

Alle drei Optionen müssen in der Verbindungs Zeichenfolge vorhanden sein, um Azure Key Vault zu verwenden.All three options must be present in the connection string to use Azure Key Vault. Außerdem muss ColumnEncryption auf Enabledfestgelegt werden.In addition, ColumnEncryption must be set to Enabled. Wenn ColumnEncryption auf Disabled festgelegt ist, aber die Azure Key Vault Optionen vorhanden sind, wird das Skript ohne Fehler fortgesetzt, es wird jedoch keine Verschlüsselung ausgeführt.If ColumnEncryption is set to Disabled but the Azure Key Vault options are present, the script will proceed without errors but no encryption will be performed.

In den folgenden Beispielen wird gezeigt, wie Sie mithilfe von Azure Key Vault eine Verbindung mit SQL Server herstellen.The following examples show how to connect to SQL Server using Azure Key Vault.

SQLSRV:SQLSRV:

Verwenden eines Azure Active Directory Kontos:Using an Azure Active Directory account:

$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd, "ColumnEncryption"=>"Enabled", "KeyStoreAuthentication"=>"KeyVaultPassword", "KeyStorePrincipalId"=>$AADUsername, "KeyStoreSecret"=>$AADPassword);
$conn = sqlsrv_connect($server, $connectionInfo);

Verwenden der Client-ID und des geheimen Schlüssels einer Azure-Anwendung:Using an Azure application client ID and secret:

$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd, "ColumnEncryption"=>"Enabled", "KeyStoreAuthentication"=>"KeyVaultClientSecret", "KeyStorePrincipalId"=>$applicationClientID, "KeyStoreSecret"=>$applicationClientSecret);
$conn = sqlsrv_connect($server, $connectionInfo);

PDO_SQLSRV: Verwenden eines Azure Active Directory Kontos:PDO_SQLSRV: Using an Azure Active Directory account:

$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; KeyStoreAuthentication = KeyVaultPassword; KeyStorePrincipalId = $AADUsername; KeyStoreSecret = $AADPassword;";
$conn = new PDO("sqlsrv:server = $server; $connectionInfo", $uid, $pwd);

Verwenden der Client-ID und des geheimen Schlüssels einer Azure-Anwendung:Using an Azure application client ID and secret:

$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; KeyStoreAuthentication = KeyVaultClientSecret; KeyStorePrincipalId = $applicationClientID; KeyStoreSecret = $applicationClientSecret;";
$conn = new PDO("sqlsrv:server = $server; $connectionInfo", $uid, $pwd);

Einschränkungen des PHP-Treibers bei Verwendung von Always EncryptedLimitations of the PHP drivers when using Always Encrypted

SQLSRV und PDO_SQLSRV:SQLSRV and PDO_SQLSRV:

  • Linux/macOS unterstützt den Windows-Zertifikat Speicher Anbieter nichtLinux/macOS do not support Windows Certificate Store Provider
  • Erzwingen von ParameterverschlüsselungForcing parameter encryption
  • Aktivieren von Always Encrypted auf Anweisungs EbeneEnabling Always Encrypted at the statement level
  • Bei Verwendung der Always Encrypted-Funktion und nicht-UTF8-Gebiets Schemas unter Linux und macOS (z. b. "en_US. ISO-8859-1 ") das Einfügen von NULL-Daten oder einer leeren Zeichenfolge in eine verschlüsselte char (n)-Spalte funktioniert möglicherweise nicht, wenn die Codepage 1252 nicht auf Ihrem System installiert ist.When using the Always Encrypted feature and non-UTF8 locales on Linux and macOS (such as "en_US.ISO-8859-1"), inserting null data or an empty string into an encrypted char(n) column may not work unless Code Page 1252 has been installed on your system

Nur sqlsrv:SQLSRV only:

  • Verwenden von sqlsrv_query für den Bindungs Parameter ohne Angabe des SQL-TypsUsing sqlsrv_query for binding parameter without specifying the SQL type
  • Verwenden von sqlsrv_prepare für das Binden von Parametern in einem Batch von SQL-AnweisungenUsing sqlsrv_prepare for binding parameters in a batch of SQL statements

Nur PDO_SQLSRV:PDO_SQLSRV only:

  • PDO::SQLSRV_ATTR_DIRECT_QUERY Anweisungs Attribut, das in einer parametrisierten Abfrage angegeben ist.PDO::SQLSRV_ATTR_DIRECT_QUERY statement attribute specified in a parameterized query
  • PDO::ATTR_EMULATE_PREPARE Anweisungs Attribut, das in einer parametrisierten Abfrage angegeben ist.PDO::ATTR_EMULATE_PREPARE statement attribute specified in a parameterized query
  • Binden von Parametern in einem Batch von SQL-Anweisungenbinding parameters in a batch of SQL statements

Die PHP-Treiber erben außerdem die Einschränkungen, die vom ODBC-Treiber für SQL Server und die Datenbank auferlegt werden.The PHP drivers also inherit the limitations imposed by the ODBC Driver for SQL Server and the database. Weitere Informationen finden Sie unter Einschränkungen des ODBC-Treibers bei Verwendung Always Encrypted und Always Encrypted Featuredetails.See Limitations of the ODBC driver when using Always Encrypted and Always Encrypted Feature Details.

Weitere InformationenSee Also

Programmierhandbuch für den PHP-SQL-Treiber API-Referenz für den SQLSRV-TreiberProgramming Guide for PHP SQL Driver SQLSRV Driver API Reference
API-Referenz für den PDO_SQLSRV-TreiberPDO_SQLSRV Driver API Reference