Edit

Share via


Cross-Platform Cryptography in .NET

Cryptographic operations in .NET are done by operating system (OS) libraries. This dependency has advantages:

  • .NET apps benefit from OS reliability. Keeping cryptography libraries safe from vulnerabilities is a high priority for OS vendors. To do that, they provide updates that system administrators should be applying.
  • .NET apps have access to FIPS-validated algorithms if the OS libraries are FIPS-validated.

The dependency on OS libraries also means that .NET apps can only use cryptographic features that the OS supports. While all platforms support certain core features, some features that .NET supports can't be used on some platforms. This article identifies the features that are supported on each platform.

This article assumes you have a working familiarity with cryptography in .NET. For more information, see .NET Cryptography Model and .NET Cryptographic Services.

Hash and Message Authentication Algorithms

All hash algorithm and hash-based message authentication (HMAC) classes, including the *Managed classes, defer to the OS libraries with the exception of .NET on Browser WASM. In Browser WASM, SHA-1, SHA-2-256, SHA-2-384, SHA-2-512 and the HMAC equivalents are implemented using managed code.

Algorithm Windows Linux macOS iOS, tvOS, MacCatalyst Android Browser
MD5 ✔️ ✔️ ✔️ ✔️ ✔️
SHA-1 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
SHA-2-256 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
SHA-2-384 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
SHA-2-512 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
SHA-3-256 Windows 11 Build 25324+ OpenSSL 1.1.1+
SHA-3-384 Windows 11 Build 25324+ OpenSSL 1.1.1+
SHA-3-512 Windows 11 Build 25324+ OpenSSL 1.1.1+
SHAKE-128 Windows 11 Build 25324+ OpenSSL 1.1.1+2
SHAKE-256 Windows 11 Build 25324+ OpenSSL 1.1.1+2
HMAC-MD5 ✔️ ✔️ ✔️ ✔️ ✔️
HMAC-SHA-1 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
HMAC-SHA-2-256 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
HMAC-SHA-2-384 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
HMAC-SHA-2-512 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
HMAC-SHA-3-256 Windows 11 Build 25324+ OpenSSL 1.1.1+
HMAC-SHA-3-384 Windows 11 Build 25324+ OpenSSL 1.1.1+
HMAC-SHA-3-512 Windows 11 Build 25324+ OpenSSL 1.1.1+
KMAC-1281 Windows 11 Build 26016+ OpenSSL 3.0+
KMAC-2561 Windows 11 Build 26016+ OpenSSL 3.0+
KMAC-XOF-1281 Windows 11 Build 26016+ OpenSSL 3.0+
KMAC-XOF-2561 Windows 11 Build 26016+ OpenSSL 3.0+

1Available starting in .NET 9.

2Streaming extensible output function (XOF) is available starting in .NET 9. On Linux, this requires OpenSSL 3.3.

Symmetric encryption

The underlying ciphers and chaining are done by the system libraries.

Cipher + Mode 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

Authenticated encryption

Authenticated encryption (AE) support is provided for AES-CCM, AES-GCM, and ChaCha20Poly1305 via the System.Security.Cryptography.AesCcm, System.Security.Cryptography.AesGcm, and System.Security.Cryptography.ChaCha20Poly1305 classes, respectively.

Since authenticated encryption requires newer platform APIs to support the algorithm, support may not be present on all platforms. The IsSupported static property on the classes for the algorithm can be used to detect at runtime if the current platform supports the algorithm or not.

Cipher + Mode Windows Linux macOS iOS, tvOS, MacCatalyst Android Browser
AES-GCM ✔️ ✔️ ✔️ ⚠️ ✔️
AES-CCM ✔️ ✔️ ✔️
ChaCha20Poly1305 Windows 10 Build 20142+ OpenSSL 1.1.0+ ✔️ ⚠️ API Level 28+

AES-CCM on macOS

Prior to .NET 10, AES-CCM worked if a supported version of OpenSSL was present and the dynamic library loader could locate it. OpenSSL support on macOS was removed in .NET 10.

AES-GCM and ChaCha20Poly1305 on iOS, tvOS, and MacCatalyst

Support for AES-GCM and ChaCha20Poly1305 is available starting in .NET 9 on iOS and tvOS 13.0 and later, and all versions of MacCatalyst.

AES-CCM keys, nonces, and tags

  • Key Sizes

    AES-CCM works with 128, 192, and 256-bit keys.

  • Nonce Sizes

    The AesCcm class supports 56, 64, 72, 80, 88, 96, and 104-bit (7, 8, 9, 10, 11, 12, and 13-byte) nonces.

  • Tag Sizes

    The AesCcm class supports creating or processing 32, 48, 64, 80, 96, 112, and 128-bit (4, 8, 10, 12, 14, and 16-byte) tags.

AES-GCM keys, nonces, and tags

  • Key Sizes

    AES-GCM works with 128, 192, and 256-bit keys.

  • Nonce Sizes

    The AesGcm class supports only 96-bit (12-byte) nonces.

  • Tag Sizes On Windows and Linux, the AesGcm class supports creating or processing 96, 104, 112, 120, and 128-bit (12, 13, 14, 15, and 16-byte) tags. On Apple platforms, the tag size is limited to 128-bit (16-byte) due to limitations of the CryptoKit framework.

ChaCha20Poly1305 keys, nonces, and tags.

ChaCha20Poly1305 has a fixed size for the key, nonce, and authentication tag. ChaCha20Poly1305 always uses a 256-bit key, a 96-bit (12-byte) nonce, and 128-bit (16-byte) tag.

Asymmetric cryptography

This section includes the following subsections:

RSA

RSA (Rivest–Shamir–Adleman) key generation is performed by the OS libraries and is subject to their size limitations and performance characteristics.

RSA key operations are performed by the OS libraries, and the types of key that can be loaded are subject to OS requirements.

.NET does not expose "raw" (unpadded) RSA operations.

Padding and digest support vary by platform:

Padding Mode Windows (CNG) Linux (OpenSSL) macOS iOS, tvOS, MacCatalyst Android Windows (CAPI)
PKCS1 Encryption ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
OAEP - SHA-1 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
OAEP - SHA-2 ✔️ ✔️ ✔️ ✔️ ✔️
OAEP - SHA-3 Windows 11 Build 25324+ OpenSSL 1.1.1+
PKCS1 Signature (MD5, SHA-1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
PKCS1 Signature (SHA-2) ✔️ ✔️ ✔️ ✔️ ✔️ ⚠️1
PKCS1 Signature (SHA-3) Windows 11 Build 25324+ OpenSSL 1.1.1+
PSS ✔️ ✔️ ✔️ ✔️ ✔️

1 Windows CryptoAPI (CAPI) is capable of PKCS1 signature with a SHA-2 algorithm. But the individual RSA object may be loaded in a cryptographic service provider (CSP) that doesn't support it.

RSA on Windows

RSA native interop

.NET exposes types to allow programs to interoperate with the OS libraries that the .NET cryptography code uses. The types involved do not translate between platforms, and should only be directly used when necessary.

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

1 On non-Windows, RSACryptoServiceProvider can be used for compatibility with existing programs. In that case, any method that requires OS interop, such as opening a named key, throws a PlatformNotSupportedException.

2 On macOS, prior to .NET 10, RSAOpenSsl worked if OpenSSL was installed and an appropriate libcrypto dylib could be found via dynamic library loading. This support was removed in .NET 10.

ECDSA

ECDSA (Elliptic Curve Digital Signature Algorithm) key generation is done by the OS libraries and is subject to their size limitations and performance characteristics.

ECDSA key curves are defined by the OS libraries and are subject to their limitations.

Elliptic Curve Windows 10 Windows 7 - 8.1 Linux macOS iOS, tvOS, MacCatalyst Android
NIST P-256 (secp256r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-384 (secp384r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-521 (secp521r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Brainpool curves (as named curves) ✔️ ⚠️1 ⚠️4
Other named curves ⚠️2 ⚠️1 ⚠️4
Explicit curves ✔️ ✔️ ✔️
Export or import as explicit ✔️ 3 ✔️ 3 3 ✔️

1 Linux distributions don't all have support for the same named curves.

2 Support for named curves was added to Windows CNG in Windows 10. For more information, see CNG Named Elliptic Curves. Named curves are not available in earlier versions of Windows, except for three curves in Windows 7.

3 Exporting with explicit curve parameters requires OS library support, which is not available on Apple platforms or earlier versions of Windows.

4 Android support for some curves depends on the Android version. Android distributors may choose to add or remove curves from their Android build as well.

ECDSA Native Interop

.NET exposes types to allow programs to interoperate with the OS libraries that the .NET cryptography code uses. The types involved don't translate between platforms and should only be directly used when necessary.

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

* On macOS, prior to .NET 10, ECDsaOpenSsl worked if OpenSSL was installed and an appropriate libcrypto dylib could be found via dynamic library loading. This support was removed in .NET 10.

ECDH

ECDH (Elliptic Curve Diffie-Hellman) key generation is done by the OS libraries and is subject to their size limitations and performance characteristics.

The ECDiffieHellman class supports the "raw" value of the ECDH computation as well as through the following key derivation functions:

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

ECDH key curves are defined by the OS libraries and are subject to their limitations.

Elliptic Curve Windows 10+ Windows 7 - 8.1 Linux macOS iOS, tvOS, MacCatalyst Android
NIST P-256 (secp256r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-384 (secp384r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
NIST P-521 (secp521r1) ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Brainpool curves (as named curves) ✔️ ⚠️1 ⚠️4
Other named curves ⚠️2 ⚠️1 ⚠️4
Explicit curves ✔️ ✔️ ✔️
Export or import as explicit ✔️ 3 ✔️ 3 3 ✔️

1 Linux distributions don't all have support for the same named curves.

2 Support for named curves was added to Windows CNG in Windows 10. For more information, see CNG Named Elliptic Curves. Named curves are not available in earlier versions of Windows, except for three curves in Windows 7.

3 Exporting with explicit curve parameters requires OS library support, which is not available on Apple platforms or earlier versions of Windows.

4 Android support for some curves depends on the Android version. Android distributors may choose to add or remove curves from their Android build as well.

ECDH native interop

.NET exposes types to allow programs to interoperate with the OS libraries that .NET uses. The types involved don't translate between platforms and should only be directly used when necessary.

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

* On macOS, prior to .NET 10, ECDiffieHellmanOpenSsl worked if OpenSSL was installed and an appropriate libcrypto dylib could be found via dynamic library loading. This support was removed in .NET 10.

DSA

DSA (Digital Signature Algorithm) key generation is performed by the system libraries and is subject to their size limitations and performance characteristics.

Function Windows CNG Linux macOS Windows CAPI iOS, tvOS, MacCatalyst Android
Key creation (<= 1024 bits) ✔️ ✔️ ✔️ ✔️
Key creation (> 1024 bits) ✔️ ✔️ ✔️
Loading keys (<= 1024 bits) ✔️ ✔️ ✔️ ✔️ ✔️
Loading keys (> 1024 bits) ✔️ ✔️ ⚠️* ✔️
FIPS 186-2 ✔️ ✔️ ✔️ ✔️ ✔️
FIPS 186-3 (SHA-2 signatures) ✔️ ✔️ ✔️

* macOS loads DSA keys bigger than 1024 bits, but the behavior of those keys is undefined. They don't behave according to FIPS 186-3.

DSA on Windows

DSA native interop

.NET exposes types to allow programs to interoperate with the OS libraries that the .NET cryptography code uses. The types involved don't translate between platforms and should only be directly used when necessary.

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

1 On non-Windows, DSACryptoServiceProvider can be used for compatibility with existing programs. In that case, any method that requires system interop, such as opening a named key, throws a PlatformNotSupportedException.

2 On macOS, prior to .NET 10, DSAOpenSsl worked if OpenSSL was installed and an appropriate libcrypto dylib could be found via dynamic library loading. This support was removed in .NET 10.

Post-quantum cryptography

Post-quantum algorithms are available starting in .NET 10. They're also available for .NET Framework using the Microsoft.Bcl.Cryptography NuGet package. The following support table indicates the platform support for the built-in operating system cryptographic components, such as those created from Generate or ImportFromPem. Implementations that derive from the base class might have different support behaviors.

For the built-in algorithms, an IsSupported static property is available to determine if the platform supports any of the parameter sets.

The native interop types for post-quantum algorithms do not support key generation or importing. They exist specifically for interop scenarios with the native platform types, such as an EVP_PKEY on OpenSSL or CngKey on Windows.

ML-KEM

Algorithm Windows Linux Apple Android Browser
ML-KEM-512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
ML-KEM-768 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
ML-KEM-1024 Windows 11 Insiders (Latest) OpenSSL 3.5.0+

Native interop ML-KEM

ML-DSA

ML-DSA has a pure and prehash variant (HashML-DSA). The following table reflects both the pure and prehash variants.

Algorithm Windows Linux Apple Android Browser
ML-DSA-44 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
ML-DSA-65 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
ML-DSA-87 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
ML-DSA-44 External Mu (μ)1 OpenSSL 3.5.0+
ML-DSA-65 External Mu (μ)1 OpenSSL 3.5.0+
ML-DSA-87 External Mu (μ)1 OpenSSL 3.5.0+

1 External Mu support is for signing and verifying Mu only. Computation of Mu isn't supported.

Native interop ML-DSA

SLH-DSA

SLH-DSA has a pure and prehash variant (HashSLH-DSA). The following table reflects both the pure and prehash variants.

Algorithm Windows Linux Apple Android Browser
SLH-DSA-SHA2-128f OpenSSL 3.5.0+
SLH-DSA-SHA2-128s OpenSSL 3.5.0+
SLH-DSA-SHA2-192f OpenSSL 3.5.0+
SLH-DSA-SHA2-192s OpenSSL 3.5.0+
SLH-DSA-SHA2-256f OpenSSL 3.5.0+
SLH-DSA-SHA2-256s OpenSSL 3.5.0+
SLH-DSA-SHAKE-128f OpenSSL 3.5.0+
SLH-DSA-SHAKE-128s OpenSSL 3.5.0+
SLH-DSA-SHAKE-192f OpenSSL 3.5.0+
SLH-DSA-SHAKE-192s OpenSSL 3.5.0+
SLH-DSA-SHAKE-256f OpenSSL 3.5.0+
SLH-DSA-SHAKE-256s OpenSSL 3.5.0+

Native interop SLH-DSA

Composite ML-DSA

Algorithm Windows Linux Apple Android Browser
MLDSA44-RSA2048-PSS-SHA256 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA44-RSA2048-PKCS15-SHA256 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA44-Ed25519-SHA512
MLDSA44-ECDSA-P256-SHA256 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-RSA3072-PSS-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-RSA3072-PKCS15-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-RSA4096-PSS-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-RSA4096-PKCS15-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-ECDSA-P256-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-ECDSA-P384-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-ECDSA-brainpoolP256r1-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA65-Ed25519-SHA512
MLDSA87-ECDSA-P384-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA87-ECDSA-brainpoolP384r1-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA87-Ed448-SHAKE256
MLDSA87-RSA3072-PSS-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA87-RSA4096-PSS-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+
MLDSA87-ECDSA-P521-SHA512 Windows 11 Insiders (Latest) OpenSSL 3.5.0+

Native interop composite ML-DSA

X.509 Certificates

The majority of support for X.509 certificates in .NET comes from OS libraries. To load a certificate into an X509Certificate2 or X509Certificate instance in .NET, the certificate must be loaded by the underlying OS library.

Read a PKCS12/PFX

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Empty ✔️ ✔️ ✔️ ✔️ ✔️
One certificate, no private key ✔️ ✔️ ✔️ ✔️ ✔️
One certificate, with private key ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, no private keys ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, one private key ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, multiple private keys ✔️ ✔️ ✔️ ✔️ ✔️

Write a PKCS12/PFX

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Empty ✔️ ✔️ ✔️ ✔️ ✔️
One certificate, no private key ✔️ ✔️ ✔️ ✔️ ✔️
One certificate, with private key ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, no private keys ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, one private key ✔️ ✔️ ✔️ ✔️ ✔️
Multiple certificates, multiple private keys ✔️ ✔️ ✔️ ✔️ ✔️
Ephemeral loading ✔️ ✔️ ✔️ ✔️

macOS can't load certificate private keys without a keychain object, which requires writing to disk. Keychains are created automatically for PFX loading, and are deleted when no longer in use. Since the X509KeyStorageFlags.EphemeralKeySet option means that the private key should not be written to disk, asserting that flag on macOS results in a PlatformNotSupportedException.

Write a PKCS7 certificate collection

Windows and Linux both emit DER-encoded PKCS7 blobs. macOS emits indefinite-length-CER-encoded PKCS7 blobs.

X509Store

On Windows, the X509Store class is a representation of the Windows Certificate Store APIs. Those APIs work the same in .NET Core and .NET 5 as they do in .NET Framework.

On non-Windows, the X509Store class is a projection of system trust decisions (read-only), user trust decisions (read-write), and user key storage (read-write).

The following tables show which scenarios are supported in each platform. For unsupported scenarios (❌ in the tables), a CryptographicException is thrown.

The My store

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Open CurrentUser\My (ReadOnly) ✔️ ✔️ ✔️ ✔️ ✔️
Open CurrentUser\My (ReadWrite) ✔️ ✔️ ✔️ ✔️ ✔️
Open CurrentUser\My (ExistingOnly) ✔️ ⚠️ ✔️ ✔️ ✔️
Open LocalMachine\My ✔️ ✔️ ✔️ ✔️

On Linux, stores are created on first write, and no user stores exist by default, so opening CurrentUser\My with ExistingOnly may fail.

On macOS, the CurrentUser\My store is the user's default keychain, which is login.keychain by default. The LocalMachine\My store is System.keychain.

The Root store

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Open CurrentUser\Root (ReadOnly) ✔️ ✔️ ✔️ ✔️
Open CurrentUser\Root (ReadWrite) ✔️ ✔️
Open CurrentUser\Root (ExistingOnly) ✔️ ⚠️ ✔️ (if ReadOnly) ✔️ (if ReadOnly)
Open LocalMachine\Root (ReadOnly) ✔️ ✔️ ✔️ ✔️
Open LocalMachine\Root (ReadWrite) ✔️
Open LocalMachine\Root (ExistingOnly) ✔️ ⚠️ ✔️ (if ReadOnly) ✔️ (if ReadOnly)

On Linux, the LocalMachine\Root store is an interpretation of the CA bundle in the default path for OpenSSL.

On macOS, the CurrentUser\Root store is an interpretation of the SecTrustSettings results for the user trust domain. The LocalMachine\Root store is an interpretation of the SecTrustSettings results for the admin and system trust domains.

The Intermediate store

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Open CurrentUser\Intermediate (ReadOnly) ✔️ ✔️ ✔️
Open CurrentUser\Intermediate (ReadWrite) ✔️ ✔️
Open CurrentUser\Intermediate (ExistingOnly) ✔️ ⚠️ ✔️ (if ReadOnly)
Open LocalMachine\Intermediate (ReadOnly) ✔️ ✔️ ✔️
Open LocalMachine\Intermediate (ReadWrite) ✔️
Open LocalMachine\Intermediate (ExistingOnly) ✔️ ⚠️ ✔️ (if ReadOnly)

On Linux, the CurrentUser\Intermediate store is used as a cache when downloading intermediate CAs by their Authority Information Access records on successful X509Chain builds. The LocalMachine\Intermediate store is an interpretation of the CA bundle in the default path for OpenSSL.

On macOS, the CurrentUser\Intermediate store is treated as a custom store. Certificates added to this store do not affect X.509 chain building.

The Disallowed store

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Open CurrentUser\Disallowed (ReadOnly) ✔️ ⚠️ ✔️ ✔️ ✔️
Open CurrentUser\Disallowed (ReadWrite) ✔️ ⚠️
Open CurrentUser\Disallowed (ExistingOnly) ✔️ ⚠️ ✔️ (if ReadOnly) ✔️ (if ReadOnly) ✔️ (if ReadOnly)
Open LocalMachine\Disallowed (ReadOnly) ✔️ ✔️ ✔️ ✔️
Open LocalMachine\Disallowed (ReadWrite) ✔️
Open LocalMachine\Disallowed (ExistingOnly) ✔️ ✔️ (if ReadOnly) ✔️ (if ReadOnly) ✔️ (if ReadOnly)

On Linux, the Disallowed store is not used in chain building, and attempting to add contents to it results in a CryptographicException. A CryptographicException is thrown when opening the Disallowed store if it has already acquired contents.

On macOS, the CurrentUser\Disallowed and LocalMachine\Disallowed stores are interpretations of the appropriate SecTrustSettings results for certificates whose trust is set to Always Deny.

Nonexistent store

Scenario Windows Linux macOS iOS, tvOS, MacCatalyst Android
Open non-existent store (ExistingOnly)
Open CurrentUser non-existent store (ReadWrite) ✔️ ✔️ ⚠️
Open LocalMachine non-existent store (ReadWrite) ✔️

On macOS, custom store creation with the X509Store API is supported only for CurrentUser location. It will create a new keychain with no password in the user's keychain directory (~/Library/Keychains). To create a keychain with password, a P/Invoke to SecKeychainCreate could be used. Similarly, SecKeychainOpen could be used to open keychains in different locations. The resulting IntPtr can be passed to new X509Store(IntPtr) to obtain a read/write-capable store, subject to the current user's permissions.

X509Chain

macOS doesn't support Offline CRL utilization, so X509RevocationMode.Offline is treated as X509RevocationMode.Online.

macOS doesn't support a user-initiated timeout on CRL (Certificate Revocation List) / OCSP (Online Certificate Status Protocol) / AIA (Authority Information Access) downloading, so X509ChainPolicy.UrlRetrievalTimeout is ignored.

Post-quantum cryptography certificates and PKCS12/PFX

Post-quantum certificate support also requires support from the primitive algorithm.

Operation Algorithm Windows Linux Apple Android Browser
PKCS#12 Import ML-DSA ✔️ ✔️
PKCS#12 Export ML-DSA ✔️ ✔️
Private Key Association ML-DSA ✔️ ✔️
 
PKCS#12 Import ML-KEM ✔️
PKCS#12 Export ML-KEM ✔️
Private Key Association ML-KEM ✔️
 
PKCS#12 Import SLH-DSA ✔️
PKCS#12 Export SLH-DSA ✔️
Private Key Association SLH-DSA ✔️

Additional resources