我正在使用加密下一代API(CNG)实现ECDHE。我成功生成公钥和私钥。对于预共享密钥,我使用 BCryptSecretAgreement API,它返回预共享密钥保密句柄(BCRYPT_SECRET_HANDLE)。
如何从BCRYPT_SECRET_HANDLE中将预共享密钥导出为BYTE数组?
答案 0 :(得分:0)
获得BCRYPT_SECRET_HANDLE
后,使用BCryptDeriveKey
获取实际的对称加密密钥。
答案 1 :(得分:0)
从Windows 8.1开始,您可以使用BCryptDeriveKey()
来调用BCRYPT_KDF_RAW_SECRET
。
生成的密钥数据是原始机密。
答案 2 :(得分:0)
我需要执行以下操作,这是我的代码的摘录,其中摘录了一些关键项目,您需要在此段之前导入私钥和公钥。
DWORD bCryptStatus;
BCRYPT_SECRET_HANDLE secretHandle = NULL;
BCRYPT_KEY_HANDLE privateKeyHandle= NULL;
BCRYPT_KEY_HANDLE importedPublicKey = NULL;
BYTE *agreedSecret = NULL;
DWORD agreedSecretLength = 0;
//Import your keys here
//Generate the secret from the imported keys
bCryptStatus= BCryptSecretAgreement(privateKeyHandle, importedPublicKey, &secretHandle, 0);
//Now get the raw value of the secret agreement and copy it into an array
bCryptStatus= BCryptDeriveKey(
secretHandle, // Secret agreement handle
BCRYPT_KDF_RAW_SECRET, // Key derivation function (null terminated unicode string)
NULL, // KDF parameters
NULL, // Buffer that recieves the derived key
0, // Length of the buffer
&agreedSecretLength, // Number of bytes copied to the buffer
0); // Flags
agreedSecret = (PBYTE)MALLOC(agreedSecretLength);
if (NULL != agreedSecret)
{
_nCryptError = BCryptDeriveKey(
secretHandle, // Secret agreement handle
BCRYPT_KDF_RAW_SECRET, // Key derivation function (null terminated unicode string)
NULL, // KDF parameters
agreedSecret, // Buffer that recieves the derived key
agreedSecretLength, // Length of the buffer
&agreedSecretLength, // Number of bytes copied to the buffer
0); // Flags
}
//Free all the objects and the array when you are done, otherwise you will get memory leaks
if (NULL != importedPublicKey)
{
BCryptDestroyKey(importedPublicKey);
}
if (NULL != privateKeyHandle)
{
BCryptDestroyKey(privateKeyHandle);
}
if (NULL != secretHandle)
{
BCryptDestroySecret(secretHandle);
}
if (NULL != agreedSecret)
{
FREE(agreedSecret);
}
请注意,如果您使用NCrypt,这也将起作用(NCryptDeriveKey),我在生产代码中对其进行了验证。 如前所述,该数组将被反转,您将需要反转字节数组以获取机密。
答案 3 :(得分:-1)
调用BCryptSecretAgreement
后,您需要使用BCryptDeriveKey
函数来检索共享密钥。
这可以按如下方式完成:
// generates an ECDH shared secret from a public key and a private key
int get_ECDH_key(BCRYPT_KEY_HANDLE pubkey, BCRYPT_KEY_HANDLE privkey, unsigned char **key,
unsigned int *keylen)
{
SECURITY_STATUS sstatus;
BCRYPT_SECRET_HANDLE secret;
int _len;
// creates the shared secret, stored in a BCRYPT_SECRET_HANDLE
sstatus = BCryptSecretAgreement(privkey, pubkey, &secret, 0);
if (!BCRYPT_SUCCESS(sstatus)) {
printf("BCryptSecretAgreement failed with status %d", sstatus);
return 0;
}
// find out how much space is needed before retrieving the shared secret
sstatus = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, NULL, NULL, 0, &_len, 0);
if (!BCRYPT_SUCCESS(sstatus)) {
printf("BCryptDeriveKey failed with status %d", sstatus);
return 0;
}
// allocate space for the shared secret
*key = malloc(_len);
if (*key == NULL) {
perror("malloc failed");
exit(1);
}
// retrieve the shared secret
sstatus = BCryptDeriveKey(secret, BCRYPT_KDF_HASH, NULL, *key, _len,
keylen, 0 );
if (!BCRYPT_SUCCESS(sstatus)) {
printf("BCryptDeriveKey failed with status %d", sstatus);
return 0;
}
return 1;
}
对于第二个参数,常量BCRYPT_KDF_HASH
表示使用哈希作为密钥派生函数。要使用的哈希值可以在第三个参数中指定。在此示例中,第三个参数为NULL,因此默认情况下使用SHA1。
此外,第四个参数,即指向接收密钥的缓冲区的指针,可以为NULL。如果是,则不复制密钥,但是将复制的字节数写入第六个参数给出的地址。这允许我们分配适当的空间量然后再次调用该函数,这次传入分配的缓冲区的地址。