CryptSetKeyParam中的NTE_BAD_DATA设置KP_P在Wincrypt中

问题描述:

我有以下代码。我正在使用char *设置diffie-hellman算法的主要部分。 我设置了素数后,数据越来越差。我在哪里做错了? 我在这个链接中跟着相同的例子。 https://msdn.microsoft.com/en-us/library/aa381969(VS.85).aspx#exchanging_diffie-hellman_keysCryptSetKeyParam中的NTE_BAD_DATA设置KP_P在Wincrypt中

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

#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时遇到错误。更新了上面的代码以反映新的代码。

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

素数大小KP_P(和KP_G)和DH密钥大小硬连接。必须是cbKey == 8*cbP。例如Diffie-Hellman Client Code for Creating the Master Key

作为密钥大小(如果使用的话)cbP * 8其中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是关键的大小。

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

+0

谢谢[RbMm](https://*.com/users/6401656/rbmm)。它解决了这个问题。但我没有发电机和相同长度的素数。发生器长1个字节,素数长128个字节。在那种情况下,如何使用这个一个字节的发生器值? –

+0

@PrakashN - 为了生成新的** P **和** G **,您不能使用'CRYPT_PREGEN'标志和下一个代码:'CryptGetKeyParam(hPrivateKey1,KP_P,0,&(P.cbData = 0),0) && CryptGetKeyParam(hPrivateKey1,KP_P,P.pbData =(PBYTE)alloca(P.cbData),&P.cbData,0)&& CryptGetKeyParam(hPrivateKey1,KP_G,0,&(G.cbData = 0),0)&& CryptGetKeyParam(hPrivateKey1,KP_G,G.pbData =(PBYTE)alloca(G.cbData),&G.cbData,0)' - 因此生成并获得一方,另一方使用CRYPT_PREGEN和** P **和** G ** – RbMm

+0

谢谢RbMm。在我的情况下,服务器已经同意P和G的值。所以我需要使用服务器生成的P和G值来生成密钥a。我在KP_X的CryptSetKeyParam中收到错误NTE_BAD_KEY。请指教。 –