如何确认Windows CNG API返回的算法实现符合FIPS合规要求
你提到的这个现象其实是CNG(Cryptography Next Generation)API的设计特性:启用系统FIPS模式后,它不会直接阻止非合规算法的实例化(比如MD5),而是通过属性标记和使用限制来区分合规/非合规实现。要确保你的代码只使用FIPS合规的算法,需要从以下几个方面入手:
1. 主动校验算法实例的FIPS合规属性
获取算法句柄后,不要直接使用,必须通过BCryptGetProperty查询BCRYPT_IS_FIPS_ALGORITHM_PROPERTY属性。这个属性会返回一个BOOL值,明确标识当前算法实例是否符合FIPS标准。
示例代码:
BOOL isFipsCompliant = FALSE; DWORD cbResult = sizeof(BOOL); // hAlgorithm 是你通过 BCryptOpenAlgorithmProvider 获取的算法句柄 NTSTATUS status = BCryptGetProperty( hAlgorithm, BCRYPT_IS_FIPS_ALGORITHM_PROPERTY, (PUCHAR)&isFipsCompliant, cbResult, &cbResult, 0 ); // 校验:如果查询失败或不是FIPS合规实现,拒绝使用 if (!BCRYPT_SUCCESS(status) || !isFipsCompliant) { BCryptCloseAlgorithmProvider(hAlgorithm, 0); // 这里可以抛出错误、返回合规性失败状态等 }
2. 使用带_FIPS后缀的算法标识符
CNG为部分核心算法提供了明确的FIPS专用标识符(后缀为_FIPS)。使用这些标识符调用BCryptOpenAlgorithmProvider时,只有当系统处于FIPS模式且存在经FIPS验证的实现时,才会成功返回句柄;否则会直接返回错误。
比如,要获取FIPS合规的SHA-256实现:
NTSTATUS status = BCryptOpenAlgorithmProvider( &hAlgorithm, BCRYPT_SHA256_FIPS_ALGORITHM, // 明确指定FIPS版本的算法ID NULL, 0 ); if (!BCRYPT_SUCCESS(status)) { // 无法获取合规的SHA-256实现,处理错误(比如提示系统未启用FIPS或无合规驱动) }
常见的FIPS专用算法ID包括BCRYPT_AES_FIPS_ALGORITHM、BCRYPT_SHA1_FIPS_ALGORITHM、BCRYPT_RSA_FIPS_ALGORITHM等。
3. 理解FIPS模式下的算法使用限制
即使你能成功获取MD5的算法句柄,在FIPS模式下,非合规算法的生成操作(比如计算新的MD5哈希、生成MD5签名)会被禁止,仅允许用于验证操作(比如验证旧系统留下的MD5签名文件)。但从合规角度来说,你应该完全避免在代码中使用任何非FIPS合规的算法,不管系统是否允许实例化。
4. 用组策略强化合规限制(可选但推荐)
除了系统层面启用FIPS模式,你还可以通过组策略进一步强化规则:
- 打开本地组策略编辑器,导航到
计算机配置>Windows设置>安全设置>本地策略>安全选项 - 找到并启用
系统加密:使用符合FIPS标准的加密、哈希和签名算法
这个组策略会更严格地限制CNG API的行为,比如部分非合规算法的实例化会直接失败,减少代码层面的校验压力。
总结
系统启用FIPS模式只是基础,要确保代码使用的是合规算法实现,核心是主动校验每个算法实例的FIPS属性,并优先使用明确的FIPS专用算法ID。不要依赖系统自动阻止非合规算法的实例化——CNG的兼容设计允许部分非合规算法被实例化,但你必须在代码层面主动过滤这些不合规的实现。
内容的提问来源于stack exchange,提问作者zuraff

