Criptografia Multiplataforma no .NET

As operações criptográficas no .NET são realizadas pelas bibliotecas do sistema operacional (SO). Essa dependência tem vantagens:

  • Os aplicativos .NET se beneficiam da confiabilidade do sistema operacional. Manter bibliotecas de criptografia seguras contra vulnerabilidades é uma alta prioridade para os fornecedores de SO. Para fazer isso, eles fornecem atualizações que os administradores do sistema devem aplicar.
  • Os aplicativos .NET terão acesso a algoritmos validados por FIPS se as bibliotecas do SO forem validadas pelo FIPS.

A dependência de bibliotecas do sistema operacional também significa que os aplicativos .NET só podem usar recursos criptográficos compatíveis com o sistema operacional. Embora todas as plataformas deem suporte a determinados recursos principais, alguns recursos com suporte no .NET não podem ser usados em algumas plataformas. Este artigo identifica os recursos com suporte em cada plataforma.

Este artigo pressupõe que você tenha uma familiaridade funcional com criptografia no .NET. Para mais informações, confira Modelo de Criptografia do .NET e Serviços de Criptografia do .NET.

Algoritmos de hash

Todas as classes de algoritmo de hash e autenticação de mensagens baseada em hash (HMAC), incluindo as classes *Managed, dependem das bibliotecas do SO, com exceção do .NET no WASM do Navegador. No Navegador: WASM, SHA-1, SHA-2-256, SHA-2-384, SHA-2-512 são implementados utilizando código gerenciado.

SHA-3

O .NET 8 introduziu o suporte para os algoritmos de hash SHA-3, incluindo o SHAKE-128 e o SHAKE-256. Atualmente, o suporte a SHA-3 é dado no Windows 11 build 25324 ou posterior, e no Linux com OpenSSL 1.1.1 ou posterior.

Criptografia simétrica

As criptografias subjacentes e o encadeamento são feitos pelas bibliotecas do sistema.

Criptografia + Modo Windows Linux macOS iOS, tvOS, MacCatalyst Android
AES-CBC ✔️ ✔️ ✔️ ✔️ ✔️
AES-ECB ✔️ ✔️ ✔️ ✔️ ✔️
AES-CFB8 ✔️ ✔️ ✔️ ✔️ ✔️
AES-CFB128 ✔️ ✔️ ✔️ ✔️ ✔️
3DES-CBC ✔️ ✔️ ✔️ ✔️ ✔️
3DES-ECB ✔️ ✔️ ✔️ ✔️ ✔️
3DES-CFB8 ✔️ ✔️ ✔️ ✔️ ✔️
3DES-CFB64 ✔️ ✔️ ✔️ ✔️ ✔️
DES-CBC ✔️ ✔️ ✔️ ✔️ ✔️
DES-ECB ✔️ ✔️ ✔️ ✔️ ✔️
DES-CFB8 ✔️ ✔️ ✔️ ✔️ ✔️
RC2-CBC ✔️ ✔️ ✔️ ✔️
RC2-ECB ✔️ ✔️ ✔️ ✔️
RC2-CFB

Criptografia autenticada

O suporte à criptografia autenticada (AE) é fornecido para AES-CCM, AES-GCM e ChaCha20Poly1305 por meio das classes System.Security.Cryptography.AesCcm, System.Security.Cryptography.AesGcm e System.Security.Cryptography.ChaCha20Poly1305, respectivamente.

Como a criptografia de autenticação requer APIs de plataforma mais recentes para dar suporte ao algoritmo, o suporte pode não estar presente em todas as plataformas. A propriedade estática IsSupported nas classes do algoritmo pode ser utilizada para detectar, em runtime, se a plataforma atual dá suporte ao algoritmo ou não.

Criptografia + Modo Windows Linux macOS iOS, tvOS, MacCatalyst Android Navegador
AES-GCM ✔️ ✔️ ⚠️ ✔️
AES-CCM ✔️ ✔️ ⚠️ ✔️
ChaCha20Poly1305 Windows 10 Build 20142+ OpenSSL 1.1.0+ ⚠️ API Nível 28+

AES-CCM no macOS

No macOS, as bibliotecas do sistema não dão suporte ao AES-CCM para código de terceiros, portanto, a classe AesCcm utiliza o OpenSSL para dar suporte. Os usuários do macOS precisam obter uma cópia apropriada do OpenSSL (libcrypto) para que esse tipo funcione e ela deve estar em um caminho no qual o sistema carregaria uma biblioteca por padrão. Recomendamos que você instale o OpenSSL de um gerenciador de pacotes, como Homebrew.

As bibliotecas libcrypto.0.9.7.dylib e libcrypto.0.9.8.dylib incluídas no macOS são de versões anteriores do OpenSSL e não serão usadas. As bibliotecas libcrypto.35.dylib, libcrypto.41.dylib e libcrypto.42.dylib são do LibreSSL e não serão usadas.

AES-GCM e ChaCha20Poly1305 no macOS

O macOS não dava suporte ao AES-GCM ou ChaCha20Poly1305 até o macOS 10.15 para códigos de terceiros. Antes do .NET 8, AesGcm e ChaCha20Poly1305 têm o mesmo requisito que o AES-CCM e os usuários devem instalar o OpenSSL para que esses tipos funcionem.

A partir do .NET 8, o .NET no macOS utilizará a estrutura CryptoKit da Apple para o AES-GCM e ChaCha20Poly1305. Os usuários não precisarão instalar ou configurar nenhuma dependência adicional no AES-GCM ou ChaCha20Poly1305 no macOS.

Chaves, nonces e marcas do AES-CCM

  • Tamanhos de chave

    O AES-CCM funciona com chaves de 128, 192 e 256 bits.

  • Tamanhos de Nonce

    A classe AesCcm dá suporte a nós de 56, 64, 72, 80, 88, 96 e 104 bits (7, 8, 9, 10, 11, 12 e 13 bytes).

  • Tamanhos de marca

    A classe AesCcm dá suporte à criação ou processamento de marcas de 32, 48, 64, 80, 96, 112 e 128 bits (4, 8, 10, 12, 14 e 16 bytes).

Chaves, nonces e marcas do AES-GCM

  • Tamanhos de chave

    O AES-GCM funciona com chaves de 128, 192 e 256 bits.

  • Tamanhos de Nonce

    A classe AesGcm dá suporte apenas a nós de 96 bits (12 bytes).

  • Tamanhos de marca No Windows e no Linux, a classe AesGcm dá suporte à criação ou ao processamento de marcas de 96, 104, 112, 120 e 128 bits (12, 13, 14, 15 e 16 bytes). No macOS, o tamanho da marca é limitado a 128 bits (16 bytes) devido às limitações da estrutura do CryptoKit.

Chaves, nonces e marcas ChaCha20Poly1305.

O ChaCha20Poly1305 tem um tamanho fixo para a chave, o nonce e a marca de autenticação. O ChaCha20Poly1305 sempre usa uma chave de 256 bits, um nonce de 96 bits (12 bytes) e uma marca de 128 bits (16 bytes).

Criptografia assimétrica

Esta seção inclui as seguintes subseções:

RSA

A geração de chaves RSA (Rivest-Shamir-Adleman) é executada pelas bibliotecas do sistema operacional e está sujeita às suas limitações de tamanho e características de desempenho.

As operações de chave RSA são executadas pelas bibliotecas do SO e os tipos de chave que podem ser carregadas estão sujeitos aos requisitos do sistema operacional.

O .NET não expõe operações RSA "brutas" (não preenchidas).

O suporte ao preenchimento e resumo da mensagem variam de acordo com a plataforma:

Modo de preenchimento Windows (CNG) Linux (OpenSSL) macOS iOS, tvOS, MacCatalyst Android Windows (CAPI)
Criptografia PKCS1 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
OAEP – SHA-1 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
OAEP - SHA-2 ✔️ ✔️ ✔️ ✔️ ✔️
OAEP - SHA-32 Windows 11 Build 25324+ OpenSSL 1.1.1+
Assinatura PKCS1 (MD5, SHA-1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Assinatura PKCS1 (SHA-2) ✔️ ✔️ ✔️ ✔️ ✔️ ⚠️1
Assinatura PKCS1 (SHA-3)2 Windows 11 Build 25324+ OpenSSL 1.1.1+
PSS ✔️ ✔️ ✔️ ✔️ ✔️

1 O Windows CryptoAPI (CAPI) tem capacidade para a assinatura PKCS1 com um algoritmo SHA-2. Porém, o objeto RSA individual pode ser carregado em um CSP (provedor de serviços de criptografia) que não dá suporte a ele.

2 Exige o .NET 8.

RSA no Windows

Interoperabilidade nativa de RSA

O .NET expõe tipos para permitir que programas interoperem com as bibliotecas do sistema operacional que o código de criptografia .NET usa. Os tipos envolvidos não são convertidos entre plataformas e só devem ser usados diretamente quando necessário.

Type Windows Linux macOS iOS, tvOS, MacCatalyst Android
RSACryptoServiceProvider ✔️ ⚠️1 ⚠️1 ⚠️1 ⚠️1
RSACng ✔️
RSAOpenSsl ✔️ ⚠️2

1 Em sistemas não Windows, RSACryptoServiceProvider pode ser utilizado para compatibilidade com programas existentes. Nesse caso, qualquer método que exija interoperabilidade do SO, como abrir uma chave nomeada, gera um PlatformNotSupportedException.

2 No macOS, RSAOpenSsl funcionará se o OpenSSL estiver instalado e um libcrypto dylib apropriado puder ser encontrado por meio do carregamento de biblioteca dinâmica. Se uma biblioteca apropriada não puder ser encontrada, serão geradas exceções.

ECDSA

A geração de chaves ECDSA (Algoritmo de Assinatura Digital da Curva Elíptica) é feita pelas bibliotecas do SO e está sujeita às suas limitações de tamanho e características de desempenho.

As curvas de chave ECDSA são definidas pelas bibliotecas do SO e estão sujeitas às respectivas limitações.

Curva elíptica Windows 10 Windows 7 a 8.1 Linux macOS iOS, tvOS, MacCatalyst Android
NIST P-256 (secp256r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-384 (secp384r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-521 (secp521r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Curvas de brainpool (como curvas nomeadas) ✔️ ⚠️1 ⚠️4
Outras curvas nomeadas ⚠️2 ⚠️1 ⚠️4
Curvas explícitas ✔️ ✔️ ✔️
Exportar ou importar como explícito ✔️ 3 ✔️ 3 3 ✔️

1 Nem todas as distribuições Linux têm suporte para as mesmas curvas nomeadas.

2 O suporte para curvas nomeadas foi adicionado ao CNG do Windows no Windows 10. Para mais informações, confira Curvas elípticas nomeadas do CNG. As curvas nomeadas não estão disponíveis em versões anteriores do Windows, exceto por três curvas no Windows 7.

3 A exportação com parâmetros de curva explícitos exige suporte da biblioteca do SO, que não está disponível nas plataformas com suporte da Apple ou em versões anteriores do Windows.

4 O suporte do Android para algumas curvas depende da versão do Android. Os distribuidores do Android também podem optar por adicionar ou remover as curvas da sua build do Android.

Interoperabilidade nativa ECDSA

O .NET expõe tipos para permitir que programas interoperem com as bibliotecas do sistema operacional que o código de criptografia .NET usa. Os tipos envolvidos não se traduzem entre plataformas e só devem ser usados diretamente quando necessário.

Type Windows Linux macOS iOS, tvOS, MacCatalyst Android
ECDsaCng ✔️
ECDsaOpenSsl ✔️ ⚠️*

* No macOS, ECDsaOpenSsl funciona se o OpenSSL está instalado no sistema e uma libcrypto dylib apropriada pode ser encontrada por meio do carregamento de biblioteca dinâmica. Se uma biblioteca apropriada não puder ser encontrada, serão geradas exceções.

ECDH

A geração de chave ECDH (Diffie-Hellman de curva elíptica) é feita pelas bibliotecas do SO e está sujeita às respectivas limitações de tamanho e características de desempenho.

A classe ECDiffieHellman dá suporte ao valor "bruto" da computação ECDH, bem como por meio das seguintes funções de derivação de chave:

  • HASH(Z)
  • HASH(prepend || Z || append)
  • HMAC(key, Z)
  • HMAC(key, prepend || Z || append)
  • HMAC(Z, Z)
  • HMAC(Z, prepend || Z || append)
  • Tls11Prf(label, seed)

A derivação de chave "Bruta" foi introduzida no .NET 8.

As curvas de chave ECDH são definidas pelas bibliotecas do sistema operacional e estão sujeitas às respectivas limitações.

Curva elíptica Windows 10 Windows 7 a 8.1 Linux macOS iOS, tvOS, MacCatalyst Android
NIST P-256 (secp256r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-384 (secp384r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-521 (secp521r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Curvas de brainpool (como curvas nomeadas) ✔️ ⚠️1 ⚠️4
Outras curvas nomeadas ⚠️2 ⚠️1 ⚠️4
Curvas explícitas ✔️ ✔️ ✔️
Exportar ou importar como explícito ✔️ 3 ✔️ 3 3 ✔️

1 Nem todas as distribuições Linux têm suporte para as mesmas curvas nomeadas.

2 O suporte para curvas nomeadas foi adicionado ao CNG do Windows no Windows 10. Para mais informações, confira Curvas elípticas nomeadas do CNG. As curvas nomeadas não estão disponíveis em versões anteriores do Windows, exceto por três curvas no Windows 7.

3 A exportação com parâmetros de curva explícitos exige suporte da biblioteca do SO, que não está disponível nas plataformas com suporte da Apple ou em versões anteriores do Windows.

4 O suporte do Android para algumas curvas depende da versão do Android. Os distribuidores do Android também podem optar por adicionar ou remover as curvas da sua build do Android.

Interoperabilidade nativa de ECDH

O .NET expõe tipos para permitir que programas interoperem com as bibliotecas do SO que o .NET usa. Os tipos envolvidos não se traduzem entre plataformas e só devem ser usados diretamente quando necessário.

Type Windows Linux macOS iOS, tvOS, MacCatalyst Android
ECDiffieHellmanCng ✔️
ECDiffieHellmanOpenSsl ✔️ ⚠️*

* No macOS, ECDiffieHellmanOpenSsl funcionará se o OpenSSL estiver instalado e um libcrypto dylib apropriado puder ser encontrado por meio do carregamento de biblioteca dinâmica. Se uma biblioteca apropriada não puder ser encontrada, serão geradas exceções.

DSA

A geração de chaves DSA (Algoritmo de Assinatura Digital) é executada pelas bibliotecas do sistema e está sujeita às suas limitações de tamanho e características de desempenho.

Função Windows CNG Linux macOS Windows CAPI iOS, tvOS, MacCatalyst Android
Criação de chave (<= 1024 bits) ✔️ ✔️ ✔️ ✔️
Criação de chave (> 1024 bits) ✔️ ✔️ ✔️
Carregar chaves (<= 1024 bits) ✔️ ✔️ ✔️ ✔️ ✔️
Carregar chaves (> 1024 bits) ✔️ ✔️ ⚠️* ✔️
FIPS 186-2 ✔️ ✔️ ✔️ ✔️ ✔️
FIPS 186-3 (assinaturas SHA-2) ✔️ ✔️ ✔️

* O macOS carrega chaves DSA maiores que 1024 bits, mas o comportamento dessas chaves é indefinido. Elas não se comportam de acordo com o FIPS 186-3.

DSA no Windows

Interoperabilidade nativa de DSA

O .NET expõe tipos para permitir que programas interoperem com as bibliotecas do sistema operacional que o código de criptografia .NET usa. Os tipos envolvidos não se traduzem entre plataformas e só devem ser usados diretamente quando necessário.

Type Windows Linux macOS iOS, tvOS, MacCatalyst Android
DSACryptoServiceProvider ✔️ ⚠️1 ⚠️1 ⚠️1
DSACng ✔️
DSAOpenSsl ✔️ ⚠️2

1 Em sistemas não Windows, DSACryptoServiceProvider pode ser utilizado para compatibilidade com programas existentes. Nesse caso, qualquer método que exija interoperabilidade do sistema, como abrir uma chave nomeada, gerará um PlatformNotSupportedException.

2 No macOS, DSAOpenSsl funcionará se o OpenSSL estiver instalado e um libcrypto dylib apropriado puder ser encontrado por meio do carregamento de biblioteca dinâmica. Se uma biblioteca apropriada não puder ser encontrada, serão geradas exceções.

Certificados X.509

A maioria do suporte para certificados X.509 no .NET vem de bibliotecas do SO. Para carregar um certificado em uma instância X509Certificate2 ou X509Certificate no .NET, o certificado deve ser carregado pela biblioteca do sistema operacional subjacente.

Ler um PKCS12/PFX

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Vazio ✔️ ✔️ ✔️ ✔️ ✔️
Um certificado, sem chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Um certificado, com chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, sem chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, uma chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, várias chaves privadas ✔️ ✔️ ✔️ ✔️ ✔️

Gravar um PKCS12/PFX

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Vazio ✔️ ✔️ ✔️ ✔️ ✔️
Um certificado, sem chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Um certificado, com chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, sem chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, uma chave privada ✔️ ✔️ ✔️ ✔️ ✔️
Vários certificados, várias chaves privadas ✔️ ✔️ ✔️ ✔️ ✔️
Carregamento efêmero ✔️ ✔️ ✔️ ✔️

O macOS não pode carregar chaves privadas de certificado sem um objeto de conjunto de chaves, o que requer gravação em disco. Os keychains são criados automaticamente para carregamento PFX e são excluídos quando não estão mais em uso. Como a opção X509KeyStorageFlags.EphemeralKeySet significa que a chave privada não deve ser gravada no disco, afirmar que o sinalizador no macOS resulta em um PlatformNotSupportedException.

Gravar uma coleção de certificados PKCS7

O Windows e o Linux emitem blobs PKCS7 codificados em DER. O macOS emite blobs PKCS7 codificados por CER indefinidos.

X509Store

No Windows, a classe X509Store é uma representação das APIs do Repositório de Certificados do Windows. Essas APIs funcionam da mesma forma no .NET Core e no .NET 5 que no .NET Framework.

Em sistemas não Windows, a classe X509Store é uma projeção das decisões de confiança do sistema (somente leitura), das decisões de confiança do usuário (leitura/gravação) e do armazenamento de chaves do usuário (leitura/gravação).

As tabelas a seguir mostram quais cenários têm suporte em cada plataforma. Para cenários sem suporte (❌ nas tabelas), um CryptographicException é gerado.

A minha loja

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Abrir CurrentUser\My (ReadOnly) ✔️ ✔️ ✔️ ✔️ ✔️
Abrir CurrentUser\My (ReadWrite) ✔️ ✔️ ✔️ ✔️ ✔️
Abrir CurrentUser\My (ExistingOnly) ✔️ ⚠️ ✔️ ✔️ ✔️
Abrir LocalMachine\My ✔️ ✔️ ✔️ ✔️

No Linux, as lojas são criadas na primeira gravação e nenhum armazenamento de usuário existe por padrão, portanto, abrir CurrentUser\My com ExistingOnly pode falhar.

No macOS, o repositório CurrentUser\My é o conjunto de chaves padrão do usuário, que é login.keychain por padrão. O repositório LocalMachine\My é System.keychain.

O repositório Raiz

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Abrir CurrentUser\Root (ReadOnly) ✔️ ✔️ ✔️ ✔️
Abrir CurrentUser\Root (ReadWrite) ✔️ ✔️
Abrir CurrentUser\Root (ExistingOnly) ✔️ ⚠️ ✔️ (se ReadOnly) ✔️ (se ReadOnly)
Abrir LocalMachine\Root (ReadOnly) ✔️ ✔️ ✔️ ✔️
Abrir LocalMachine\Root (ReadWrite) ✔️
Abrir LocalMachine\Root (ExistingOnly) ✔️ ⚠️ ✔️ (se ReadOnly) ✔️ (se ReadOnly)

No Linux, o repositório LocalMachine\Root é uma interpretação do pacote de AC no caminho padrão para OpenSSL.

No macOS, o repositório CurrentUser\Root é uma interpretação dos resultados SecTrustSettings do domínio de confiança do usuário. O repositório LocalMachine\Root é uma interpretação dos resultados SecTrustSettings para os domínios de confiança do administrador e do sistema.

O repositório intermediário

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Abrir CurrentUser\Intermediate (ReadOnly) ✔️ ✔️ ✔️
Abrir CurrentUser\Intermediate (ReadWrite) ✔️ ✔️
Abrir CurrentUser\Intermediate (ExistingOnly) ✔️ ⚠️ ✔️ (se ReadOnly)
Abrir LocalMachine\Intermediate (ReadOnly) ✔️ ✔️ ✔️
Abrir LocalMachine\Intermediate (ReadWrite) ✔️
Abrir LocalMachine\Intermediate (ExistingOnly) ✔️ ⚠️ ✔️ (se ReadOnly)

No Linux, o repositório CurrentUser\Intermediate é usado como um cache ao baixar CAs intermediárias por seus registros de acesso às informações da autoridade em builds X509Chain bem-sucedidos. O repositório LocalMachine\Intermediate é uma interpretação do pacote de AC no caminho padrão para OpenSSL.

No macOS, o repositório CurrentUser\Intermediate é tratado como um repositório personalizado. Os certificados adicionados a esse repositório não afetam a compilação de cadeias X.509.

O repositório não permitido

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Abrir CurrentUser\Disallowed (ReadOnly) ✔️ ⚠️ ✔️ ✔️ ✔️
Abrir CurrentUser\Disallowed (ReadWrite) ✔️ ⚠️
Abrir CurrentUser\Disallowed (ExistingOnly) ✔️ ⚠️ ✔️ (se ReadOnly) ✔️ (se ReadOnly) ✔️ (se ReadOnly)
Abrir LocalMachine\Disallowed (ReadOnly) ✔️ ✔️ ✔️ ✔️
Abrir LocalMachine\Disallowed (ReadWrite) ✔️
Abrir LocalMachine\Disallowed (ExistingOnly) ✔️ ✔️ (se ReadOnly) ✔️ (se ReadOnly) ✔️ (se ReadOnly)

No Linux, o repositório Disallowed não é usado na criação de cadeias e tentar adicionar conteúdo a ele resulta em um CryptographicException. Um CryptographicException será gerado ao abrir o repositório Disallowed se ele já tiver adquirido conteúdo.

No macOS, os repositórios CurrentUser\Disallowed e LocalMachine\Disallowed são interpretações dos resultados apropriados do SecTrustSettings para certificados cuja confiança está definida como Always Deny.

Repositório inexistente

Cenário Windows Linux macOS iOS, tvOS, MacCatalyst Android
Abrir repositório inexistente (ExistingOnly)
Abrir repositório inexistente CurrentUser (ReadWrite) ✔️ ✔️ ⚠️
Abrir repositório inexistente LocalMachine (ReadWrite) ✔️

No macOS, há suporte para a criação de repositório personalizado com a API X509Store apenas para o local CurrentUser. Ele criará um conjunto de chaves sem senha no diretório do conjunto de chaves do usuário (~/Library/Keychains). Para criar um conjunto de chaves com senha, um P/Invoke a SecKeychainCreate pode ser usado. Da mesma forma, SecKeychainOpen pode ser usado para abrir conjuntos de chaves em locais diferentes. O resultado IntPtr pode ser passado para new X509Store(IntPtr) para obter um repositório com capacidade de leitura/gravação, sujeito às permissões do usuário atual.

X509Chain

O macOS não dá suporte à utilização de CRL offline, portanto, X509RevocationMode.Offline é tratado como X509RevocationMode.Online.

O macOS não dá suporte a um tempo limite iniciado pelo usuário na CRL (Lista de Certificados Revogados)/OCSP (Protocolo de Status de Certificado Online)/AIA (acesso às informações da autoridade) baixando, portanto, X509ChainPolicy.UrlRetrievalTimeout é ignorado.

Recursos adicionais