我有一个字节数组,它应该是我用来解码用公钥编码的消息的私钥。
BCryptDecrypt使用BCRYPT_KEY_HANDLE类型作为用于解密消息的密钥。 如何将私钥转换为密钥句柄?
答案 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标头。如果您的关键字节流具有此标头,则使用此功能加载密钥。否则你需要创建这样的标题。