.NET 中的跨平台加密
.NET 中的加密操作由操作系统 (OS) 库完成。 此依赖项具有以下优势:
- .NET 应用程序从操作系统可靠性中获益。 对于 OS 供应商而言,确保加密函式库安全应该高度优先考虑。 为此,它们提供了系统管理员应该应用的更新。
- 如果 OS 库是 FIPS 验证的,则 .NET 应用有权访问经过 FIPS 验证的算法。
对 OS 库的依赖也意味着,.NET 应用只能使用操作系统支持的加密功能。 虽然所有平台都支持某些核心功能,但 .NET 支持的某些功能无法在某些平台上使用。 本文列出了每个平台支持的功能。
本文假设您已熟悉如何在 .NET 中进行加密。 有关详细信息,请参阅 .Net 加密模型和 .NET 加密服务。
哈希和消息身份验证算法
除浏览器 WASM 上的 .NET 外,所有哈希算法和基于哈希的消息身份验证 (HMAC) 类(包括 *Managed
类)都遵从操作系统库。 在浏览器 WASM 中,SHA-1、SHA-2-256、SHA-2-384、SHA-2-512 和 HMAC 等效项使用托管代码实现。
算法 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android | 浏览器 |
---|---|---|---|---|---|---|
MD5 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
SHA-1 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
SHA-2-256 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
SHA-2-384 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
SHA-2-512 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
SHA-3-256 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
SHA-3-384 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
SHA-3-512 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
SHAKE-128 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+2 | ❌ | ❌ | ❌ | ❌ |
SHAKE-256 | Windows 11 内部版本 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 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
HMAC-SHA-3-384 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
HMAC-SHA-3-512 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
KMAC-1281 | Windows 11 内部版本 26016+ | OpenSSL 3.0+ | ❌ | ❌ | ❌ | ❌ |
KMAC-2561 | Windows 11 内部版本 26016+ | OpenSSL 3.0+ | ❌ | ❌ | ❌ | ❌ |
KMAC-XOF-1281 | Windows 11 内部版本 26016+ | OpenSSL 3.0+ | ❌ | ❌ | ❌ | ❌ |
KMAC-XOF-2561 | Windows 11 内部版本 26016+ | OpenSSL 3.0+ | ❌ | ❌ | ❌ | ❌ |
1从 .NET 9 开始可用。
从 .NET 9 开始,可以使用 2个流式扩展输出函数 (XOF)。 在 Linux 上,这需要 OpenSSL 3.3。
对称加密
基础密码和链接由系统库完成。
密码 + 模式 | 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 | ❌ | ❌ | ❌ | ❌ | ❌ |
已验证加密
分别通过 System.Security.Cryptography.AesCcm、System.Security.Cryptography.AesGcm 和 System.Security.Cryptography.ChaCha20Poly1305 类为 AES-CCM、AES-GCM 和 ChaCha20Poly1305 提供经过身份验证的加密 (AE) 支持。
由于经过身份验证的加密需要较新的平台 API 来支持算法,因此并非所有平台上都存在支持。 算法类上的 IsSupported
静态属性可用于在运行时检测当前平台是否支持该算法。
密码 + 模式 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android | 浏览器 |
---|---|---|---|---|---|---|
AES-GCM | ✔️ | ✔️ | ✔️ | ⚠️ | ✔️ | ❌ |
AES-CCM | ✔️ | ✔️ | ⚠️ | ❌ | ✔️ | ❌ |
ChaCha20Poly1305 | Windows 10 内部版本 20142+ | OpenSSL 1.1.0+ | ✔️ | ⚠️ | API 级别 28+ | ❌ |
macOS 上的 AES-CCM
在 macOS 上,系统库不支持第三方代码的 AES-CCM,因此 AesCcm 类使用 OpenSSL 提供支持。 MacOS 上的用户需要获取 OpenSSL (libcrypto) 的相应副本,此类型才能正常工作,并且它必须位于系统默认加载库的路径中。 建议从包管理器(如 Homebrew)安装 OpenSSL。
MacOS 中包含的 libcrypto.0.9.7.dylib
和 libcrypto.0.9.8.dylib
库来自早期版本的 OpenSSL,不会使用。 libcrypto.35.dylib
、 libcrypto.41.dylib
和 libcrypto.42.dylib
库来自 LibreSSL,不会使用。
iOS、tvOS 和 MacCatalyst 上的 AES-GCM 和 ChaCha20Poly1305
从 iOS 和 tvOS 13.0 及更高版本以及所有版本的 MacCatalyst 上的 .NET 9 开始,均支持 AES-GCM 和 ChaCha20Poly1305。
AES-CCM 密钥、nonce 和标记
密钥大小
AES-CCM 适用于 128、192 和 256 位密钥。
Nonce 大小
AesCcm 类支持 56、64、72、80、88、96和 104 位(7、8、9、10、11、12 和 13 字节)nonce。
标记大小
AesCcm 类支持创建或处理 32、48、64、80、96、112 和 128 位(4、8、10、12、14 和 16 字节)标记。
AES-GCM 密钥、nonce 和标记
密钥大小
AES-GCM 适用于 128、192 和 256 位密钥。
Nonce 大小
AesGcm 类仅支持 96 位 (12 字节) nonce。
对于 Windows 和 Linux 上的标记大小,AesGcm 类支持创建或处理 96、104、112、120 和 128 位(12、13、14、15 和 16 字节)标记。 在 Apple 平台上,由于 CryptoKit 框架的限制,标记大小限制为 128 位(16 字节)。
ChaCha20Poly1305 密钥、nonce 和标记。
ChaCha20Poly1305 具有固定大小的密钥、nonce 和身份验证标记。 ChaCha20Poly1305 始终使用 256 位密钥、96 位(12 字节)nonce 和 128 位(16 字节)标记。
非对称加密
本节包括下列小节:
RSA
RSA (Rivest-Shamir-Adleman) 密钥生成由 OS 库执行,并受其大小限制和性能特征的限制。
RSA 密钥操作由 OS 库执行,可以加载的密钥类型受 OS 要求的限制。
.NET 不会公开“原始”(未填充)RSA 操作。
填充和摘要支持因平台而异:
填充模式 | Windows (CNG) | Linux (OpenSSL) | macOS | iOS、tvOS、MacCatalyst | Android | Windows (CAPI) |
---|---|---|---|---|---|---|
PKCS1 加密 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
OAEP - SHA-1 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
OAEP - SHA-2 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
OAEP - SHA-3 | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
PKCS1 签名 (MD5、SHA-1) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
PKCS1 签名 (SHA-2) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ⚠️1 |
PKCS1 签名 (SHA-3) | Windows 11 内部版本 25324+ | OpenSSL 1.1.1+ | ❌ | ❌ | ❌ | ❌ |
PSS | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
1 Windows CryptoAPI (CAPI) 能够使用 SHA-2 算法进行 PKCS1 签名。 但是,单个 RSA 对象可能加载到不支持它的加密服务提供程序 (CSP) 中。
RSA on Windows
- 使用
new RSACryptoServiceProvider()
时,使用 Windows CryptoAPI (CAPI)。 - 使用
new RSACng()
时,使用 Windows Cryptography API Next Generation (CNG)。 - 由 RSA.Create 返回的对象由 Windows CNG 内部提供支持。 使用 Windows CNG 是一个实现细节,可能会更改。
- X509Certificate2 的 GetRSAPublicKey 扩展方法返回实例 RSACng。 使用 RSACng 是一个实现细节,可能会更改。
- 当前 X509Certificate2 的 GetRSAPrivateKey 扩展方法首选 实例RSACng,但如果 RSACng 无法打开密钥,将尝试 RSACryptoServiceProvider。 首选的提供程序是一个实现细节,可能会更改。
RSA 本机互操作
.NET 公开类型以允许程序与 .NET 加密代码使用的 OS 库进行互操作。 所涉及的类型不会在平台之间转换,只应在必要时直接使用。
类型 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
RSACryptoServiceProvider | ✔️ | ⚠️1 | ⚠️1 | ⚠️1 | ⚠️1 |
RSACng | ✔️ | ❌ | ❌ | ❌ | ❌ |
RSAOpenSsl | ❌ | ✔️ | ⚠️2 | ❌ | ❌ |
1 在非 Windows 上,RSACryptoServiceProvider 可用于与现有程序兼容。 在这种情况下,任何需要 OS 互操作的方法(如打开命名密钥)都会引发 PlatformNotSupportedException。
2 在 macOS 上,如果安装了 OpenSSL,并且可以通过动态库加载找到相应的 libcrypto dylib,则 RSAOpenSsl 有效。 如果找不到相应的库,将引发异常。
ECDSA
ECDSA(椭圆曲线数字签名算法) 密钥生成由 OS 库完成,并受其大小限制和性能特征的限制。
ECDSA 密钥曲线由 OS 库定义,并受其限制。
椭圆曲线 | 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 曲线(命名曲线) | ✔️ | ❌ | ⚠️1 | ❌ | ❌ | ⚠️4 |
其他命名曲线 | ⚠️2 | ❌ | ⚠️1 | ❌ | ❌ | ⚠️4 |
显式曲线 | ✔️ | ❌ | ✔️ | ❌ | ❌ | ✔️ |
显式导出或导入 | ✔️ | ❌3 | ✔️ | ❌3 | ❌3 | ✔️ |
1 Linux 分发版并不都支持相同的命名曲线。
2 对命名曲线的支持已添加到 Windows CNG Windows 10。 有关详细信息,请参阅 CNG 命名椭圆曲线。 命名曲线在早期版本的 Windows 中不可用,Windows 7 中的三条曲线除外。
3 使用显式曲线参数导出需要 OS 库支持,在 Apple 平台或早期版本的 Windows 上不可用。
4 Android 对某些曲线的支持取决于 Android 版本。 Android 分销商也可以选择在其 Android 版本中添加或删除曲线。
RSA 本机互操作
.NET 公开类型以允许程序与 .NET 加密代码使用的 OS 库进行互操作。 所涉及的类型不会在平台之间转换,只应在必要时直接使用。
类型 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
ECDsaCng | ✔️ | ❌ | ❌ | ❌ | ❌ |
ECDsaOpenSsl | ❌ | ✔️ | ⚠️* | ❌ | ❌ |
* 在 macOS 上,如果安装了 OpenSSL,并且可以通过动态库加载找到相应的 libcrypto dylib,则 ECDsaOpenSsl 有效。 如果找不到相应的库,将引发异常。
ECDH
ECDSA(椭圆曲线数字签名算法)密钥生成由 OS 库完成,并受其大小限制和性能特征的限制。
ECDiffieHellman 类支持 ECDH 计算的“原始”值,以及通过以下密钥派生函数提供支持:
- HASH(Z)
- HASH (前||Z ||追加)
- HMAC (键,Z)
- HMAC (键,前||Z ||追加)
- HMAC (Z、Z)
- HASH (Z、前||Z ||追加)
- Tls11Prf (标签、种子)
ECDSA 密钥曲线由 OS 库定义,并受其限制。
椭圆曲线 | 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 曲线(命名曲线) | ✔️ | ❌ | ⚠️1 | ❌ | ❌ | ⚠️4 |
其他命名曲线 | ⚠️2 | ❌ | ⚠️1 | ❌ | ❌ | ⚠️4 |
显式曲线 | ✔️ | ❌ | ✔️ | ❌ | ❌ | ✔️ |
显式导出或导入 | ✔️ | ❌3 | ✔️ | ❌3 | ❌3 | ✔️ |
1 Linux 分发版并不都支持相同的命名曲线。
2 对命名曲线的支持已添加到 Windows CNG Windows 10。 有关详细信息,请参阅 CNG 命名椭圆曲线。 命名曲线在早期版本的 Windows 中不可用,Windows 7 中的三条曲线除外。
3 使用显式曲线参数导出需要 OS 库支持,在 Apple 平台或早期版本的 Windows 上不可用。
4 Android 对某些曲线的支持取决于 Android 版本。 Android 分销商也可以选择在其 Android 版本中添加或删除曲线。
ECDH 本机互操作
.NET 公开类型以允许程序与 .NET 使用的 OS 库进行互操作。 所涉及的类型不会在平台之间转换,只应在必要时直接使用。
类型 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
ECDiffieHellmanCng | ✔️ | ❌ | ❌ | ❌ | ❌ |
ECDiffieHellmanOpenSsl | ❌ | ✔️ | ⚠️* | ❌ | ❌ |
*在 macOS 上,如果安装了 OpenSSL,并且可以通过动态库加载找到相应的 libcrypto dylib,则 ECDiffieHellmanOpenSsl 有效。 如果找不到相应的库,将引发异常。
DSA
DSA(数字签名算法)密钥生成由系统库完成,并受其大小限制和性能特征的限制。
函数 | Windows CNG | Linux | macOS | Windows CAPI | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|---|
密钥创建 (<= 1024 位) | ✔️ | ✔️ | ❌ | ✔️ | ❌ | ✔️ |
密钥创建 (> 1024 位) | ✔️ | ✔️ | ❌ | ❌ | ❌ | ✔️ |
加载密钥 (<= 1024 位) | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
加载密钥 (>= 1024 位) | ✔️ | ✔️ | ⚠️* | ❌ | ❌ | ✔️ |
FIPS 186-2 | ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
FIPS 186-3 (SHA-2 签名) | ✔️ | ✔️ | ❌ | ❌ | ❌ | ✔️ |
* macOS 加载大于 1024 位的 DSA 密钥,但这些密钥的行为不确定。 它们的行为与 FIPS 186-3 不符。
DSA on Windows
- 使用
new DSACryptoServiceProvider()
时,使用 Windows CryptoAPI (CAPI)。 - 使用
new DSACng()
时,使用 Windows Cryptography API Next Generation (CNG)。 - 由 DSA.Create 返回的对象由 Windows CNG 内部提供支持。 使用 Windows CNG 是一个实现细节,可能会更改。
- X509Certificate2 的 GetDSAPublicKey 扩展方法返回实例 DSACng。 使用 DSACng 是一个实现细节,可能会更改。
- X509Certificate2 的 GetDSAPrivateKey 扩展方法首选实例 DSACng,但如果 DSACng 无法打开密钥,将尝试 DSACryptoServiceProvider。 首选的提供程序是一个实现细节,可能会更改。
DSA 本机互操作
.NET 公开类型以允许程序与 .NET 加密代码使用的 OS 库进行互操作。 所涉及的类型不会在平台之间转换,只应在必要时直接使用。
类型 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
DSACryptoServiceProvider | ✔️ | ⚠️1 | ⚠️1 | ❌ | ⚠️1 |
DSACng | ✔️ | ❌ | ❌ | ❌ | ❌ |
DSAOpenSsl | ❌ | ✔️ | ⚠️2 | ❌ | ❌ |
1 在非 Windows 上,DSACryptoServiceProvider 可用于与现有程序兼容。 在这种情况下,任何需要系统互操作的方法(如打开命名密钥)都会引发 PlatformNotSupportedException。
2 在 macOS 上,如果安装了 OpenSSL,并且可以通过动态库加载找到相应的 libcrypto dylib,则 DSAOpenSsl 有效。 如果找不到相应的库,将引发异常。
X.509 证书
对于 .NET 中的 X.509 证书,大多数支持都来自 OS 库。 若要将证书加载到 .NET 中的 X509Certificate2 或 X509Certificate 实例,证书必须由基础 OS 库加载。
读取 PKCS12/PFX
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
空 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
一个证书,无私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
一个证书,带私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,无私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,一个私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,多个私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
编写 PKCS12/PFX
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
空 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
一个证书,无私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
一个证书,带私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,无私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,一个私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
多个证书,多个私钥 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
暂时加载 | ✔️ | ✔️ | ❌ | ✔️ | ✔️ |
macOS 无法加载没有密钥链对象的证书私钥,这需要写入磁盘。 密钥链是自动创建的,用于 PFX 加载,在不再使用时被删除。 由于 X509KeyStorageFlags.EphemeralKeySet 选项意味着不应将私钥写入磁盘,因此在 macOS 上断言该标志会导致 PlatformNotSupportedException。
写入 PKCS7 证书集合
Windows 和 Linux 都发出 DER 编码的 PKCS7 blob。 macOS 发出无限长度 CER 编码的 PKCS7 blob。
X509Store
在 Windows 上,X509Store 类表示 Windows 证书存储区 API。 这些 API 在 .NET Core 和 .NET 5 中的工作方式与在 .NET Framework 中的工作方式相同。
在非 Windows 上,X509Store 类是系统信任决策(只读)、用户信任决策(读写),以及用户密钥存储(读写)的预测。
下表显示了每个平台支持的方案。 对于不受支持的方案(表中的 ❌),将引发 CryptographicException。
我的应用商店
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
打开 CurrentUser\My (ReadOnly) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
打开 CurrentUser\My (ReadWrite) | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
打开 CurrentUser\My (ExistingOnly) | ✔️ | ⚠️ | ✔️ | ✔️ | ✔️ |
打开 LocalMachine\My | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
在 Linux 上,存储是在首次写入时创建的,默认情况下不存在用户存储区,因此打开 CurrentUser\My
时 ExistingOnly
可能会失败。
在 macOS 上,CurrentUser\My
存储是用户的默认密钥链,默认情况下为 login.keychain
。 LocalMachine\My
存储区是 System.keychain
。
根存储区
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
打开 CurrentUser\Root (ReadOnly) | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
打开 CurrentUser\Root (ReadWrite) | ✔️ | ✔️ | ❌ | ❌ | ❌ |
打开 CurrentUser\Root (ExistingOnly) | ✔️ | ⚠️ | 如果为 ReadOnly,则✔️ | ❌ | 如果为 ReadOnly,则✔️ |
打开 LocalMachine\Root (ReadOnly) | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |
打开 LocalMachine\Root (ReadWrite) | ✔️ | ❌ | ❌ | ❌ | ❌ |
打开 LocalMachine\Root (ExistingOnly) | ✔️ | ⚠️ | 如果为 ReadOnly,则✔️ | ❌ | 如果为 ReadOnly,则✔️ |
在 Linux 上,LocalMachine\Root
存储是 OpenSSL 的默认路径中的 CA 捆绑包的解释。
在 macOS 上,CurrentUser\Root
存储是用户信任域 SecTrustSettings
结果的解释。 在 macOS 上,LocalMachine\Root
存储是管理员和系统信任域 SecTrustSettings
结果的解释。
中间存储
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
打开 CurrentUser\Intermediate (ReadOnly) | ✔️ | ✔️ | ✔️ | ❌ | ❌ |
打开 CurrentUser\Intermediate (ReadWrite) | ✔️ | ✔️ | ❌ | ❌ | ❌ |
打开 CurrentUser\Intermediate (ExistingOnly) | ✔️ | ⚠️ | 如果为 ReadOnly,则✔️ | ❌ | ❌ |
打开 LocalMachine\Intermediate (ReadOnly) | ✔️ | ✔️ | ✔️ | ❌ | ❌ |
打开 LocalMachine\Intermediate (ReadWrite) | ✔️ | ❌ | ❌ | ❌ | ❌ |
打开 LocalMachine\Intermediate (ExistingOnly) | ✔️ | ⚠️ | 如果为 ReadOnly,则✔️ | ❌ | ❌ |
在 Linux 上,当通过其授权信息访问记录在成功的 X509Chain 生成下载中间 CA 时,CurrentUser\Intermediate
存储将用作缓存。 LocalMachine\Intermediate
存储是 OpenSSL 的默认路径中的 CA 捆绑包的解释。
在 macOS 上,CurrentUser\Intermediate
存储被视为自定义存储。 添加到此存储的证书不会影响 X.509 链构建。
禁止存储
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
打开 CurrentUser\Disallowed (ReadOnly) | ✔️ | ⚠️ | ✔️ | ✔️ | ✔️ |
打开 CurrentUser\Disallowed (ReadWrite) | ✔️ | ⚠️ | ❌ | ❌ | ❌ |
打开 CurrentUser\Disallowed (ExistingOnly) | ✔️ | ⚠️ | 如果为 ReadOnly,则✔️ | 如果为 ReadOnly,则✔️ | 如果为 ReadOnly,则✔️ |
打开 LocalMachine\Disallowed (ReadOnly) | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
打开 LocalMachine\Disallowed (ReadWrite) | ✔️ | ❌ | ❌ | ❌ | ❌ |
打开 LocalMachine\Disallowed (ExistingOnly) | ✔️ | ❌ | 如果为 ReadOnly,则✔️ | 如果为 ReadOnly,则✔️ | 如果为 ReadOnly,则✔️ |
在 Linux 上,不在链生成中使用该 Disallowed
存储区,尝试向其添加内容会导致 CryptographicException。 如果存储区已经获取内容,打开 Disallowed
存储,则会引发 CryptographicException。
在 macOS 上,CurrentUser\Disallowed 和 LocalMachine\Disallowed 存储是对其信任设置为 Always Deny
的证书的相应 SecTrustSettings 结果的解释。
不存在的存储
方案 | Windows | Linux | macOS | iOS、tvOS、MacCatalyst | Android |
---|---|---|---|---|---|
打开不存在的存储 (ExistingOnly) | ❌ | ❌ | ❌ | ❌ | ❌ |
打开 CurrentUser 不存在的存储 (ReadWrite) | ✔️ | ✔️ | ⚠️ | ❌ | ❌ |
打开 LocalMachine 不存在的存储 (ReadWrite) | ✔️ | ❌ | ❌ | ❌ | ❌ |
在 macOS 上,只支持在 CurrentUser
位置创建具有 X509STORE API 的自定义存储。 它将创建一个新的密钥链,在用户的密钥链目录中没有密码 (~/Library/Keychains)。 若要创建具有密码的密钥链,可以为 SecKeychainCreate
使用 P/Invoke。 同样,SecKeychainOpen
可用于在不同位置打开密钥链。 根据当前用户的权限,可以将生成的 IntPtr
传递给 new X509Store(IntPtr)
,以获取支持读写存储。
X509Chain
macOS 不支持脱机 CRL 使用率,因此 X509RevocationMode.Offline
将被视为 X509RevocationMode.Online
。
macOS 不支持在 CRL(证书吊销列表)/OCSP(联机证书状态协议) /AIA(授权信息访问)下载时出现用户启动的超时,因此 X509ChainPolicy.UrlRetrievalTimeout
会被忽略。