【问题标题】:BCrypt how to turn bytes to a Key HandleBCrypt如何将字节转换为密钥句柄
【发布时间】:2014-09-18 10:19:06
【问题描述】:

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

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

【问题讨论】:

  • 我有根据的猜测是BCryptImportKeyPair
  • 有道理,所以我尝试了 BCryptImportKeyPair,给出了“坏数据”错误,有什么想法吗?
  • BCryptImportKeyPair 需要很多参数,除非您确切知道如何生成该字节数组,否则您无法正确设置这些参数。你?首先,您知道消息是使用哪种加密算法编码的吗?
  • 我知道它的 rsa 算法,我已经正确打开了算法句柄,因为我已经使用它从证书中提取公钥。我有字节数组中的证书和私钥。然后我用公钥加密了一个值,我想用私钥解密它以进行验证。
  • 我想我需要把私钥变成一个私钥 blob。该结构在 msdn 上,知道如何将私钥以字节为单位转换为 blob 以传递给 importkeypair 吗?

标签: c++ key private bcrypt crypt


【解决方案1】:

我遇到了类似的问题。您需要密钥(作为字节流),但您还需要了解其他信息(例如使用的算法等)。

如果我们假设使用 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 标头。如果您的密钥字节流具有此标头,则您可以使用此函数加载密钥。否则你需要创建这样的标题。

【讨论】:

    猜你喜欢
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多