在设计产品以使用Microsoft自己的产品和服务所需的相同 API、算法、协议和密钥长度时,请使用此信息作为参考。 大部分内容都基于Microsoft用于创建安全开发生命周期的内部安全标准。
非 Windows 平台上的开发人员可能会受益于这些建议。 虽然 API 和库名称可能有所不同,但涉及算法选择、密钥长度和数据保护的最佳做法在平台中相似。
安全协议、算法和密钥长度建议
TLS/SSL 版本
产品和服务应使用 TLS/SSL 的加密安全版本:
必须启用 TLS 1.3
可以启用 TLS 1.2 以提高与旧客户端的兼容性。
必须禁用 TLS 1.1、TLS 1.0、SSL 3 和 SSL 2
对称块加密、密码模式和初始化向量
块密码
对于使用对称块密码的产品:
需要高级加密标准(AES)。
所有其他块加密(包括 3DES(三重 DES/TDEA)和 RC4 都必须替换用于加密。
对于对称块加密算法,我们建议支持 256 位密钥,但允许 128 位。 建议用于新代码的唯一块加密算法是 AES(AES-128、AES-192 和 AES-256 都是可接受的,指出 AES-192 在某些处理器上缺乏优化)。
密码模式
对称算法可以在各种模式下运行,其中大多数模式将加密作链接在连续的纯文本和密码文本块上。
对称块加密应与以下密码模式之一配合使用:
其他一些密码模式(如后面的密码模式)存在实现陷阱,使得它们更有可能被错误地使用。 具体而言,必须避免电子代码簿(ECB)作模式。 在“流式加密模式”(如 CTR)中重用相同的初始化向量(IV),可能会导致显示加密数据。 如果使用以下任一模式,建议进行额外的安全评审:
输出反馈 (OFB)
密码反馈 (CFB)
计数器 (CTR)
上述“推荐”列表上没有的任何其他内容
初始化向量 (IV)
所有对称块密码还应与加密强随机数一起使用作为初始化向量。 初始化向量不应是常量或可谓词值。 有关生成加密强随机数的建议,请参阅随机数生成器。
执行多个加密作时,不应重复使用初始化向量。 重复使用可能会揭示有关加密数据的信息,尤其是在使用流式处理密码模式(如输出反馈(OFB)或计数器(CTR)时。
AES-GCM 和 AES-CCM 建议
AES-GCM(Galois/Counter Mode)和 AES-CCM(具有 CBC-MAC的计数器)被广泛使用经过身份验证的加密模式。 它们结合了保密性和完整性保护,使它们可用于安全通信。 然而,他们的脆弱性在于非重复利用。 当使用相同的 nonce(初始化向量)两次时,可能会导致灾难性后果。
建议遵循 NIST SP 800-38D 中所述的 nonce 准则、针对块密码作模式的建议:Galois/Counter Mode (GCM) 和 GMAC,特别注意有关密钥和非密钥/IV 的唯一性要求的第 8.1、8.2 和 8.3 节。
另一种方法是为每个加密的消息生成唯一的 AES-GCM/CCM 密钥,从而有效地将调用的最大数目限制为 1。 建议使用此方法对静态数据进行加密,其中使用计数器或确保可以跟踪给定密钥的最大调用数是不切实际的。
若要加密静态数据,还可以考虑将 AES-CBC 与消息身份验证代码(MAC)结合使用,作为使用 Encrypt-then-MAC 方案的替代方法,确保对加密和 MAC 使用单独的密钥。
完整性验证
加密默认提供保密性和完整性保证是一种常见的误解。 许多加密算法不提供任何完整性检查,可能容易受到篡改攻击。 必须采取额外的步骤来确保在发送和接收之前数据的完整性。
如果不能将经过身份验证的加密算法与关联的数据(例如 AES-GCM)配合使用,另一种方法是使用加密时 MAC 方案通过消息身份验证代码(MAC)验证完整性,确保对加密和 MAC 使用单独的密钥。
使用单独的密钥进行加密和 MAC 至关重要。 如果无法存储这两个密钥,有效的替代方法是使用合适的密钥派生函数(KDF),一个用于加密目的,另一个用于 MAC,从主密钥派生函数派生两个密钥。 有关详细信息,请参阅 [SP 800-108 Rev. 1, 建议使用伪random 函数进行密钥派生 |中国证监会(nist.gov)](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf.
非对称算法、密钥长度和填充模式
RSA
RSA 可用于密钥传输、密钥交换和签名。
RSA 加密应使用 OAEP 或 RSA-PSS 填充模式。
现有代码可以使用 PKCS #1 v1.5 填充模式进行签名。
不允许使用 PKCS#1 v1.5 进行加密。
不建议使用 null 填充。
2048 位密钥长度是最小值,但我们建议支持 3072 位密钥长度。
ECDSA 和 ECDH
基于 ECDH 的密钥交换和基于 ECDSA 的签名应使用三条 NIST 批准的曲线之一(P-256、P-384 或 P521)。
应将对 P-256 的支持视为最低支持,但我们建议支持 P-384。
ML-DSA
必须使用 FIPS 204 标准。 请勿在草稿标准中使用版本。
建议将 ML-DSA 与经典签名算法(即 ECDSA 或 RSA)结合使用。 使用 IETF(草稿) 或其他标准定义的组合器是互作性的首选。
对于 ML-DSA,有效的混合(复合)机制是使用经典和 ML-DSA 对相同的数据进行签名,并验证这两种数据(如果任一验证失败,验证失败)。
ML-KEM
必须使用 FIPS 203 标准。 请勿在草稿标准中使用版本。
建议使用组合器或混合加密系统组合 ML-KEM 和经典 KEM 算法(即 ECDH)。 使用 IETF(草稿) 或其他标准定义的组合器是互作性的首选。
SLH-DSA
必须使用 FIPS 205 标准。 请勿在草稿标准中使用版本。
允许所有 SLH-DSA 参数集,但建议的参数集将取决于用例。
SHA-2 和 SHAKE (SHA-3) 版本之间没有已知的安全差异
LMS 和 XMSS
支持 LMS 或 XMSS 进行签名验证是安全的。
强烈建议先咨询一位主题专家,然后再实施/部署基础结构进行签名和密钥生成。 没有已知的弱点,但人为诱发的错误是非常可能的,很容易使它变得至关重要,因为它对于正确管理状态至关重要。
整数 Diffie-Hellman
- 虽然整数 Diffie-Hellman(DH)被批准用于密钥交换,但它不是现代标准最高效的。 强烈建议改用 ECDH。
- 建议使用密钥长度 >= 2048 位
- 组参数应为已知命名组(例如 RFC 7919),或者由受信任的方生成,并在使用前进行身份验证。
密钥生存期
为所有密钥定义 加密 。
- 例如:数据加密的对称密钥(通常称为数据加密密钥或 DEK)的使用情况期限可能长达两年,用于加密数据,也称为发起方使用周期。 可以定义它具有三年以上解密的有效使用期,也称为收件人使用周期。
你应该提供一种机制,或者有一个用于替换密钥以达到有限活动生存期的过程。 在其活动生存期结束时,密钥不得用于生成新数据(例如,用于加密或签名),但仍可用于读取数据(例如,解密或验证)。
随机数生成器
当需要随机性时,所有产品和服务都应使用加密安全随机数生成器。
CNG
- 将 BCryptGenRandom 与BCRYPT_USE_SYSTEM_PREFERRED_RNG标志配合使用。
Win32/64
旧代码可以在内核模式下使用 RtlGenRandom 。
新代码应使用 BCryptGenRandom 或 CryptGenRandom。
还建议使用 C 函数 Rand_s( 在 Windows 上调用 CryptGenRandom)。
Rand_s()是兰德()的安全和高性能的替代品。
Rand() 不得用于任何加密应用程序。
.NET
PowerShell
Windows 应用商店应用
- Windows 应用商店应用可以使用 CryptographicBuffer.GenerateRandom 或 CryptographicBuffer.GenerateRandomNumber。
不建议
与随机数生成相关的不安全函数包括:rand、System.Random (.NET)、GetTickCount、GetTickCount64 和 Get-Random (PowerShell cmdlet)。
不允许使用双椭圆曲线随机数生成器(“DUAL_E_DRBG”)算法。
Windows 平台支持的加密库
在 Windows 平台上,Microsoft建议使用作系统中内置的加密 API。 在其他平台上,开发人员可能会选择评估要使用的非平台加密库。 通常,平台加密库会更频繁地更新,因为它们作为作系统的一部分交付,而不是与应用程序捆绑在一起。
有关平台与非平台加密的任何使用决策都应遵循以下要求:
该库应是当前不受已知安全漏洞支持的版本。
应支持最新的安全协议、算法和密钥长度。
(可选)该库应能够支持较旧的安全协议/算法,以便仅向后兼容。
本机代码
加密基元:如果发布在 Windows 上,请尽可能使用 CNG。
代码签名验证: WinVerifyTrust 是支持在 Windows 平台上验证代码签名的 API。
证书验证(如代码签名或 TLS/DTLS 的限制证书验证中使用的):CAPI2 API;例如 ,CertGetCertificateChain 和 CertVerifyCertificateChainPolicy。
密钥派生函数
密钥派生是从共享机密或现有加密密钥派生加密密钥材料的过程。 产品应使用建议的密钥派生函数。 从用户选择的密码或身份验证系统中存储的哈希密码派生密钥是本指南未涵盖的特殊情况:开发人员应咨询专家。
以下标准指定建议使用的 KDF 函数:
NIST SP 800-108(修订版 1):建议使用伪随机函数进行密钥派生。 具体而言,在计数器模式下使用 HMAC 作为伪随机函数的 KDF
NIST SP 800-56A(修订版 3):建议使用离散对数加密 Pair-Wise 关键建立方案。
若要从现有密钥派生密钥,请使用 BCryptKeyDerivation API 和其中一种算法:
BCRYPT_SP800108_CTR_HMAC_ALGORITHM
BCRYPT_SP80056A_CONCAT_ALGORITHM
若要从共享机密(密钥协议的输出)派生密钥,请使用具有以下算法之一的 BCryptDeriveKey API:
BCRYPT_KDF_SP80056A_CONCAT
BCRYPT_KDF_HMAC
证书验证
使用 TLS 或 DTLS 的产品应完全验证它们连接到的实体的 X.509 证书。 此过程包括验证证书的以下部分:
域名。
有效期(开始日期和到期日期)。
吊销状态。
用法(例如,服务器的“服务器身份验证”,客户端的“客户端身份验证”)。
信任链。 证书应链接到平台信任的根证书颁发机构(CA),或由管理员显式配置。
如果上述任何验证测试失败,产品应终止与实体的连接。
不要使用“自签名”证书。 自签名本身不会传达信任、支持吊销或支持密钥续订。
加密哈希函数
产品应使用 SHA-2 系列哈希算法(SHA-256、SHA-384 和 SHA-512)。 不允许出于安全目的截断加密哈希,使其小于 128 位。 虽然 SHA-256 的使用最低,但我们建议支持 SHA-384。
MAC/HMAC/键控哈希算法
消息身份验证代码(MAC)是附加到邮件的一段信息,允许其收件人使用密钥验证发件人的真实性和邮件的完整性。
建议使用 基于哈希的 MAC(HMAC) 或 基于块密码的 MAC ,前提是建议使用所有基础哈希或对称加密算法:目前,这包括 HMAC-SHA2 函数(HMAC-SHA256、HMAC-SHA384 和 HMAC-SHA512)。 虽然 HMAC-SHA256 的使用最低,但我们建议支持 HMAC-SHA384。
不建议将 HMAC 截断为小于 128 位。
设计和作注意事项
应提供一种机制来根据需要替换加密密钥。 密钥在达到活动生存期结束时或加密密钥遭到入侵后,应替换密钥。
- 每当续订证书时,都应使用新密钥续订证书(重新生成密钥)。
使用加密算法保护数据的产品应包含足够的元数据以及该内容,以支持将来迁移到不同的算法。 此元数据应包括使用的算法、键大小和填充模式。
- 有关加密敏捷性的详细信息,请参阅 “加密敏捷性”一文。
如果可用,产品应使用已建立的平台提供的加密协议,而不是重新实施它们,包括签名格式(例如,使用标准格式、现有格式)。
不要向最终用户报告加密作失败。 将错误返回到远程调用方(例如,客户端-服务器方案中的 Web 客户端或客户端)时,仅使用通用错误消息。
- 避免提供任何不必要的信息,例如直接报告范围外或长度无效错误。 仅在服务器上记录详细错误,并且仅当启用了详细日志记录时。
对于包含以下项的任何设计,强烈建议进行额外的安全评审:
主要侧重于安全性的新协议(例如身份验证或授权协议)
采用新或非标准方式使用加密的新协议。 示例注意事项包括:
实现协议的产品是否会调用任何加密 API 或方法作为协议实现的一部分?
协议是否依赖于用于身份验证或授权的任何其他协议?
协议是否会为加密元素(如密钥)定义存储格式?
不建议使用自签名证书。 使用自签名证书(如使用原始加密密钥)本身不会向用户或管理员提供任何基础来做出信任决策。
- 相比之下,使用基于受信任证书颁发机构的证书明确了依赖关联的私钥的基础,并在出现安全故障时启用吊销和更新。