sgcCrypto 提供一个可选的编译时开关 SGC_CRYPTO_FIPS, 它使库中只保留 FIPS 批准的算法。它面向那些不得使用 FIPS 和 NIST SP 出版物范围之外算法的项目。 本页说明该开关的作用、如何启用它、它保留哪些算法、移除哪些算法,以及它不涵盖哪些内容。
此处 FIPS 的含义
FIPS 140-3 认证的对象是密码模块,而不是算法。 由经过认可的实验室依据 NIST 的密码模块验证计划(CMVP),对某个产品的一个特定构建进行测试, 然后由 NIST 为该构建发布证书。使用 AES 这类批准的算法,并不会使程序成为经过验证的程序。
sgcCrypto 不是经过 FIPS 140-3 验证的模块, 启用该开关也不构成任何验证声明。该开关实际所做的事情范围更窄:
保留下来的算法遵循下表所列的 FIPS 和 NIST SP 出版物。
如果您的项目有正式的 FIPS 140-3 要求,其密码学运算必须通过经过验证的模块完成, 例如在以 FIPS 模式运行的系统上使用 Windows CNG。该开关有助于把未经批准的算法挡在您的代码之外。 它不能替代经过验证的模块。
启用该开关
该开关默认关闭。未启用时一切保持不变,密码学页面中列出的每一种算法都可以使用。 要启用它,请执行以下任一操作:
{.$DEFINE SGC_CRYPTO_FIPS} { off, the default }
{$DEFINE SGC_CRYPTO_FIPS} { on }
然后重新构建。该开关只影响使用该定义编译的代码,因此未使用该定义构建的预编译包不受影响。
启用该开关后,被移除的函数将不复存在。仍然调用其中任何一个函数的代码将无法编译, 并报告“Undeclared identifier”(未声明的标识符)错误。这是有意为之:任何未经批准的内容都不会意外进入二进制文件, 而且编译器会指出每一处需要改用其他算法的位置。
保留的内容
证书、一次性密码和编码辅助函数同样被保留,因为它们要么完全由批准的算法构建而成, 要么根本不是密码学算法。
| 算法族 | 保留的内容 | 标准 |
| AES | ECB、CBC、CFB、OFB、CTR、CTS、GCM 和 CCM 模式下的 AES-128/192/256,AES 密钥包装(KW 和 KWP),以及 AES-CMAC 和 AES-GMAC | FIPS 197, SP 800-38A/B/C/D/F |
| 哈希 | SHA-1(仅限仍被允许的场合,绝不用于新签名)、SHA-224、SHA-256、SHA-384、SHA-512、SHA3-224/256/384/512、SHAKE128、SHAKE256、cSHAKE 和 KMAC | FIPS 180-4, FIPS 202, SP 800-185 |
| 消息认证 | HMAC-SHA1、HMAC-SHA256、HMAC-SHA384 和 HMAC-SHA512 | FIPS 198-1 |
| 密钥派生 | PBKDF2、HKDF 和 ANSI X9.63 KDF | SP 800-132 (PBKDF2), SP 800-56C (HKDF), SP 800-135 (ANSI X9.63 KDF) |
| RSA | RSA 密钥生成、PKCS#1 v1.5 和 PSS 签名、RSA-OAEP 加密 | FIPS 186-5, SP 800-56B |
| ECDSA 和 ECDH | 基于 NIST P-256、P-384 和 P-521 的签名与密钥协商(sgcCrypto 未实现 P-224) | FIPS 186-5, SP 800-56A |
| EdDSA | Ed25519 和 Ed448 签名 | FIPS 186-5 |
| 后量子密码学 | ML-KEM、ML-DSA 和 SLH-DSA | FIPS 203, FIPS 204, FIPS 205 |
| 证书与 PKI | X.509 证书解析、证书链验证和 CRL 检查,以及使用上述算法签名的证书或 CSR 生成 | RFC 5280, RFC 2986 |
| 一次性密码 | 基于 HMAC 构建的 HOTP 和 TOTP | RFC 4226, RFC 6238 |
| 编码与实用工具 | 十六进制、Base32 和 Base64 编码,恒定时间比较,安全清零 | RFC 4648 |
移除的内容
| 移除的内容 | 原因 |
| ChaCha20、XChaCha20、Salsa20、XSalsa20、Poly1305、ChaCha20-Poly1305 和 XChaCha20-Poly1305 | 不是 NIST 算法。 |
| X25519 和 X448 密钥交换 | SP 800-56A 未批准将其用于密钥协商。 |
| X25519 + ML-KEM-768 混合构造,以及 ECIES | 二者都基于 X25519 构建。 |
| secp256k1 和 Brainpool 曲线,以及 BIP-340 Schnorr 签名 | 它们不是 NIST 推荐的曲线,而且 BIP-340 不是 FIPS 186-5 签名方案。FIPS 模式只保留 NIST P 曲线。 |
| Argon2 和 scrypt | 不是 NIST 规定的基于密码的密钥派生函数。 |
| BLAKE2b、BLAKE2s、SipHash 和 TLSH | 不是 NIST 算法。 |
| MD4、MD5、HMAC-MD5、RIPEMD-160 和 DES(sgcCrypto_Legacy 单元) | 已经过时,或从未获得 NIST 批准。 |
| KDF1 和 KDF2 | 定义于 ISO 18033-2,而不是 NIST 出版物。ANSI X9.63 KDF 仍然保留。 |
| RSA PKCS#1 v1.5 加密 | SP 800-131A 不允许使用。PKCS#1 v1.5 签名仍然保留。 |
| WinZip AES(AE-1 和 AE-2) | 不是 NIST 格式。 |
对于大多数被移除的算法,第一张表中都有批准的替代算法:用 AES-GCM 替代 ChaCha20-Poly1305, 用基于 P-256 或 P-384 的 ECDH 替代 X25519,用 PBKDF2 替代 Argon2 或 scrypt, 用 SHA-256 或 SHA-3 替代 BLAKE2,用 RSA-OAEP 替代 PKCS#1 v1.5 加密。
运行时检查的规则
有些规则取决于传给函数的值,因此编译器无法强制执行它们。启用该开关后,sgcCrypto 会在函数运行时检查这些规则, 每一项检查失败时都会引发异常,其消息以 sgcCrypto FIPS: 开头:
随机字节的来源
密钥、随机数和盐值都需要随机字节。sgcRandomBytes 在两种模式下都始终从操作系统读取随机字节,从不在其之上再运行自己的生成器。该开关只改变所使用的系统来源:
| 平台 | 启用 SGC_CRYPTO_FIPS 时 | 未启用 SGC_CRYPTO_FIPS 时 |
| Windows | BCryptGenRandom(CNG,系统首选 RNG),没有回退 | BCryptGenRandom,当 BCryptGenRandom 不可用时依次回退到 RtlGenRandom 和 CryptGenRandom |
| Linux 和 Android | getrandom 系统调用 | /dev/urandom |
| macOS 和 iOS | Security 框架中的 SecRandomCopyBytes | /dev/urandom |
在两种模式下,如果无法读取任何来源,都会引发异常,而不会返回弱随机字节。 操作系统的生成器是否算作符合 FIPS,取决于操作系统及其配置,而不取决于 sgcCrypto。
该开关不涵盖的内容
该开关仅适用于 sgcCrypto 单元。sgcWebSockets 的其他部分仍可能使用未经批准的算法:
如果整个应用程序都必须限定在批准的算法范围内,请同时审查上述这些方面。
另请参阅