首页 > 解决方案 > 如何创建用于 OpenSSL 的公钥/私钥对

问题描述

我正在尝试创建一个 Windows 应用程序,该应用程序创建一个公钥和私钥并将其导出,以便我可以将其与 OpenSSL 一起使用。我采用了 MSDN 提供的相同示例,但有一些问题......我认为这是分配内存大小的问题。

我需要的结果是一个 base64 编码的公钥和私钥,如下所示:

const char* szPemPrivKey = "-----BEGIN RSA PRIVATE KEY-----" "MIICXAIBAAKBgQCf6YAJOSBYPve1jpYDzq+w++8YVoATI/YCi/RKZaQk+l2ZfoUQ" "g0qrYrfkzeoOa/qd5VLjTTvHEgwXnlDXMfo+vSgxosUxDOZXMTBqJGOViv5K2QBv" "k8A1wi4k8tuo/7OWya29HvcfavUk3YXaV2YFe8V6ssaZjNcVWmDdjqNkXwIDAQAB" "AoGALrd+ ijNAOcebglT3ioE1XpUbUpbir7TPyAqvAZUUESF7er41jY9tnwgmBRgL" "Cs+M1dgLERCdKBkjozrDDzswifFQmq6PrmYrBkFFqCoLJwepSYdWnK1gbZ/d43rR" "2sXzSGZngscx0CxO7KZ7xUkwENGd3+lKXV7J6/vgzJ4XnkECQQDTP6zWKT7YDckk" "We04hbhHyBuNOW068NgUUvoZdBewerR74MJx6nz28Tp+DeNvc0EveiQxsEnbV8u+" "NRkX5y0xAkEAwcnEAGBn5kJd6SpU0ALA9XEpUv7tHTAGQYgCRbfTT59hhOq6I22A" "ivjOCNG9c6E7EB2kcPVGuCpYUhy7XBIGjwJAK5lavKCqncDKoLwGn8HJdNcyCIWv" "q5iFoDw37gTt1ricg2yx9PzmabkDz3xiUmBBNeFJkw/FToXiQRGIakyGIQJAJIem" "PPPvYgZssYFbT4LVYO8d/Rk1FWVyKHQ9CWtnmADRXz7oK7l+m7PfEuaGsf9YpOcR" "koGJ/TluQLxNzUNQnQJBAImwr/yYFenIx3HQ6UX/fCt6qpGDv0VfOLyR64MNeegx" "o7DhNxHbFkIGzk4lKhMKcHKDrawZbdJtS9ie2geSwVQ=" "-----END RSA PRIVATE KEY-----";

const char* szPemPubKey = "-----BEGIN RSA PUBLIC KEY-----" "MIGJAoGBAJ/pgAk5IFg+97WOlgPOr7D77xhWgBMj9gKL9EplpCT6XZl+hRCDSqti" "t+TN6g5r+p3lUuNNO8cSDBeeUNcx+j69KDGixTEM5lcxMGokY5WK/krZAG+TwDXC" "LiTy26j/s5bJrb0e9x9q9STdhdpXZgV7xXqyxpmM1xVaYN2Oo2RfAgMBAAE=" " -----结束 RSA 公钥-----";

https://www.idrix.fr/Root/Samples/capi_pem.cpp

有人可以更正我的代码或提示我做错了什么吗?

int CreateKeys(DWORD keyLength)
{
/* variables */
HCRYPTPROV hCryptProv = NULL;
DWORD flags = keyLength /*key length*/ << 16;
flags |= CRYPT_EXPORTABLE;
DWORD size = 0;
HCRYPTKEY hKey = NULL;

/* variables public key */
HCRYPTKEY hPublicKey = NULL;
DWORD dwPublicKeyLen = 0;
BYTE* pbPublicKey = NULL;
HANDLE hPublicKeyFile = NULL;
LPBYTE pPublicBLOB = (LPBYTE)LocalAlloc(0, size);

/* variables private key */
HCRYPTKEY hPrivateKey = NULL;
DWORD dwPrivateKeyLen = 0;
BYTE* pbPrivateKey = NULL;
HANDLE hPrivateKeyFile = NULL;
LPBYTE pPrivateKeyBLOB = (LPBYTE)LocalAlloc(0, size);

/* get provider */  
DWORD rc = CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);

// Generate new key pair
//_tprintf(_T("CryptGenKey...\n"));
if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hKey))
{
    // Error
    //_tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
    return 1;
}
// Get public key size
//_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen))
{
    // Error
    //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
    return 1;
}
// Create a buffer for the public key
//_tprintf(_T("malloc...\n"));
if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen)))
{
    // Error
    //_tprintf(_T("malloc error 0x%x\n"), GetLastError());
    return 1;
}
// Get public key
//_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen))
{
    // Error
    //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
    return 1;
}





// Get private key size
//_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen))
{
    // Error
    //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
    return 1;
}
// Create a buffer for the private key
//_tprintf(_T("malloc...\n"));
if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen)))
{
    // Error
    //_tprintf(_T("malloc error 0x%x\n"), GetLastError());
    return 1;
}
// Get private key
//_tprintf(_T("CryptExportKey...\n"));
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen))
{
    // Error
    //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
    return 1;
}

/*
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, 0, &size);
LPBYTE pPrivKeyBLOB = (LPBYTE)LocalAlloc(0, size);
rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, pPrivKeyBLOB, &size);
*/

/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, NULL, &dwPrivateKeyLen);

LPBYTE pPrivateDER = (LPBYTE)LocalAlloc(0, dwPrivateKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, pPrivateDER, &dwPrivateKeyLen);

/* PEM */
DWORD pemPrivateSize = 0;
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPrivateSize);

LPSTR pPrivatePEM = (LPSTR)LocalAlloc(0, pemPrivateSize);
rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPrivateSize);



/* DER */
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbPublicKey, 0, NULL, NULL, &dwPublicKeyLen);

LPBYTE pPublicDER = (LPBYTE)LocalAlloc(0, dwPublicKeyLen);
rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pbPublicKey, 0, NULL, pPublicDER, &dwPublicKeyLen);

/* PEM */
DWORD pemPublicSize = 0;
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPublicSize);

LPSTR pPublicPEM = (LPSTR)LocalAlloc(0, pemPublicSize);
rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPublicSize);

printf("%s", pPrivatePEM);
printf("%s", pPublicPEM);

return 0;
}

标签: c++keyprivatepubliccryptoapi

解决方案


似乎您向CryptEncodeObjectEx函数提供了错误的格式来获取我用来CryptExportPublicKeyInfo获取正确密钥信息的公钥。

试试这个代码:

int CreateKeys(DWORD keyLength)
{
    /* variables */
    HCRYPTPROV hCryptProv = NULL;
    DWORD flags = keyLength /*key length*/ << 16;
    flags |= CRYPT_EXPORTABLE;
    DWORD size = 0;
    HCRYPTKEY hKey = NULL;

    /* variables public key */
    HCRYPTKEY hPublicKey = NULL;
    DWORD dwPublicKeyLen = 0;
    BYTE* pbPublicKey = NULL;
    HANDLE hPublicKeyFile = NULL;
    LPBYTE pPublicBLOB = (LPBYTE)LocalAlloc(0, size);

    /* variables private key */
    HCRYPTKEY hPrivateKey = NULL;
    DWORD dwPrivateKeyLen = 0;
    BYTE* pbPrivateKey = NULL;
    HANDLE hPrivateKeyFile = NULL;
    LPBYTE pPrivateKeyBLOB = (LPBYTE)LocalAlloc(0, size);

    /* get provider */
    DWORD rc = CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);

    // Generate new key pair
    //_tprintf(_T("CryptGenKey...\n"));
    if (!CryptGenKey(hCryptProv, AT_KEYEXCHANGE, CRYPT_ARCHIVABLE, &hKey)) {
        // Error
        //_tprintf(_T("CryptGenKey error 0x%x\n"), GetLastError());
        return 1;
    }
    // Get public key size
    //_tprintf(_T("CryptExportKey...\n"));
    if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwPublicKeyLen)) {
        // Error
        //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
        return 1;
    }
    // Create a buffer for the public key
    //_tprintf(_T("malloc...\n"));
    if (!(pbPublicKey = (BYTE *)malloc(dwPublicKeyLen))) {
        // Error
        //_tprintf(_T("malloc error 0x%x\n"), GetLastError());
        return 1;
    }
    // Get public key
    //_tprintf(_T("CryptExportKey...\n"));
    if (!CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, pbPublicKey, &dwPublicKeyLen)) {
        // Error
        //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
        return 1;
    }





    // Get private key size
    //_tprintf(_T("CryptExportKey...\n"));
    if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPrivateKeyLen)) {
        // Error
        //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
        return 1;
    }
    // Create a buffer for the private key
    //_tprintf(_T("malloc...\n"));
    if (!(pbPrivateKey = (BYTE *)malloc(dwPrivateKeyLen))) {
        // Error
        //_tprintf(_T("malloc error 0x%x\n"), GetLastError());
        return 1;
    }
    // Get private key
    //_tprintf(_T("CryptExportKey...\n"));
    if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pbPrivateKey, &dwPrivateKeyLen)) {
        // Error
        //_tprintf(_T("CryptExportKey error 0x%x\n"), GetLastError());
        return 1;
    }

    /*
    rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, 0, &size);
    LPBYTE pPrivKeyBLOB = (LPBYTE)LocalAlloc(0, size);
    rc = CryptExportKey(hPrivateKey, 0, PRIVATEKEYBLOB, 0, pPrivKeyBLOB, &size);
    */

    /* DER */
    rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, NULL, &dwPrivateKeyLen);

    LPBYTE pPrivateDER = (LPBYTE)LocalAlloc(0, dwPrivateKeyLen);
    rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbPrivateKey, 0, NULL, pPrivateDER, &dwPrivateKeyLen);

    /* PEM */
    DWORD pemPrivateSize = 0;
    rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPrivateSize);

    LPSTR pPrivatePEM = (LPSTR)LocalAlloc(0, pemPrivateSize);
    rc = CryptBinaryToStringA(pPrivateDER, dwPrivateKeyLen, CRYPT_STRING_BASE64HEADER, pPrivatePEM, &pemPrivateSize);

    DWORD  pkiLen = 0;
    LPVOID pki = nullptr;
    rc = CryptExportPublicKeyInfo(hCryptProv, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &pkiLen);

    // allocate memory
    pki = (LPBYTE)LocalAlloc(0, pkiLen);

    rc = CryptExportPublicKeyInfo(hCryptProv, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (PCERT_PUBLIC_KEY_INFO)pki, &pkiLen);

    /* DER */   
    rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pki, 0, NULL, NULL, &pkiLen);

    LPBYTE pPublicDER = (LPBYTE)LocalAlloc(0, dwPublicKeyLen);
    rc = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pki, 0, NULL, pPublicDER, &dwPublicKeyLen);

    /* PEM */
    DWORD pemPublicSize = 0;
    rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, NULL, &pemPublicSize);

    LPSTR pPublicPEM = (LPSTR)LocalAlloc(0, pemPublicSize);
    rc = CryptBinaryToStringA(pPublicDER, dwPublicKeyLen, CRYPT_STRING_BASE64HEADER, pPublicPEM, &pemPublicSize);

    printf("%s", pPrivatePEM);
    printf("%s", pPublicPEM);

    return 0;
}

推荐阅读