Microsoft SDL 加密建议

简介

本文档包含有关在 Microsoft 平台上使用加密的建议和最佳做法。 此处的大部分内容转述或源自 Microsoft 创建安全开发生命周期所采用的内部安全标准。 在设计产品以使用 Microsoft 对其自身产品和服务所要求的 API、算法、协议和密钥长度时,可参考本文档。

非 Windows 平台上的开发人员也可以从这些建议中受益。 尽管 API 和库的名称可能不同,但涉及算法选择、密钥长度和数据保护的最佳做法在各个平台上都相似。

安全协议、算法和密钥长度建议

SSL/TLS 版本

产品和服务应使用 SSL/TLS 的加密安全版本:

  • 应启用 TLS 1.2

  • 仅在需要向后兼容时才启用 TLS 1.1 和 TLS 1.0

  • 默认情况下应禁用 SSL 3 和 SSL 2

对称分组加密、密码模式和初始化向量

分组加密

使用对称块加密法的产品:

  • 建议为新代码使用高级加密标准 (AES)。

  • 为了向后兼容,允许在现有代码中使用三重数据加密标准 (3DES)。

  • 其他所有分组加密,包括 RC2、DES、双重密钥 3DES、DESX 和 Skipjack,只能用于解密旧数据,用于加密时应改用其他算法。

对于对称分组加密算法,建议至少指定 128 位的密钥长度。 建议用于新代码的唯一分组加密算法是 AES(AES-128、AES-192 和 AES-256 都可以接受,注意 AES-192 缺少对某些处理器的优化)。 如果已在现有代码中使用三重密钥 3DES,则可接受该算法;建议过渡到 AES。 行业不再认为 DES、DESX、RC2 和 Skipjack 是安全的。 只能出于向后兼容的目的将这些算法用于解密现有数据,应使用建议的分组加密重新加密数据。

密码模式

对称算法可以在多种模式下运行,其中大多数模式将对连续纯文本和密文块的加密操作链接在一起。

对称分组加密应与以下密码模式之一结合使用:

如下所示的其他密码模式在实施上存在缺陷,因此更有可能被误用。 特别是,应避免使用电子码簿 (ECB) 操作模式。 对采用“流加密法模式”的分组加密(例如 CTR)重复使用相同的初始化向量 (IV) 可能会导致泄露已加密的数据。 如果使用以下任一模式,建议执行额外的安全审查:

  • 输出反馈 (OFB)

  • 密码反馈 (CFB)

  • 计数器 (CTR)

  • 带 CBC-MAC 的计数器 (CCM)

  • Galois/计数器模式 (GCM)

  • 上面的“建议”列表中没有的其他模式

初始化向量 (IV)

所有对称分组加密还应与加密强度高的随机数一起用作初始化向量。 初始化向量绝不能为常量值。 有关如何生成加密强度高的随机数的建议,请参阅《随机数生成器》。

执行多个加密操作时,切勿重复使用初始化向量,因为这会泄露正在加密的数据的相关信息,尤其是在使用输出反馈 (OFB) 或计数器 (CTR) 等流加密法模式时。

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

RSA

  • RSA 应该用于加密、密钥交换和签名。

  • RSA 加密应使用 OAEP 或 RSA-PSS 填充模式。 现有代码应仅使用 PKCS #1 v1.5 填充模式实现兼容性。

  • 不建议使用 null 填充。

  • 建议密钥 >= 2048 位

ECDSA

  • 建议使用密钥 >= 256 位的 ECDSA

  • 基于 ECDSA 的签名应使用 NIST 批准的三种曲线算法之一(P-256、P-384 或 P521)。

ECDH

  • 建议使用密钥 >= 256 位的 ECDH

  • 基于 ECDH 的密钥交换应使用 NIST 批准的三种曲线算法之一(P-256、P-384 或 P521)。

整数 Diffie-Hellman

  • 建议密钥长度 >= 2048 位

  • 组参数应该是众所周知的命名组(例如 RFC 7919),或者由受信任方生成并在使用前进行身份验证

密钥生存期

  • 所有非对称密钥的生存期最长为 5 年,建议生存期为 1 年。

  • 所有对称密钥的生存期最长为 3 年;建议生存期为 1 年。

  • 你应该提供密钥替换机制或建立密钥替换流程,以实现有限的有效生存期。 有效生存期结束后,密钥不得用于生成新数据(例如,用于加密或签名),但仍可用于读取数据(例如,用于解密或验证)。

随机数生成器

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

CNG

CAPI

Win32/64

  • 旧代码可以在内核模式下使用 RtlGenRandom

  • 新代码应使用 BCryptGenRandomCryptGenRandom

  • 建议在 Windows 上调用 CryptGenRandom) 的 C 函数 Rand_s ( ()

  • Rand_s () 是兰德 () 的安全且高性能的替代项。 Rand() 不得用于任何加密应用程序,只能用于内部测试。

  • 对于内核模式代码,建议使用 SystemPrng 函数。

.NET

Windows 应用商店应用程序

不建议使用

Windows 平台支持的加密库

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

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

  1. 该库应该是最新的受支持版本,没有已知的安全漏洞

  2. 应该支持最新的安全协议、算法和密钥长度

  3. (可选)该库应仅在需要向后兼容时才支持较旧的安全协议/算法

本机代码

托管代码

  • 加密基元:使用 System.Security.Cryptography 命名空间中定义的 API - 首选 CNG 类。

  • 使用可用的最新版 .Net Framework。 至少应为 .Net Framework 4.6 版。 如果需要较旧的版本,请确保将SchUseStrongCrypto注册表项设置为针对有问题的应用程序启用 TLS 1.2。

  • 证书验证:使用在 System.Security.Cryptography.X509Certificates 命名空间下定义的 API。

  • SSL/TLS/DTLS:使用在 System.Net 命名空间下定义的 API(例如,HttpWebRequest

密钥派生功能

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

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

  • NIST SP 800-108:使用伪随机函数进行密钥派生的相关建议。 具体而言,KDF 处于计数器模式,将 HMAC 作为伪随机函数

  • NIST SP 800-56A(修订版 2):使用离散对数密码学的成对密钥建立方案的相关建议。 具体而言,建议使用第 5.8.1 节中的“单步密钥派生功能”。

若要从现有密钥派生密钥,请将 BCryptKeyDerivation API 与以下算法之一结合使用:

  • BCRYPT_SP800108_CTR_HMAC_ALGORITHM

  • BCRYPT_SP80056A_CONCAT_ALGORITHM

若要从共享机密(密钥协议的输出)派生密钥,请将 BCryptDeriveKey API 与以下算法之一结合使用:

  • BCRYPT_KDF_SP80056A_CONCAT

  • BCRYPT_KDF_HMAC

证书验证

使用 SSL、TLS 或 DTLS 的产品应全面验证它们连接到的实体的 X.509 证书。 这包括验证证书的以下信息:

  • 域名。

  • 生效日期(开始日期和到期日期)。

  • 吊销状态。

  • 用途(例如,对服务器进行“服务器身份验证”,对客户端进行“客户端身份验证”)。

  • 信任链。 证书应链接到平台信任的或者由管理员显式配置的根证书颁发机构 (CA)。

如果这些验证测试中有任何一个失败,产品应终止与实体的连接。

信任“自签名”证书的客户端(例如,以默认配置连接到 Exchange 服务器的邮件客户端)可能会忽略证书验证检查。 但是,自签名证书本质上不传达信任、支持吊销或支持密钥续订。 仅当从其他可靠来源(例如,通过经过身份验证且完整性受保护的传输机制提供证书的受信任实体)获取自签名证书时,才应信任自签名证书。

加密哈希函数

产品应使用 SHA-2 系列的哈希算法(SHA256、SHA384 和 SHA512)。 出于安全目的,建议不要将加密哈希截断至 128 位以下。

MAC/HMAC/键控哈希算法

消息身份验证代码 (MAC) 是附加到消息的信息片段,可让其接收方使用机密密钥来验证发送方的真实性和消息的完整性。

只要还建议使用所有底层哈希或对称加密算法,就建议使用基于哈希的 MAC (HMAC)基于分组加密的 MAC;目前,这些算法包括 HMAC SHA2 函数(HMAC-SHA256、HMAC SHA384 和 HMAC SHA512)。

建议不要将 HMAC 截断至 128 位以下。

设计和操作注意事项

  • 你应该提供一种根据需要更换加密密钥的机制。 一旦密钥的有效生存期结束,或者加密密钥遭到破坏,就应将其更换。 每当续订证书时,都应使用新密钥续订。

  • 使用加密算法保护数据的产品应包括足够的元数据以及该内容,以支持将来迁移到其他算法。 这应该包括所使用的算法、密钥大小、初始化向量和填充模式。

  • 产品应尽可能使用平台提供的既定加密协议,而不是重新实现它们。 这包括签名格式(例如,使用标准的现有格式)。

  • 不应使用对称流加密法,例如 RC4。 产品不应使用对称流加密法,应使用块加密法,具体而言,密钥长度至少为 128 位的 AES。

  • 不要向最终用户报告加密操作失败。 将错误返回到远程调用方(例如 Web 客户端,或客户端-服务器方案中的客户端)时,请仅使用一般错误消息。

    • 避免提供任何不必要的信息,例如直接报告超出范围或长度无效错误。 仅在启用详细日志记录的情况下,才在服务器上记录详细错误。
  • 强烈建议对包含以下协议的任何设计执行额外的安全审查:

    • 主要关注安全性的新协议(例如身份验证或授权协议)

    • 以新颖或非标准方式使用加密的新协议。注意事项示例包括:

      • 实现协议的产品会在协议实现中调用任何加密 API 或方法吗?

      • 协议是否依赖用于身份验证或授权的任何其他协议?

      • 协议会为加密元素(例如密钥)定义存储格式吗?

  • 不建议将自签名证书用于生产环境。 自签名证书的使用与原始加密密钥一样,本质上不为用户或管理员提供任何进行信任决策的依据。

    • 相比之下,使用受信任证书颁发机构颁发的证书明确了依赖关联私钥的依据,并在出现安全故障时启用吊销和更新。

存储前加密敏感数据

DPAPI/DPAPI-NG

对于需要在系统重新引导时保留的数据:

  • CryptProtectData

  • CryptUnprotectData

  • NCryptProtectSecret (Windows 8 CNG DPAPI)

对于不需要在系统重新引导时保留的数据:

  • CryptProtectMemory

  • CryptUnprotectMemory

对于需要保留并由多个域帐户和计算机访问的数据:

SQL Server TDE

你可以使用 SQL Server 透明数据加密 (TDE) 来保护敏感数据。

你应该使用符合 SDL 加密算法和密钥强度要求的 TDE 数据库加密密钥 (DEK)。 目前,建议仅AES_128、AES_192和AES_256;不建议使用TRIPLE_DES_3KEY。

使用 SQL TDE 时,应牢记一些重要注意事项:

凭据管理

使用 Windows 凭据管理器 APIMicrosoft Azure KeyVault 保护密码和凭据数据。

Windows 应用商店应用

使用 Windows.Security.CryptographyWindows.Security.Cryptography.DataProtection 命名空间中的类来保护机密和敏感数据。

  • ProtectAsync

  • ProtectStreamAsync

  • UnprotectAsync

  • UnprotectStreamAsync

使用 Windows.Security.Credentials 命名空间中的类来保护密码和凭据数据。

.NET

对于需要在系统重新引导时保留的数据:

  • ProtectedData.Protect

  • ProtectedData.Unprotect

对于不需要在系统重新引导时保留的数据:

  • ProtectedMemory.Protect

  • ProtectedMemory.Unprotect

对于配置文件,使用

RSAProtectedConfigurationProviderDPAPIProtectedConfigurationProvider,分别通过 RSA 加密或 DPAPI 来保护配置。

可跨群集中的多台计算机使用 RSAProtectedConfigurationProvider。 有关详细信息,请参阅使用受保护的配置来加密配置信息