Usar o Always Encrypted com o PHP Drivers for SQL Server

Baixar o driver PHP

Aplicável a

  • Microsoft Drivers 5.2 for PHP for SQL Server

Introdução

Este artigo fornece informações sobre como desenvolver aplicativos PHP usando o Always Encrypted (mecanismo de banco de dados) e o PHP Drivers para SQL Server.

O Always Encrypted permite que os aplicativos cliente criptografem dados confidenciais e nunca revelem os dados nem as chaves de criptografia para o SQL Server ou o Banco de Dados SQL do Azure. Um driver habilitado para Always Encrypted, como o ODBC Driver for SQL Server, criptografa e descriptografa de modo transparente dados confidenciais no aplicativo cliente. O driver determina automaticamente quais parâmetros de consulta correspondem às colunas de banco de dados confidenciais (protegidas com o Always Encrypted) e criptografa os valores desses parâmetros antes de passar os dados para o SQL Server ou o Banco de Dados SQL do Azure. Da mesma forma, o driver descriptografa de modo transparente os dados recuperados das colunas de banco de dados criptografadas nos resultados da consulta. Para obter mais informações, veja Always Encrypted (Mecanismo de Banco de Dados). Os drivers PHP para SQL Server usam o driver ODBC para SQL Server para criptografar dados confidenciais.

Pré-requisitos

  • Configure o Sempre Criptografado em seu banco de dados. Essa configuração envolve o provisionamento de chaves do Always Encrypted e a configuração de criptografia de colunas de banco de dados selecionadas. Se você ainda não tem um banco de dados com o Always Encrypted configurado, siga as instruções em Tutorial: introdução ao Always Encrypted. Em particular, seu banco de dados deve conter as definições de metadados para uma chave mestra de coluna (CMK), uma chave de criptografia de coluna (CEK) e uma tabela contendo uma ou mais colunas criptografadas usando esse CEK.
  • Verifique se a versão 17 ou posterior do ODBC Driver for SQL Server está instalada no computador de desenvolvimento. Para saber mais, confira ODBC Driver for SQL Server.

Habilitar o Always Encrypted em um aplicativo do PHP

A maneira mais fácil para habilitar a criptografia de parâmetros direcionados às colunas criptografadas e a descriptografia dos resultados da consulta é definindo o valor da palavra-chave da cadeia de conexão ColumnEncryption como Enabled. Veja a seguir exemplos de como habilitar Always Encrypted nos drivers SQLSRV e PDO_SQLSRV:

SQLSRV:

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

PDO_SQLSRV:

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

Habilitar o Always Encrypted não é suficiente para o êxito da criptografia ou descriptografia. Do mesmo modo, é preciso ter certeza de que:

  • O aplicativo tem as permissões de banco de dados VIEW ANY COLUMN MASTER KEY DEFINITION e VIEW ANY COLUMN ENCRYPTION KEY DEFINITION, necessárias para acessar os metadados sobre as chaves do Always Encrypted no banco de dados. Para saber mais, confira Permissão de banco de dados.
  • O aplicativo pode acessar a CMK que protege as CEKs para as colunas criptografadas consultadas. Esse requisito é dependente do provedor do repositório de chaves que armazena o CMK. Para saber mais, confira Como trabalhar com repositórios de chaves mestras de coluna.

Recuperação e modificação de dados em colunas criptografadas

Depois de habilitar o Always Encrypted em uma conexão, você pode usar APIs de SQLSRV padrão (confira Referência da API do driver SQLSRV) ou APIs do PDO_SQLSRV (confira Referência da API do driver PDO_SQLSRV) para recuperar ou modificar dados em colunas de banco de dados criptografadas. Supondo que seu aplicativo tem as permissões de banco de dados e pode acessar a chave mestra de coluna, o driver criptografa quaisquer parâmetros de consulta que se destinam a colunas criptografadas e descriptografa os dados recuperados de colunas criptografadas, comportando-se de forma transparente para o aplicativo, como se as colunas não fossem criptografadas.

Se o Always Encrypted não estiver habilitado, as consultas com parâmetros que se destinam a colunas criptografadas falharão. Os dados ainda podem ser recuperados de colunas criptografadas, desde que a consulta não tenha parâmetros que se destinem a colunas criptografadas. No entanto, o driver não tenta descriptografar nenhuma criptografia e o aplicativo recebe os dados binários criptografados (como matrizes de bytes).

A tabela abaixo resume o comportamento das consultas dependendo se Always Encrypted está habilitado ou não:

Característica da consulta O Always Encrypted está habilitado e o aplicativo pode acessar as chaves e os metadados da chave O Sempre Criptografado está habilitado e o aplicativo não pode acessar as chaves nem os metadados da chave O Sempre Criptografado está desabilitado
Parâmetros que se destinam a colunas criptografadas. Os valores de parâmetro são criptografados de modo transparente. Erro Erro
Recuperando dados de colunas criptografadas, sem parâmetros que se destinam a colunas criptografadas. Os resultados das colunas criptografadas são descriptografados de modo transparente. O aplicativo recebe valores de coluna de texto não criptografado. Erro Os resultados das colunas criptografadas não são descriptografados. O aplicativo recebe valores criptografados como matrizes de bytes.

Os exemplos a seguir ilustram como recuperar e modificar dados em colunas criptografadas. Por exemplo, considere uma tabela com o seguinte esquema. As colunas SSN e BirthDate estão criptografadas.

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

Exemplo de inserção de dados

Os exemplos a seguir demonstram como usar os drivers SQLSRV e PDO_SQLSRV para inserir uma linha na tabela Pacientes. Observe o seguinte:

  • Não há nada específico de criptografia no código de exemplo. O driver detecta e criptografa automaticamente os valores dos parâmetros de SSN e BirthDate que se destinam a colunas criptografadas. Esse mecanismo torna a criptografia transparente para o aplicativo.
  • Os valores inseridos nas colunas de banco de dados, incluindo as colunas criptografadas, são passados como parâmetros associados. Embora o uso de parâmetros seja opcional ao enviar valores para colunas não criptografadas (mesmo que seja altamente recomendável, pois ajuda a prevenir a injeção de SQL), ele é necessário para valores que se destinam a colunas criptografadas. Se os valores inseridos nas colunas SSN ou BirthDate foram passados como literais inseridos na instrução de consulta, a consulta falha, pois o driver não tenta criptografar ou processar os literais em consultas. Como resultado, o servidor os rejeitaria como incompatíveis com as colunas criptografadas.
  • Ao inserir valores usando parâmetros de associação, um tipo SQL que é idêntico ao tipo de dados da coluna de destino ou cuja conversão para o tipo de dados da coluna de destino é compatível deve ser passado ao banco de dados. Esse requisito existe porque o Always Encrypted dá suporte a algumas conversões de tipo (para saber mais, confira Always Encrypted (Mecanismo de Banco de Dados)). Os dois drivers PHP, SQLSRV e PDO_SQLSRV, têm um mecanismo para ajudar o usuário a determinar o tipo SQL do valor. Assim, o usuário não precisa fornecer o tipo SQL explicitamente.
    • Para o driver SQLSRV, o usuário tem duas opções:
      • Confiar no driver PHP para determinar e definir o tipo SQL correto. Nesse caso, o usuário deve usar sqlsrv_prepare e sqlsrv_execute para executar uma consulta parametrizada.
      • Definir o tipo SQL explicitamente.
    • Para o driver de PDO_SQLSRV, o usuário não pode definir explicitamente o tipo SQL de um parâmetro. Ao associar um parâmetro, o driver PDO_SQLSRV ajuda automaticamente o usuário a determinar o tipo SQL.
  • Para os drivers determinarem o tipo SQL, algumas limitações se aplicam:
    • Driver SQLSRV:
      • Se o usuário quiser que o driver determine os tipos SQL para as colunas criptografadas, ele deverá usar sqlsrv_prepare e sqlsrv_execute.
      • Se sqlsrv_query for preferencial, o usuário será responsável por especificar os tipos SQL para todos os parâmetros. O tipo SQL especificado deve incluir o comprimento da cadeia de caracteres para tipos de cadeia de caracteres e a escala e precisão para tipos decimais.
    • Driver PDO_SQLSRV:
      • Não há suporte para o atributo de instrução PDO::SQLSRV_ATTR_DIRECT_QUERY em uma consulta parametrizada.
      • Não há suporte para o atributo de instrução PDO::ATTR_EMULATE_PREPARES em uma consulta parametrizada.

Driver SQLSRV e 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);

Driver SQLSRV e 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);

Driver PDO_SQLSRV e 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();

Exemplo de recuperação de dados de texto não criptografado

Os exemplos a seguir demonstram a filtragem de dados com base em valores criptografados e a recuperação de dados de texto não criptografado de colunas criptografadas usando os drivers SQLSRV e PDO_SQLSRV. Observe o seguinte:

  • O valor usado na cláusula WHERE a ser filtrado na coluna SSN precisa ser passado como um parâmetro using bind para que o driver possa criptografá-lo de modo transparente antes de enviá-lo ao servidor.
  • Ao executar uma consulta com parâmetros associados, os drivers PHP determinam automaticamente o tipo SQL para o usuário, a menos que o usuário especifique explicitamente o tipo SQL ao usar o driver SQLSRV.
  • Todos os valores impressos pelo programa estão em texto não criptografado, já que o driver descriptografa de modo transparente os dados recuperados das colunas SSN e BirthDate.

Observação

Consultas poderão executar comparações de igualdade em colunas criptografadas somente se a criptografia for determinística.

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:

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

Exemplo de recuperação de dados de texto cifrado

Se o Always Encrypted não estiver habilitado, uma consulta ainda poderá recuperar dados de colunas criptografadas, desde que a consulta não tenha parâmetros que se destinam a colunas criptografadas.

Os exemplos a seguir ilustram como recuperar dados binários criptografados de colunas criptografadas usando os drivers SQLSRV e PDO_SQLSRV. Observe o seguinte:

  • Como o Always Encrypted não está habilitado na cadeia de conexão, a consulta retorna valores criptografados de SSN e BirthDate como matrizes de bytes (o programa converte os valores em cadeias de caracteres).
  • Uma consulta que recupera dados de colunas criptografadas com o Sempre Criptografado desabilitado pode ter parâmetros, desde que nenhum dos parâmetros se destinem a uma coluna criptografada. A consulta a seguir filtra por LastName, que não é criptografado no banco de dados. Se a consulta filtrar por SSN ou BirthDate, a consulta falhará.

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:

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

Evitando problemas comuns ao consultar colunas criptografadas

Esta seção descreve as categorias comuns de erros ao consultar colunas criptografadas de aplicativos PHP e algumas diretrizes para como evitá-los.

Erros de conversão de tipo de dados sem suporte

O Always Encrypted dá suporte a algumas conversões de tipos de dados criptografados. Confira Always Encrypted (Mecanismo de Banco de Dados) para obter a lista detalhada de conversões de tipo compatíveis. Faça o seguinte para evitar erros de conversão de tipo de dados:

  • Ao usar o driver SQLSRV com sqlsrv_prepare e sqlsrv_execute, o tipo SQL é determinado automaticamente junto com o tamanho da coluna e o número de dígitos decimais do parâmetro.
  • Ao usar o driver PDO_SQLSRV para executar uma consulta, o tipo SQL com o tamanho da coluna e o número de dígitos decimais do parâmetro também é determinado automaticamente
  • Ao usar o driver SQLSRV com sqlsrv_query para executar uma consulta:
    • O tipo SQL do parâmetro é exatamente o mesmo que o tipo da coluna de destino, ou a conversão de um tipo SQL para o tipo da coluna é suportada.
    • A precisão e a escala dos parâmetros que se destinam às colunas dos tipos de dados decimal e numeric do SQL Server são iguais à precisão e à escala configuradas para a coluna de destino.
    • A precisão dos parâmetros que se destinam às colunas dos tipos de dados datetime2, datetimeoffset ou time do SQL Server não é maior que a precisão da coluna de destino, em consultas que modificam a coluna de destino.
  • Não use atributos de instrução PDO::SQLSRV_ATTR_DIRECT_QUERY ou PDO::ATTR_EMULATE_PREPARES do PDO_SQLSRV em uma consulta parametrizada

Erros devido à passagem de texto sem formatação em vez de valores criptografados

Qualquer valor que se destina a uma coluna criptografada precisa ser criptografado antes de ser enviado ao servidor. Uma tentativa de inserir, modificar ou filtrar por um valor de texto não criptografado em uma coluna criptografada resulta em um erro. Para evitar esses erros, garanta que:

  • O Always Encrypted esteja habilitado (na cadeia de conexão, defina a palavra-chave ColumnEncryption como Enabled).
  • Use o parâmetro de associação para enviar dados que se destinam a colunas criptografadas. O exemplo a seguir mostra uma consulta filtrada incorretamente por um literal/constante em uma coluna criptografada (SSN):
$query = "SELET [SSN], [FirstName], [LastName], [BirthDate] FROM [dbo].[Patients] WHERE SSN='795-73-9838'";

Controlando o impacto no desempenho do Always Encrypted

Como o Always Encrypted é uma tecnologia de criptografia do lado do cliente, a maior parte da sobrecarga de desempenho é observada no lado do cliente, não no banco de dados. Além do custo das operações de criptografia e descriptografia, as outras fontes de sobrecarga de desempenho no lado do cliente são:

  • Viagens de ida e volta adicionais ao banco de dados para recuperar metadados dos parâmetros de consulta.
  • Chamadas a um repositório de chaves mestras de coluna para acessar uma chave mestra de coluna.

Viagens de ida e volta para recuperar metadados dos parâmetros de consulta

Se o Always Encrypted estiver habilitado para uma conexão, por padrão, o ODBC Driver chamará sys.sp_describe_parameter_encryption para cada consulta parametrizada, passando a instrução de consulta (sem nenhum valor de parâmetro) para o SQL Server. Este procedimento armazenado analisa a instrução de consulta para descobrir se os parâmetros precisam ser criptografados e, se for o caso, retorna as informações relacionadas à criptografia para cada parâmetro para permitir ao driver criptografá-los.

Como os drivers PHP permitem que o usuário associe um parâmetro em uma instrução preparada sem fornecer o tipo SQL, ao associar um parâmetro em uma conexão habilitada Always Encrypted, os drivers PHP chamam o SQLDescribeParam no parâmetro para obter o tipo SQL, o tamanho da coluna e os dígitos decimais. Os metadados são usados para chamar o SQLBindParameter. Essas chamadas extras de SQLDescribeParam não exigem viagens adicionais de ida e volta ao banco de dados, pois o driver ODBC já armazenou as informações no lado do cliente quando sys.sp_describe_parameter_encryption foi chamado.

Os comportamentos anteriores garantem um alto nível de transparência ao aplicativo cliente (e o desenvolvedor do aplicativo) não precisa estar ciente de quais consultas acessam colunas criptografadas, desde que os valores que se destinam às colunas criptografadas sejam passados para o driver nos parâmetros.

Ao contrário do driver ODBC para SQL Server, ainda não há suporte nos drivers PHP para habilitação de Always Encrypted no nível da instrução/consulta.

Cache de chaves de criptografia de coluna

Para reduzir o número de chamadas a um repositório de chaves mestras de coluna para descriptografar chaves de criptografia de coluna (CEK), o driver armazena CEKs de texto não criptografado na memória. Depois de receber a CEK criptografada (ECEK) dos metadados do banco de dados, o driver do ODBC primeiro tenta encontrar a CEK de texto não criptografado correspondente ao valor da chave criptografada no cache. O driver chama o repositório de chaves que contém a CMK somente se ele não conseguir localizar a CEK de texto não criptografado correspondente no cache.

Observação: no ODBC Driver para SQL Server, as entradas no cache são removidas após um tempo limite de duas horas. Esse comportamento significa que, para determinada ECEK, o driver entra em contato com o repositório de chaves apenas uma vez durante o tempo de vida do aplicativo, ou a cada duas horas, o que for menor.

Como trabalhar com repositórios de Chave Mestra de Coluna

Para criptografar ou descriptografar dados, o driver precisa obter uma CEK que é configurada para a coluna de destino. As CEKs são armazenadas em formato criptografado (ECEKs) nos metadados do banco de dados. Cada CEK tem uma CMK correspondente que foi usada para criptografá-la. Os metadados de banco de dados não armazenam a CMK em si. Eles contêm apenas o nome do repositório de chaves e as informações que o repositório de chaves pode usar para localizar a CMK.

Para obter o valor de texto não criptografado de uma ECEK, o driver primeiro obtém os metadados sobre a CEK e sua CMK correspondente e, em seguida, usa essas informações para entrar em contato com o repositório de chaves que contém a CMK e solicitar para descriptografar a ECEK. O driver se comunica com um repositório de chaves usando um provedor de repositório de chaves.

No Microsoft Driver 5.3.0 para PHP para SQL Server, existe suporte somente para o Provedor de Repositório de Certificados do Windows e o Azure Key Vault. Ainda não há suporte para o outro Provedor de Repositório de Chaves com suporte do driver ODBC (Provedor de Repositório de Chaves Personalizado).

Uso do provedor do Repositório de Certificados do Windows

O ODBC Driver for SQL Server no Windows inclui um provedor de repositório de chaves mestras de coluna interno para o Repositório de Certificados do Windows chamado MSSQL_CERTIFICATE_STORE. (Esse provedor não está disponível no macOS ou no Linux.) Com esse provedor, a CMK é armazenada localmente no computador cliente e nenhuma outra configuração pelo aplicativo é necessária para usá-la com o driver. No entanto, o aplicativo deve ter acesso ao certificado e sua chave privada no repositório. Para obter mais informações, consulte Create and Store Column Master Keys (Always Encrypted)Criar e armazenar chaves mestras de coluna (Always Encrypted).

Como usar o Azure Key Vault

O Azure Key Vault oferece uma maneira de armazenar chaves de criptografia, senhas e outros dados confidenciais usando o Azure e pode ser usado para armazenar chaves para Always Encrypted. O ODBC Driver for SQL Server (versão 17 e posteriores) inclui um provedor de repositório de chaves mestras interno para o Azure Key Vault. As seguintes opções de conexão usam a configuração do Azure Key Vault: KeyStoreAuthentication, KeyStorePrincipalId e KeyStoreSecret.

  • KeyStoreAuthentication pode usar um dos dois valores de cadeia de caracteres possíveis: KeyVaultPassword e KeyVaultClientSecret. Esses valores controlam quais tipo de credenciais de autenticação são usadas com as outras duas palavras-chave.
  • KeyStorePrincipalId usa uma cadeia de caracteres que representa um identificador da conta que quer acessar o Azure Key Vault.
    • Se KeyStoreAuthentication estiver definido como KeyVaultPassword, então KeyStorePrincipalId deve ser o nome de um usuário do Microsoft Entra.
    • Se KeyStoreAuthentication for definido como KeyVaultClientSecret, KeyStorePrincipalId deverá ser uma ID de cliente de aplicativo.
  • KeyStoreSecret usa uma cadeia de caracteres que representa um segredo de credencial.
    • Se KeyStoreAuthentication for definido como KeyVaultPassword, KeyStoreSecret deverá ser a senha do usuário.
    • Se KeyStoreAuthentication for definido como KeyVaultClientSecret, KeyStoreSecret deverá ser o segredo do aplicativo associado à ID do cliente do aplicativo.

Todas as três opções devem estar presentes na cadeia de conexão para usar o Azure Key Vault. Além disso, ColumnEncryption precisa ser definida como Enabled. Se ColumnEncryption for definido como Disabled, mas as opções do Azure Key Vault estiverem presentes, o script continuará sem erros, mas não será executada criptografia.

Os exemplos a seguir mostram como se conectar ao SQL Server usando o Azure Key Vault.

SQLSRV:

Como usar uma conta do Microsoft Entra:

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

Usar uma ID e um segredo do cliente do aplicativo Azure:

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

PDO_SQLSRV: Como usar uma conta do Microsoft Entra:

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

Usar uma ID e um segredo do cliente do aplicativo Azure:

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

Limitações de drivers PHP ao usar o Always Encrypted

SQLSRV e PDO_SQLSRV:

  • O Linux/macOS não dá suporte ao Provedor de Repositório de Certificados do Windows
  • Forçando a criptografia de parâmetro
  • Habilitar o Always Encrypted no nível da instrução
  • Ao usar o recurso Always Encrypted e localidades não UTF8 no Linux e no macOS (como "en_US.ISO-8859-1"), a inserção de dados nulos ou uma cadeia de caracteres vazia na coluna de caracteres criptografados (n) pode não funcionar, a menos que a página de código 1252 esteja instalada em seu sistema

Somente no SQLSRV:

  • Usar sqlsrv_query como parâmetro de associação sem especificar o tipo SQL
  • Usar sqlsrv_prepare como parâmetros de associação em um lote de instruções SQL

Somente no PDO_SQLSRV:

  • O atributo de instrução PDO::SQLSRV_ATTR_DIRECT_QUERY especificado em uma consulta parametrizada
  • O atributo de instrução PDO::ATTR_EMULATE_PREPARE especificado em uma consulta parametrizada
  • parâmetros de associação em um lote de instruções SQL

Os drivers PHP também herdam as limitações impostas pelo banco de dados e pelo ODBC Driver for SQL Server. Confira Limitações do Driver ODBC ao usar Always Encrypted e Limitações do Always Encrypted.

Confira também

Guia de programação para o driver SQL de PHP
Referência da API do driver SQLSRV
Referência da API do Driver PDO_SQLSRV