Microsoft SDL 加密建议

在设计产品时,使用此信息作为参考,以使用 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。

对于对称块加密算法,最小密钥长度为 128 位,但我们建议支持 256 位密钥。 建议用于新代码的唯一分组加密算法是 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 的重复使用。 当使用相同的 nonce(初始化向量)两次时,可能会导致灾难性后果。

建议遵循 NIST SP 800-38D,关于分组加密操作模式的建议:Galois/计数器模式 (GCM) 和 GMAC 中所述的 nonce 指导原则,特别注意第 8.3 节中关于最大调用次数的规定。

另一个选项将为加密的每个消息生成唯一的 AES-GCM/CCM 密钥,从而有效地将调用的最大数目限制为 1。 建议使用这种方法对静态数据进行加密,因为在这种情况下,使用计数器或确保可以跟踪给定密钥的最大调用次数是不切实际的。

对于静态数据的加密,也可以考虑使用 AES-CBC 和消息验证码 (MAC),作为加密-然后-MAC 方案的替代方案,确保加密和 MAC 使用不同的密钥。

完整性验证

加密默认提供保密性和完整性保证是一种常见的误解。 许多加密算法不提供任何完整性检查,可能容易受到篡改攻击。 必须采取额外的步骤来确保在发送和接收之前数据的完整性。

如果不能将经过身份验证的加密算法与关联的数据(例如 AES-GCM)配合使用,替代方法是使用加密时 MAC 方案通过消息身份验证代码(MAC)验证完整性,确保对加密和 MAC 使用单独的密钥。

使用单独的密钥进行加密和 MAC 至关重要。 如果无法存储这两个密钥,一个有效的替代方法是使用合适的密钥推导函数 (KDF),从主密钥中推导出两个密钥,一个用于加密,另一个用于 MAC。 有关详细信息,请参阅 SP 800-108 Rev. 1,关于使用伪随机函数提取密钥的建议 | CSRC (nist.gov)

非对称算法、密钥长度和填充模式

RSA

  • RSA 可用于加密、密钥交换和签名。
  • RSA 加密应使用 OAEP 或 RSA-PSS 填充模式。
  • 现有代码只能出于兼容目的使用 PKCS #1 v1.5 填充模式。
  • 不建议使用 null 填充。
  • 建议至少使用 2048 位密钥长度,但我们建议支持 3072 位密钥长度。

ECDSA 和 ECDH

  • 基于 ECDH 的密钥交换和基于 ECDSA 的签名应使用三条 NIST 批准的曲线之一(P-256、P-384 或 P521)。
  • 应将对 P-256 的支持视为最低支持,但我们建议支持 P-384。

整数 Diffie-Hellman

  • 建议使用密钥长度 >= 2048 位
  • 组参数应为已知命名组(例如,RFC 7919),或者由受信任的方生成,并在使用前进行身份验证。

密钥生存期

  • 为所有密钥定义加密
    • 例如:数据加密的对称密钥(通常称为数据加密密钥或 DEK)的使用情况期限可能长达两年,用于加密数据,也称为发起方使用周期。 可以定义它具有额外三年的解密有效使用期,也称为接受方使用周期。
  • 你应该提供密钥替换机制或建立密钥替换流程,以实现有限的有效生存期。 在其活动生存期结束时,密钥不得用于生成新数据(例如,用于加密或签名),但仍可用于读取数据(例如,解密或验证)。

随机数生成器

当需要随机性时,所有产品和服务都应使用加密安全的随机数生成器。

CNG

  • BCryptGenRandom 与BCRYPT_USE_SYSTEM_PREFERRED_RNG 标志配合使用。

Win32/64

.NET

PowerShell

Windows 应用商店应用程序

Linux/macOS

  • /dev/urandom 设备提供随机数据的加密强源,getrandom(2) 系统调用也一样。

Windows 平台支持的加密库

在 Windows 平台上,Microsoft 建议使用操作系统内置的加密 API。 在其他平台上,开发人员可能会选择评估要使用的非平台加密库。 通常,平台加密库的更新更频繁,因为它们作为操作系统的一部分提供,而不是与应用程序捆绑在一起。

关于平台与非平台加密的任何使用决策均应遵循以下要求:

  • 该库应该是最新的受支持版本,没有已知的安全漏洞。
  • 应该支持最新的安全协议、算法和密钥长度。
  • (可选)该库应仅在需要向后兼容时才支持较旧的安全协议/算法。

本机代码

托管代码 (.NET)

密钥派生功能

密钥派生是从共享机密或现有加密密钥派生加密密钥材料的过程。 产品应使用推荐的密钥派生功能。 从用户选择的密码或从身份验证系统中存储的哈希密码派生密钥是本指南未涵盖的特殊情况;开发人员应咨询专家。

以下标准指定了建议使用的 KDF 功能:

若要从现有密钥派生密钥,请将 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 或方法吗?
      • 协议是否依赖用于身份验证或授权的任何其他协议?
      • 协议会为加密元素(例如密钥)定义存储格式吗?
  • 不建议使用自签名证书。 自签名证书的使用与原始加密密钥一样,本质上不为用户或管理员提供任何进行信任决策的依据。
    • 相比之下,使用基于受信任证书颁发机构的证书明确了依赖关联的私钥的基础,并在出现安全故障时启用吊销和更新。