c++ - 在 wincrypt 中设置 KP_P 时 CryptSetKeyParam 中的 NTE_BAD_DATA

标签 c++ windows winapi diffie-hellman wincrypt

我有以下代码。我正在使用 char * 为 diffie-hellman 算法设置素数。 设置素数后,我得到了错误的数据。我哪里做错了? 我在此链接中遵循了相同的示例。 https://msdn.microsoft.com/en-us/library/aa381969(VS.85).aspx#exchanging_diffie-hellman_keys

使用 wincrypt 在 diffie-hellman 中设置质数的正确方法是什么?

#define DHKEYSIZE 1024
int fld_sz = 256;
BYTE* g_rgbPrime = new BYTE[DHKEYSIZE/8];   
char * prime = "A1BD60EBD2D43C53FA78D938C1EF8C9AD231F9862FC402739302DEF1B6BEB01E5BE59848A04C48B0069A8FB56143688678F7CC1097B921EA3E13E1EF9B9EB5381BEFDE7BBF614C13827493A1CA31DA76B4083B62C5073451D6B1F06A2F1049C291464AC68CBB2F69474470BBAD374073392696B6447C82BF55F20B2D015EB97B";
string s_prime(prime, fld_sz);
vector<std::string> res;
// split the string two charactes for converting into hex format
for (size_t i = 0; i < fld_sz; i += 2)
    res.push_back(s_prime.substr(i, 2));
for(int i = 0; i < res.size(); i++) {
    BYTE b = static_cast<BYTE>(std::stoi(res[i], 0, 16));
    g_rgbPrime[i] = b;
}
BYTE g_rgbGenerator[128] = 
{
    0x02
};
BOOL fReturn;
HCRYPTPROV hProvParty1 = NULL; 
HCRYPTPROV hProvParty2 = NULL; 
CRYPT_DATA_BLOB P;
CRYPT_DATA_BLOB G;
HCRYPTKEY hPrivateKey1 = NULL;
HCRYPTKEY hPrivateKey2 = NULL;
PBYTE pbKeyBlob1 = NULL;
PBYTE pbKeyBlob2 = NULL;
HCRYPTKEY hSessionKey1 = NULL;
HCRYPTKEY hSessionKey2 = NULL;
PBYTE pbData = NULL;

/************************
Construct data BLOBs for the prime and generator. The P and G 
values, represented by the g_rgbPrime and g_rgbGenerator arrays 
respectively, are shared values that have been agreed to by both 
parties.
************************/
P.cbData = DHKEYSIZE / 8;
P.pbData = (BYTE*)(g_rgbPrime);

G.cbData = DHKEYSIZE / 8;
G.pbData = (BYTE*)(g_rgbGenerator);

/************************
Create the private Diffie-Hellman key for party 1. 
************************/
// Acquire a provider handle for party 1.
fReturn = CryptAcquireContext(
    &hProvParty1, 
    NULL,
    MS_ENH_DSS_DH_PROV,
    PROV_DSS_DH, 
    CRYPT_VERIFYCONTEXT);
if(!fReturn)
{
    goto ErrorExit;
}

// Create an ephemeral private key for party 1.
fReturn = CryptGenKey(
    hProvParty1, 
    CALG_DH_EPHEM, 
    DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN,
    &hPrivateKey1);
if(!fReturn)
{
    goto ErrorExit;
}

// Set the prime for party 1's private key.
fReturn = CryptSetKeyParam(
    hPrivateKey1,
    KP_P,
    (PBYTE)&P,
    0);
if(!fReturn)
{
    std::cout << GetLastError() << endl;
    goto ErrorExit;
}

// Set the generator for party 1's private key.
fReturn = CryptSetKeyParam(
    hPrivateKey1,
    KP_G,
    (PBYTE)&G,
    0);
if(!fReturn)
{
    std::cout << GetLastError() << endl;
    goto ErrorExit;
}

提前致谢。

更新 1: 感谢@RbMm我能够设置素数。问题出在 DHKEYSize 上。但是我在设置 KP_X 时遇到错误。更新了上面的代码以反射(reflect)新代码。

这里我将字符串转换为十六进制字节数组。

最佳答案

素数 KP_P(和 KP_G)的大小和 DH key 大小硬连接。必须是 cbKey == 8*cbP。寻找例子 Diffie-Hellman Client Code for Creating the Master Key :

如果使用 cbP * 8 作为 key 大小,其中 cbP 素数 P 的大小。在您的链接中还有 P.cbData = DHKEYSIZE/8;

也可以在代码中硬编码 P(和 G)的大小,您可以在运行时获取它:

ULONG dwDataLen;
CryptGetKeyParam(hPrivateKey1, KP_P, 0, &(dwDataLen = 0), 0);
CryptGetKeyParam(hPrivateKey1, KP_G, 0, &(dwDataLen = 0), 0);

并且您可以确定 dwDataLen == DHKEYSIZE/8 其中 DHKEYSIZE 是 key 大小。

因为您使用 512 作为 key 大小,所以 PG 的数据长度必须是 512/8=64。但是您使用 256(对于 P)和 1(对于 G)。作为结果和错误。

关于c++ - 在 wincrypt 中设置 KP_P 时 CryptSetKeyParam 中的 NTE_BAD_DATA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45926946/

相关文章:

c - 如何在 C 中优雅地关闭线程

qt - 是否可以更改 Qt 中顶级菜单的外观?

c++ - DirectX11 监视器句柄

c++ - 为什么有条件地编译一个运算符模板会改变另一个运算符的可用性?

c - win32 api编辑控件和键盘加速器

wpf - 要构建像 WPF 这样的框架,我应该知道什么?

windows - 使用 Powershell 停止/启动 Microsoft Windows 集群角色

c++ - C++正则表达式无限循环

c++ - 简单数组排序/检查 + 分而治之版本

windows - 单个 OpenGL 上下文,多个 View