BCrypt如何将字节转换为键句柄

时间:2014-07-26 19:25:00

标签: c++ key private bcrypt crypt

我有一个字节数组,它应该是我用来解码用公钥编码的消息的私钥。

BCryptDecrypt使用BCRYPT_KEY_HANDLE类型作为用于解密消息的密钥。 如何将私钥转换为密钥句柄?

1 个答案:

答案 0 :(得分:0)

我有一个类似的问题。您需要密钥(作为字节流),但您还需要知道其他信息(例如使用的算法等)。

如果我们假设密钥是使用BCryptExportKey导出的(导出密钥和CNG特定标头),那么你可以加载这样的密钥:

BCRYPT_KEY_HANDLE ImportKey(BYTE* pbKey, ULONG uLength)
{
    if(uLength < sizeof(BCRYPT_KEY_BLOB))
        return nullptr;

    const wchar_t*  wszAlgorithm;
    bool bPublic;
    switch(reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic)
    {
    case BCRYPT_RSAPUBLIC_MAGIC:
    case BCRYPT_RSAPRIVATE_MAGIC:
    case BCRYPT_RSAFULLPRIVATE_MAGIC:
        if(uLength < sizeof(BCRYPT_RSAKEY_BLOB))
            return nullptr;
        wszAlgorithm = BCRYPT_RSA_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_RSAPUBLIC_MAGIC);
        break;
    case BCRYPT_ECDH_PUBLIC_P256_MAGIC:
    case BCRYPT_ECDH_PRIVATE_P256_MAGIC:
        wszAlgorithm = BCRYPT_ECDH_P256_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDH_PUBLIC_P256_MAGIC);
        break;
    case BCRYPT_ECDH_PUBLIC_P384_MAGIC:
    case BCRYPT_ECDH_PRIVATE_P384_MAGIC:
        wszAlgorithm = BCRYPT_ECDH_P384_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDH_PUBLIC_P384_MAGIC);
        break;
    case BCRYPT_ECDH_PUBLIC_P521_MAGIC:
    case BCRYPT_ECDH_PRIVATE_P521_MAGIC:
        wszAlgorithm = BCRYPT_ECDH_P521_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDH_PUBLIC_P521_MAGIC);
        break;
    case BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
    case BCRYPT_ECDSA_PRIVATE_P256_MAGIC:
        wszAlgorithm = BCRYPT_ECDSA_P256_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDSA_PUBLIC_P256_MAGIC);
        break;
    case BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
    case BCRYPT_ECDSA_PRIVATE_P384_MAGIC:
        wszAlgorithm = BCRYPT_ECDSA_P384_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDSA_PUBLIC_P384_MAGIC);
        break;
    case BCRYPT_ECDSA_PUBLIC_P521_MAGIC:
    case BCRYPT_ECDSA_PRIVATE_P521_MAGIC:
        wszAlgorithm = BCRYPT_ECDSA_P521_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_ECDSA_PUBLIC_P521_MAGIC);
        break;
    case BCRYPT_DH_PUBLIC_MAGIC:
    case BCRYPT_DH_PRIVATE_MAGIC:
        if(uLength < sizeof(BCRYPT_DH_KEY_BLOB))
            return nullptr;
        wszAlgorithm = BCRYPT_DH_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_DH_PUBLIC_MAGIC);
        break;
    case BCRYPT_DSA_PUBLIC_MAGIC:
    case BCRYPT_DSA_PRIVATE_MAGIC:
    case BCRYPT_DSA_PUBLIC_MAGIC_V2:
    case BCRYPT_DSA_PRIVATE_MAGIC_V2:
        if(uLength < sizeof(BCRYPT_DSA_KEY_BLOB))
            return nullptr;
        wszAlgorithm = BCRYPT_DSA_ALGORITHM;
        bPublic = (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_DSA_PUBLIC_MAGIC) || (reinterpret_cast<BCRYPT_KEY_BLOB*>(pbKey)->Magic == BCRYPT_DSA_PUBLIC_MAGIC_V2);
        break;
    default:
        return nullptr;
    }

    // Query provider (I recommend to use RAII here for the case of exceptions; I omit that in this example here)
    BCRYPT_ALG_HANDLE hAlgorithm;
    NTSTATUS ntResult = BCryptOpenAlgorithmProvider(&hAlgorithm, wszAlgorithm, MS_PRIMITIVE_PROVIDER, 0);
    if(!BCRYPT_SUCCESS(ntResult))
        return nullptr;

    // Import key
    BCRYPT_KEY_HANDLE hKey;
    ntResult = BCryptImportKeyPair(hAlgorithm, nullptr, bPublic ? BCRYPT_PUBLIC_KEY_BLOB : BCRYPT_PRIVATE_KEY_BLOB, &hKey, pbKey, uLength, 0);
    BCryptCloseAlgorithmProvider(hAlgorithm, 0);        // Close in each case
    if(!BCRYPT_SUCCESS(ntResult))
        return nullptr;

    return hKey;
}

如您所见,此示例函数期望字节流具有CNG标头。如果您的关键字节流具有此标头,则使用此功能加载密钥。否则你需要创建这样的标题。