Я внедряю ECDHE с использованием крипто API следующего поколения (CNG). Я генерирую открытый и закрытый ключи успешно. Для предварительного общего ключа я использую BCryptSecretAgreement API, который возвращает мне секретный дескриптор предварительного ключа (BCRYPT_SECRET_HANDLE).
Как я могу экспортировать предварительный общий ключ как массив BYTE из BCRYPT_SECRET_HANDLE?
Как только вы получили BCRYPT_SECRET_HANDLE
, ты используешь BCryptDeriveKey
получить актуальный симметричный ключ шифрования.
После звонка 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. Если это так, ключ не копируется, однако количество байтов, которые будут скопированы, записывается по адресу, указанному шестым параметром. Это позволяет нам выделить необходимое количество места, а затем снова вызвать функцию, на этот раз передавая адрес выделенного буфера.