使用Microsoft CNG生成DSA密钥时BCryptSetProperty调用失败求助
解决BCryptSetProperty设置DSA参数返回STATUS_NOT_SUPPORTED的问题
核心问题分析
你的代码存在两个致命错误:
- 错误地将
BCRYPT_DSA_PARAMETERS属性绑定到算法句柄hAlg,实际上该属性属于密钥级,必须设置在**密钥句柄hKey**上 - DSA参数Blob中的
Seed、q、Modulus、Generator字段未初始化,属于无效数据,不符合FIPS标准要求
修正后的完整代码示例
以下是可正确生成DSA密钥对的C语言实现:
#include <windows.h> #include <bcrypt.h> #include <iostream> #include <cstring> #pragma comment(lib, "bcrypt.lib") #define KEYSIZE 3072 #define CBSEEDLENGTH 43 #define CBGROUPSIZE 32 #define CBKEYLENGTH 384 // 3072位密钥对应字节数 struct _DSA_PARAMETER_BLOB { BCRYPT_DSA_PARAMETER_HEADER_V2 H; UCHAR Seed[CBSEEDLENGTH]; // 大端格式 UCHAR q[CBGROUPSIZE]; // 大端格式,256位素数 UCHAR Modulus[CBKEYLENGTH]; // 大端格式,3072位素数 UCHAR Generator[CBKEYLENGTH]; // 大端格式,生成元 }; int main() { NTSTATUS nts; BCRYPT_ALG_HANDLE hAlg = NULL; BCRYPT_KEY_HANDLE hKey = NULL; // 打开DSA算法提供者 nts = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_DSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); if (STATUS_SUCCESS != nts) { std::cout << "BCryptOpenAlgorithmProvider失败,状态码0X" << std::hex << nts << std::endl; return (int)nts; } // 创建空密钥对容器 nts = BCryptGenerateKeyPair(hAlg, &hKey, KEYSIZE, 0); if (STATUS_SUCCESS != nts) { std::cout << "BCryptGenerateKeyPair失败,状态码0X" << std::hex << nts << std::endl; goto cleanup1; } // 初始化DSA参数Blob(需替换为合法的FIPS 186-3标准参数) _DSA_PARAMETER_BLOB dpb = {0}; dpb.H.cbLength = sizeof(dpb); dpb.H.dwMagic = BCRYPT_DSA_PARAMETERS_MAGIC_V2; dpb.H.cbKeyLength = CBKEYLENGTH; dpb.H.hashAlgorithm = DSA_HASH_ALGORITHM_SHA512; dpb.H.standardVersion = DSA_FIPS186_3; dpb.H.cbSeedLength = CBSEEDLENGTH; dpb.H.cbGroupSize = CBGROUPSIZE; // 迭代次数设为64(大端格式存储) dpb.H.Count[3] = 64; // 注意:此处需填充合法的DSA参数值(示例仅做格式演示,实际需使用合规素数) memset(dpb.q, 0xFF, CBGROUPSIZE); // 示例256位q值 // 请将Seed、Modulus、Generator替换为符合标准的大端数值 // 核心修正:将参数设置到密钥句柄而非算法句柄 nts = BCryptSetProperty(hKey, BCRYPT_DSA_PARAMETERS, (PUCHAR)&dpb, sizeof(dpb), 0); if (STATUS_SUCCESS != nts) { std::cout << "BCryptSetProperty失败,状态码0X" << std::hex << nts << std::endl; goto cleanup2; } // 完成密钥对生成 nts = BCryptFinalizeKeyPair(hKey, 0); if (STATUS_SUCCESS != nts) { std::cout << "BCryptFinalizeKeyPair失败,状态码0X" << std::hex << nts << std::endl; goto cleanup2; } std::cout << "DSA密钥对生成成功" << std::endl; cleanup2: if (hKey) BCryptDestroyKey(hKey); cleanup1: if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0); return (int)nts; }
关键注意事项
- 属性绑定对象:
BCRYPT_DSA_PARAMETERS是密钥专属属性,必须在BCryptGenerateKeyPair之后、BCryptFinalizeKeyPair之前,绑定到密钥句柄hKey - 参数合规性:
Seed、q、Modulus、Generator必须是符合FIPS 186-3标准的大端格式数值,无效值会导致操作失败 - 哈希匹配:3072位DSA密钥搭配
DSA_HASH_ALGORITHM_SHA512是合法组合,需确保q的长度与哈希输出长度匹配
内容的提问来源于stack exchange,提问作者trindflo
相关产品推荐
相关产品推荐

