C++ 如何使用MS CryptoAPI导出受密码保护的私钥?

C++ 如何使用MS CryptoAPI导出受密码保护的私钥?,c++,winapi,encryption,cryptoapi,C++,Winapi,Encryption,Cryptoapi,我使用Microsoft CryptoAPI生成了一个新的RSA密钥对,现在正试图将私钥导出到PKCS#8加密(密码保护)的PEM文件中 我首先研究了CryptExportPKCS8()和CryptExportPKCS8Ex(),但前者不支持加密密钥,后者则不支持。MSDN表示这两个函数都已被弃用 我当前的尝试是将从密码派生的会话密钥传递给CryptExportKey(): HCRYPTPROV提供程序; BOOL result=CryptAcquireContext(&provider,容器名

我使用Microsoft CryptoAPI生成了一个新的RSA密钥对,现在正试图将私钥导出到PKCS#8加密(密码保护)的PEM文件中

我首先研究了CryptExportPKCS8()和CryptExportPKCS8Ex(),但前者不支持加密密钥,后者则不支持。MSDN表示这两个函数都已被弃用

我当前的尝试是将从密码派生的会话密钥传递给CryptExportKey():

HCRYPTPROV提供程序;
BOOL result=CryptAcquireContext(&provider,容器名,MS增强型,PROV RSA全,CRYPT新密钥集,CRYPT静默);
HCRYPTKEY密钥对;

结果=CryptGenKey(提供程序,CALG_RSA_KEYX,(2048PKCS_RSA_PRIVATE_密钥仅在私钥块未加密时使用。加密时必须使用PKCS_encrypted_PRIVATE_密钥信息。工作代码示例

BOOL expKey(PCSTR password)
{
    BOOL fOk = FALSE;
    HCRYPTPROV hProv;
    if (CryptAcquireContext(&hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        HCRYPTKEY hKey, hExpKey;
        HCRYPTHASH hHash;

        BOOL f = FALSE;

        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (PBYTE)password, (ULONG)strlen(password), 0))
            {
                f = CryptDeriveKey(hProv, CALG_3DES, hHash, 0, &hExpKey);
            }
            CryptDestroyHash(hHash);
        }

        if (f)
        {
            if (CryptGenKey(hProv, CALG_RSA_KEYX, RSA1024BIT_KEY*2|CRYPT_EXPORTABLE, &hKey))
            {
                CRYPT_ENCRYPTED_PRIVATE_KEY_INFO cepki = {{ szOID_RSA_DES_EDE3_CBC}};
                if (
                    CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, 0, &cepki.EncryptedPrivateKey.cbData) &&
                    CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, cepki.EncryptedPrivateKey.pbData = (PBYTE)alloca(cepki.EncryptedPrivateKey.cbData), &cepki.EncryptedPrivateKey.cbData)
                    )
                {
                    ULONG cb;
                    PVOID pvEncoded;
                    if (CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_ENCRYPTED_PRIVATE_KEY_INFO, &cepki, CRYPT_ENCODE_ALLOC_FLAG, 0, &pvEncoded, &(cb = sizeof(PVOID))))
                    {
                        fOk = TRUE;
                        LocalFree(pvEncoded);
                    }
                }
            }
            CryptDestroyKey(hExpKey);
        }
        CryptReleaseContext(hProv, 0);
    }

    return fOk;
}

PKCS_RSA_PRIVATE_密钥仅在私钥blob未加密时使用。加密时必须使用PKCS_encrypted_PRIVATE_密钥信息。工作代码示例

BOOL expKey(PCSTR password)
{
    BOOL fOk = FALSE;
    HCRYPTPROV hProv;
    if (CryptAcquireContext(&hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        HCRYPTKEY hKey, hExpKey;
        HCRYPTHASH hHash;

        BOOL f = FALSE;

        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (PBYTE)password, (ULONG)strlen(password), 0))
            {
                f = CryptDeriveKey(hProv, CALG_3DES, hHash, 0, &hExpKey);
            }
            CryptDestroyHash(hHash);
        }

        if (f)
        {
            if (CryptGenKey(hProv, CALG_RSA_KEYX, RSA1024BIT_KEY*2|CRYPT_EXPORTABLE, &hKey))
            {
                CRYPT_ENCRYPTED_PRIVATE_KEY_INFO cepki = {{ szOID_RSA_DES_EDE3_CBC}};
                if (
                    CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, 0, &cepki.EncryptedPrivateKey.cbData) &&
                    CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, cepki.EncryptedPrivateKey.pbData = (PBYTE)alloca(cepki.EncryptedPrivateKey.cbData), &cepki.EncryptedPrivateKey.cbData)
                    )
                {
                    ULONG cb;
                    PVOID pvEncoded;
                    if (CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_ENCRYPTED_PRIVATE_KEY_INFO, &cepki, CRYPT_ENCODE_ALLOC_FLAG, 0, &pvEncoded, &(cb = sizeof(PVOID))))
                    {
                        fOk = TRUE;
                        LocalFree(pvEncoded);
                    }
                }
            }
            CryptDestroyKey(hExpKey);
        }
        CryptReleaseContext(hProv, 0);
    }

    return fOk;
}

pvEncoded是什么格式?
openssl asn1parse-inform DER-in test.DER
显示有效的ASN.1,但
openssl pkcs8-inform DER-in test.DER
给出了
未知的pbe算法:evp_pbe.c:162:TYPE=des-ede3-cbc
。pvEncoded是什么格式?
openssl asn1parse-inform DER-in test.DER
显示有效的ASN.1,但
opensslpkcs8-通知DER-测试中。DER
给出
未知pbe算法:evp_pbe.c:162:TYPE=des-ede3-cbc