Exporting shared secret as BYTE array from BCRYPT_

2019-07-13 05:07发布

I'm implementing ECDHE using crypto next generation APIs (CNG). I generate public and private keys successfully. For pre-shared key, I use BCryptSecretAgreement API, which returns me the pre-shared key secret handle (BCRYPT_SECRET_HANDLE).

How can I export the pre-shared key as BYTE array from the BCRYPT_SECRET_HANDLE?

3条回答
一夜七次
2楼-- · 2019-07-13 05:38

Starting with Windows 10, you can call BCryptDeriveKey() with BCRYPT_KDF_RAW_SECRET.

The resulting key data is the raw secret.

Note 1: bcrypt.h indicates that this format works for "WINBLUE", which would be Windows 8.1, if I understand correctly, but I received STATUS_NOT_SUPPORTED for the use of this KDF type on both Windows 8.1 and Windows Server 2012 R2. This works, however, on Windows 10.)

Note2: I found the data returned using this KDF type to be little-endian (where everything else in BCrypt is big-endian). So, to use the value in an otherwise big-endian world, you need to byte-flip the data.

查看更多
Lonely孤独者°
3楼-- · 2019-07-13 05:40

Once you got your BCRYPT_SECRET_HANDLE, you use BCryptDeriveKey to obtain the actual symmetric encryption key.

查看更多
孤傲高冷的网名
4楼-- · 2019-07-13 05:53

After calling BCryptSecretAgreement, You need to use the BCryptDeriveKey function to retrieve the shared secret.

This can be done as follows:

// 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;
}

For the second parameter, the constant BCRYPT_KDF_HASH says to use a hash as the key derivation function. The hash to use can be specified in the third parameter. In this example, the third parameter is NULL, so it uses SHA1 by default.

Also, the fourth parameter, which is a pointer to the buffer to receive the key, can be NULL. If so, the key is not copied however the number of bytes that would be copied are written to the address given by the sixth parameter. This allows us to allocate the proper amount of space then call the function again, this time passing in the address of the allocated buffer.

查看更多
登录 后发表回答