c++ - 如何创建用于 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;
}
解决方案
似乎您向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;
}
推荐阅读
- python - 无法打开 CSV 文件
- azure-functions - 具有 AzureWebJobStorage 应用程序设置的多个 Azure 函数,相同的 KeyVault?
- swift - 文本在视图中居中而不是在视图后面
- python - 如何在 Python 中检查在线文本文件中的字符串
- python - Python 常规 MIMEText 电子邮件有效,但 MIMEMultiPart 无效
- image - 通过锁定 gSheet 中的图像运行脚本
- hibernate - 使用桥接表时的 HQL 查询?
- html - 如何在显示 flex 中居中对齐容器的一个子项?
- python - 是否可以从我的 django 项目中创建一个连接到 mysql 数据库的可执行文件?
- c# - 从另一个项目启动项目时,调试时会出现任何问题吗?